From 7597212abced110723f2fee985a7d60557c092ec Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 13 Jan 2011 07:58:56 +0000 Subject: [PATCH] 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 --- include/llvm/MC/MCExpr.h | 4 +- lib/MC/MCExpr.cpp | 8 --- lib/MC/MCObjectStreamer.cpp | 5 +- lib/Target/ARM/ARMCodeEmitter.cpp | 2 +- lib/Target/ARM/ARMInstrInfo.td | 12 ++-- lib/Target/ARM/ARMInstrThumb2.td | 7 ++- lib/Target/ARM/ARMMCCodeEmitter.cpp | 62 +++++++++---------- lib/Target/ARM/ARMMCExpr.cpp | 73 +++++++++++++++++++++++ lib/Target/ARM/ARMMCExpr.h | 73 +++++++++++++++++++++++ lib/Target/ARM/ARMMCInstLower.cpp | 26 +++++--- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 38 +++++------- lib/Target/ARM/CMakeLists.txt | 1 + test/MC/ARM/elf-movt.s | 4 +- test/MC/ARM/hilo-16bit-relocations.s | 21 +++++++ utils/TableGen/EDEmitter.cpp | 2 +- 15 files changed, 248 insertions(+), 90 deletions(-) create mode 100644 lib/Target/ARM/ARMMCExpr.cpp create mode 100644 lib/Target/ARM/ARMMCExpr.h create mode 100644 test/MC/ARM/hilo-16bit-relocations.s diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 49bdfd96cc7..0c9cb396b97 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -155,8 +155,6 @@ public: VK_TPOFF, VK_DTPOFF, VK_TLVP, // Mach-O thread local variable relocation - 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 .w file) // FIXME: We'd really like to use the generic Kinds listed above for these. VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF @@ -421,7 +419,7 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const = 0; - + virtual void AddValueSymbols(MCAssembler *) const = 0; static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 58f2e94dd62..d927df396f0 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -42,10 +42,6 @@ void MCExpr::print(raw_ostream &OS) const { // absolute names. bool UseParens = Sym.getName()[0] == '$'; - if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_HI16 || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_LO16) - OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); - if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_HA16 || SRE.getKind() == MCSymbolRefExpr::VK_PPC_LO16) { OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); @@ -65,8 +61,6 @@ void MCExpr::print(raw_ostream &OS) const { SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF) OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); else if (SRE.getKind() != MCSymbolRefExpr::VK_None && - SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 && - SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16 && SRE.getKind() != MCSymbolRefExpr::VK_PPC_HA16 && SRE.getKind() != MCSymbolRefExpr::VK_PPC_LO16) OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); @@ -196,8 +190,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_TPOFF: return "TPOFF"; case VK_DTPOFF: return "DTPOFF"; case VK_TLVP: return "TLVP"; - case VK_ARM_HI16: return ":upper16:"; - case VK_ARM_LO16: return ":lower16:"; case VK_ARM_PLT: return "(PLT)"; case VK_ARM_GOT: return "(GOT)"; case VK_ARM_GOTOFF: return "(GOTOFF)"; diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index b428e8747b6..ecd7257c70a 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -56,7 +56,10 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { switch (Value->getKind()) { - case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!"); + case MCExpr::Target: + cast(Value)->AddValueSymbols(Assembler); + break; + case MCExpr::Constant: break; diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 38386b81bdb..895ad7322d9 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 91af41ffde6..c615ad9d0f7 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -425,11 +425,11 @@ def imm0_31_m1 : Operand, 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 { - let EncoderMethod = "getMovtImmOpValue"; +def i32imm_hilo16 : Operand { + 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 1a013dee62f..4afe79ae342 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 1c6cdad2b9a..542d24d0558 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 &Fixups) const; - /// getMovtImmOpValue - Return the encoding for the movw/movt pair - uint32_t getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, - SmallVectorImpl &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 &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(E); - case MCExpr::Binary: - return FindLHSymExpr(cast(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 &Fixups) const { +uint32_t +ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &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(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(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 00000000000..2727ba8c8aa --- /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(Value); + AddValueSymbols_(BE->getLHS(), Asm); + AddValueSymbols_(BE->getRHS(), Asm); + break; + } + + case MCExpr::SymbolRef: + Asm->getOrCreateSymbolData(cast(Value)->getSymbol()); + break; + + case MCExpr::Unary: + AddValueSymbols_(cast(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 00000000000..d42f766ca91 --- /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 78bb22e8a5c..4f5b9526956 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 c8ffa267ac1..4e2f9ce41b8 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 &); bool ParseMemory(SmallVectorImpl &); bool ParseOperand(SmallVectorImpl &); - 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 &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 cd376e72a93..38741eb26f2 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 diff --git a/test/MC/ARM/elf-movt.s b/test/MC/ARM/elf-movt.s index 066b2d1baf4..485728def36 100644 --- a/test/MC/ARM/elf-movt.s +++ b/test/MC/ARM/elf-movt.s @@ -11,8 +11,8 @@ barf: @ @barf movw r0, :lower16:GOT-(.LPC0_2+8) movt r0, :upper16:GOT-(.LPC0_2+16) .LPC0_2: -@ ASM: movw r0, :lower16:GOT-(.LPC0_2+8) -@ ASM-NEXT: movt r0, :upper16:GOT-(.LPC0_2+16) +@ ASM: movw r0, :lower16:(GOT-(.LPC0_2+8)) +@ ASM-NEXT: movt r0, :upper16:(GOT-(.LPC0_2+16)) @@ make sure that the text section fixups are sane too @ OBJ: '.text' diff --git a/test/MC/ARM/hilo-16bit-relocations.s b/test/MC/ARM/hilo-16bit-relocations.s new file mode 100644 index 00000000000..46039e5392a --- /dev/null +++ b/test/MC/ARM/hilo-16bit-relocations.s @@ -0,0 +1,21 @@ +@ RUN: llvm-mc %s -triple armv7-apple-darwin -show-encoding | FileCheck %s + +_t: + movw r0, :lower16:(L_foo$non_lazy_ptr - (L1 + 8)) + movt r0, :upper16:(L_foo$non_lazy_ptr - (L1 + 8)) +L1: + +@ CHECK: movw r0, :lower16:(L_foo$non_lazy_ptr-(L1+8)) @ encoding: [A,A,0x00,0xe3] +@ CHECK: @ fixup A - offset: 0, value: L_foo$non_lazy_ptr-(L1+8), kind: fixup_arm_movw_lo16_pcrel +@ CHECK: movt r0, :upper16:(L_foo$non_lazy_ptr-(L1+8)) @ encoding: [A,A,0x40,0xe3] +@ CHECK: @ fixup A - offset: 0, value: L_foo$non_lazy_ptr-(L1+8), kind: fixup_arm_movt_hi16_pcrel + + .comm _foo,4,2 + + .section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers + .align 2 +L_foo$non_lazy_ptr: + .indirect_symbol _foo + .long 0 + +.subsections_via_symbols diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 7ee1019194a..fe97d7385a0 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -564,7 +564,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, REG("QQQQPR"); IMM("i32imm"); - IMM("movt_imm"); + IMM("i32imm_hilo16"); IMM("bf_inv_mask_imm"); IMM("jtblock_operand"); IMM("nohash_imm");