diff options
author | Evan Cheng <evan.cheng@apple.com> | 2011-01-13 07:58:56 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2011-01-13 07:58:56 +0000 |
commit | 7597212abced110723f2fee985a7d60557c092ec (patch) | |
tree | 5e01be3847a6ec23112b8feb910ac5a2bb6b2fcb /lib/Target | |
parent | 04f5079ca1fd6c46a2b2efc369e293fb6feab793 (diff) |
Model :upper16: and :lower16: as ARM specific MCTargetExpr. This is a step
in the right direction. It eliminated some hacks and will unblock codegen
work. But it's far from being done. It doesn't reject illegal expressions,
e.g. (FOO - :lower16:BAR). It also doesn't work in Thumb2 mode at all.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123369 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 12 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 7 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 62 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCExpr.cpp | 73 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCExpr.h | 73 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCInstLower.cpp | 26 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 38 | ||||
-rw-r--r-- | lib/Target/ARM/CMakeLists.txt | 1 |
9 files changed, 219 insertions, 75 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 38386b81bd..895ad7322d 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -251,7 +251,7 @@ namespace { return Binary; } - unsigned getMovtImmOpValue(const MachineInstr &MI, unsigned Op) const { + unsigned getHiLo16ImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 91af41ffde..c615ad9d0f 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -425,11 +425,11 @@ def imm0_31_m1 : Operand<i32>, PatLeaf<(imm), [{ let EncoderMethod = "getImmMinusOneOpValue"; } -// For movt/movw - sets the MC Encoder method. +// i32imm_hilo16 - For movt/movw - sets the MC Encoder method. // The imm is split into imm{15-12}, imm{11-0} // -def movt_imm : Operand<i32> { - let EncoderMethod = "getMovtImmOpValue"; +def i32imm_hilo16 : Operand<i32> { + let EncoderMethod = "getHiLo16ImmOpValue"; } /// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield @@ -1907,7 +1907,7 @@ def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi, } let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in -def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins movt_imm:$imm), +def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm_hilo16:$imm), DPFrm, IIC_iMOVi, "movw", "\t$Rd, $imm", [(set GPR:$Rd, imm0_65535:$imm)]>, @@ -1922,7 +1922,7 @@ def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins movt_imm:$imm), } let Constraints = "$src = $Rd" in -def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, movt_imm:$imm), +def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm), DPFrm, IIC_iMOVi, "movt", "\t$Rd, $imm", [(set GPR:$Rd, @@ -3050,7 +3050,7 @@ def MOVCCs : AI1<0b1101, (outs GPR:$Rd), } let isMoveImm = 1 in -def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, movt_imm:$imm), +def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm_hilo16:$imm), DPFrm, IIC_iMOVi, "movw", "\t$Rd, $imm", []>, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 1a013dee62..4afe79ae34 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -1677,7 +1677,7 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi, } let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in -def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm:$imm), IIC_iMOVi, +def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi, "movw", "\t$Rd, $imm", [(set rGPR:$Rd, imm0_65535:$imm)]> { let Inst{31-27} = 0b11110; @@ -1697,7 +1697,8 @@ def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm:$imm), IIC_iMOVi, } let Constraints = "$src = $Rd" in -def t2MOVTi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$src, i32imm:$imm), IIC_iMOVi, +def t2MOVTi16 : T2I<(outs rGPR:$Rd), + (ins rGPR:$src, i32imm_hilo16:$imm), IIC_iMOVi, "movt", "\t$Rd, $imm", [(set rGPR:$Rd, (or (and rGPR:$src, 0xffff), lo16AllZero:$imm))]> { @@ -2684,7 +2685,7 @@ def t2MOVCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), } let isMoveImm = 1 in -def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm:$imm), +def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm_hilo16:$imm), IIC_iCMOVi, "movw", "\t$Rd, $imm", []>, RegConstraint<"$false = $Rd"> { diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 1c6cdad2b9..542d24d055 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -16,6 +16,7 @@ #include "ARMAddressingModes.h" #include "ARMFixupKinds.h" #include "ARMInstrInfo.h" +#include "ARMMCExpr.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -53,9 +54,11 @@ public: unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups) const; - /// getMovtImmOpValue - Return the encoding for the movw/movt pair - uint32_t getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const; + /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of + /// the specified operand. This is used for operands with :lower16: and + /// :upper16: prefixes. + uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const; bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, unsigned &Imm, @@ -626,19 +629,6 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, return Binary; } -// FIXME: This routine needs to handle more MCExpr types -static const MCSymbolRefExpr *FindLHSymExpr(const MCExpr *E) { - // recurse left child until finding a MCSymbolRefExpr - switch (E->getKind()) { - case MCExpr::SymbolRef: - return cast<MCSymbolRefExpr>(E); - case MCExpr::Binary: - return FindLHSymExpr(cast<MCBinaryExpr>(E)->getLHS()); - default: - return NULL; - } -} - // FIXME: This routine assumes that a binary // expression will always result in a PCRel expression // In reality, its only true if one or more subexpressions @@ -652,38 +642,40 @@ static bool EvaluateAsPCRel(const MCExpr *Expr) { } } -uint32_t ARMMCCodeEmitter:: -getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl<MCFixup> &Fixups) const { +uint32_t +ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl<MCFixup> &Fixups) const { // {20-16} = imm{15-12} // {11-0} = imm{11-0} const MCOperand &MO = MI.getOperand(OpIdx); - if (MO.isImm()) { + if (MO.isImm()) + // Hi / lo 16 bits already extracted during earlier passes. return static_cast<unsigned>(MO.getImm()); - } else if (const MCSymbolRefExpr *Expr = - FindLHSymExpr(MO.getExpr())) { - // FIXME: :lower16: and :upper16: should be applicable to - // to whole expression, not just symbolrefs - // Until that change takes place, this hack is required to - // generate working code. - const MCExpr *OrigExpr = MO.getExpr(); + + // Handle :upper16: and :lower16: assembly prefixes. + const MCExpr *E = MO.getExpr(); + if (E->getKind() == MCExpr::Target) { + const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E); + E = ARM16Expr->getSubExpr(); + MCFixupKind Kind; - switch (Expr->getKind()) { + switch (ARM16Expr->getKind()) { default: assert(0 && "Unsupported ARMFixup"); - case MCSymbolRefExpr::VK_ARM_HI16: + case ARMMCExpr::VK_ARM_HI16: Kind = MCFixupKind(ARM::fixup_arm_movt_hi16); - if (EvaluateAsPCRel(OrigExpr)) + if (EvaluateAsPCRel(E)) Kind = MCFixupKind(ARM::fixup_arm_movt_hi16_pcrel); break; - case MCSymbolRefExpr::VK_ARM_LO16: + case ARMMCExpr::VK_ARM_LO16: Kind = MCFixupKind(ARM::fixup_arm_movw_lo16); - if (EvaluateAsPCRel(OrigExpr)) + if (EvaluateAsPCRel(E)) Kind = MCFixupKind(ARM::fixup_arm_movw_lo16_pcrel); break; } - Fixups.push_back(MCFixup::Create(0, OrigExpr, Kind)); + Fixups.push_back(MCFixup::Create(0, E, Kind)); return 0; }; + llvm_unreachable("Unsupported MCExpr type in MCOperand!"); return 0; } @@ -1173,8 +1165,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, case ARMII::Size4Bytes: Size = 4; break; } uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); - // Thumb 32-bit wide instructions need to be have the high order halfword - // emitted first. + // Thumb 32-bit wide instructions need to emit the high order halfword + // first. if (Subtarget.isThumb() && Size == 4) { EmitConstant(Binary >> 16, 2, OS); EmitConstant(Binary & 0xffff, 2, OS); diff --git a/lib/Target/ARM/ARMMCExpr.cpp b/lib/Target/ARM/ARMMCExpr.cpp new file mode 100644 index 0000000000..2727ba8c8a --- /dev/null +++ b/lib/Target/ARM/ARMMCExpr.cpp @@ -0,0 +1,73 @@ +//===-- ARMMCExpr.cpp - ARM specific MC expression classes ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "armmcexpr" +#include "ARMMCExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAssembler.h" +using namespace llvm; + +const ARMMCExpr* +ARMMCExpr::Create(VariantKind Kind, const MCExpr *Expr, + MCContext &Ctx) { + return new (Ctx) ARMMCExpr(Kind, Expr); +} + +void ARMMCExpr::PrintImpl(raw_ostream &OS) const { + switch (Kind) { + default: assert(0 && "Invalid kind!"); + case VK_ARM_HI16: OS << ":upper16:"; break; + case VK_ARM_LO16: OS << ":lower16:"; break; + } + + const MCExpr *Expr = getSubExpr(); + if (Expr->getKind() != MCExpr::SymbolRef) + OS << '('; + Expr->print(OS); + if (Expr->getKind() != MCExpr::SymbolRef) + OS << ')'; +} + +bool +ARMMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { + return false; +} + +// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps +// that method should be made public? +static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) { + switch (Value->getKind()) { + case MCExpr::Target: + assert(0 && "Can't handle nested target expr!"); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); + AddValueSymbols_(BE->getLHS(), Asm); + AddValueSymbols_(BE->getRHS(), Asm); + break; + } + + case MCExpr::SymbolRef: + Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); + break; + + case MCExpr::Unary: + AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm); + break; + } +} + +void ARMMCExpr::AddValueSymbols(MCAssembler *Asm) const { + AddValueSymbols_(getSubExpr(), Asm); +} diff --git a/lib/Target/ARM/ARMMCExpr.h b/lib/Target/ARM/ARMMCExpr.h new file mode 100644 index 0000000000..d42f766ca9 --- /dev/null +++ b/lib/Target/ARM/ARMMCExpr.h @@ -0,0 +1,73 @@ +//===-- ARMMCExpr.h - ARM specific MC expression classes ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMMCEXPR_H +#define ARMMCEXPR_H + +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +class ARMMCExpr : public MCTargetExpr { +public: + enum VariantKind { + VK_ARM_None, + VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file) + VK_ARM_LO16 // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .s file) + }; + +private: + const VariantKind Kind; + const MCExpr *Expr; + + explicit ARMMCExpr(VariantKind _Kind, const MCExpr *_Expr) + : Kind(_Kind), Expr(_Expr) {} + +public: + /// @name Construction + /// @{ + + static const ARMMCExpr *Create(VariantKind Kind, const MCExpr *Expr, + MCContext &Ctx); + + static const ARMMCExpr *CreateUpper16(const MCExpr *Expr, MCContext &Ctx) { + return Create(VK_ARM_HI16, Expr, Ctx); + } + + static const ARMMCExpr *CreateLower16(const MCExpr *Expr, MCContext &Ctx) { + return Create(VK_ARM_LO16, Expr, Ctx); + } + + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this expression. + VariantKind getKind() const { return Kind; } + + /// getSubExpr - Get the child of this expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// @} + + void PrintImpl(raw_ostream &OS) const; + bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const; + void AddValueSymbols(MCAssembler *) const; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + + static bool classof(const ARMMCExpr *) { return true; } + +}; +} // end namespace llvm + +#endif diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp index 78bb22e8a5..4f5b952695 100644 --- a/lib/Target/ARM/ARMMCInstLower.cpp +++ b/lib/Target/ARM/ARMMCInstLower.cpp @@ -14,6 +14,7 @@ #include "ARM.h" #include "ARMAsmPrinter.h" +#include "ARMMCExpr.h" #include "llvm/Constants.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/MC/MCExpr.h" @@ -27,16 +28,25 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, MCContext &Ctx = Printer.OutContext; const MCExpr *Expr; switch (MO.getTargetFlags()) { - default: assert(0 && "Unknown target flag on symbol operand"); - case 0: + default: { Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); + switch (MO.getTargetFlags()) { + default: + assert(0 && "Unknown target flag on symbol operand"); + case 0: + break; + case ARMII::MO_LO16: + Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); + Expr = ARMMCExpr::CreateLower16(Expr, Ctx); + break; + case ARMII::MO_HI16: + Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); + Expr = ARMMCExpr::CreateUpper16(Expr, Ctx); + break; + } break; - case ARMII::MO_LO16: - Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_LO16, Ctx); - break; - case ARMII::MO_HI16: - Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx); - break; + } + case ARMII::MO_PLT: Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx); break; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c8ffa267ac..4e2f9ce41b 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -9,6 +9,7 @@ #include "ARM.h" #include "ARMAddressingModes.h" +#include "ARMMCExpr.h" #include "ARMBaseRegisterInfo.h" #include "ARMSubtarget.h" #include "llvm/MC/MCParser/MCAsmLexer.h" @@ -55,7 +56,7 @@ class ARMAsmParser : public TargetAsmParser { bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &); - bool ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind); + bool ParsePrefix(ARMMCExpr::VariantKind &RefKind); const MCExpr *ApplyPrefixToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant); @@ -870,36 +871,29 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands){ return false; case AsmToken::Colon: { // ":lower16:" and ":upper16:" expression prefixes - MCSymbolRefExpr::VariantKind RefKind; + // FIXME: Check it's an expression prefix, + // e.g. (FOO - :lower16:BAR) isn't legal. + ARMMCExpr::VariantKind RefKind; if (ParsePrefix(RefKind)) return true; - const MCExpr *ExprVal; - if (getParser().ParseExpression(ExprVal)) + const MCExpr *SubExprVal; + if (getParser().ParseExpression(SubExprVal)) return true; - // TODO: Attach the prefix to the entire expression - // instead of just the first symbol. - const MCExpr *ModExprVal = ApplyPrefixToExpr(ExprVal, RefKind); - if (!ModExprVal) { - return TokError("invalid modifier '" + getTok().getIdentifier() + - "' (no symbols present)"); - } - + const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal, + getContext()); E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(ModExprVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); return false; } } } -// FIXME: The next 2 routines are hacks to get ARMAsmParser to understand -// :lower16: and :upper16: -// It still attaches VK_ARM_HI/LO16 to MCSymbolRefExpr, but it really -// should be attached to the entire MCExpr as a whole - perhaps using -// MCTargetExpr? -bool ARMAsmParser::ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind) { - RefKind = MCSymbolRefExpr::VK_None; +// ParsePrefix - Parse ARM 16-bit relocations expression prefix, i.e. +// :lower16: and :upper16:. +bool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) { + RefKind = ARMMCExpr::VK_ARM_None; // :lower16: and :upper16: modifiers assert(getLexer().is(AsmToken::Colon) && "expected a :"); @@ -912,9 +906,9 @@ bool ARMAsmParser::ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind) { StringRef IDVal = Parser.getTok().getIdentifier(); if (IDVal == "lower16") { - RefKind = MCSymbolRefExpr::VK_ARM_LO16; + RefKind = ARMMCExpr::VK_ARM_LO16; } else if (IDVal == "upper16") { - RefKind = MCSymbolRefExpr::VK_ARM_HI16; + RefKind = ARMMCExpr::VK_ARM_HI16; } else { Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); return true; diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index cd376e72a9..38741eb26f 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -35,6 +35,7 @@ add_llvm_target(ARMCodeGen ARMInstrInfo.cpp ARMJITInfo.cpp ARMMCCodeEmitter.cpp + ARMMCExpr.cpp ARMLoadStoreOptimizer.cpp ARMMCAsmInfo.cpp ARMMCInstLower.cpp |