Model :upper16: and :lower16: as ARM specific MCTargetExpr. This is a step
authorEvan Cheng <evan.cheng@apple.com>
Thu, 13 Jan 2011 07:58:56 +0000 (07:58 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 13 Jan 2011 07:58:56 +0000 (07:58 +0000)
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

15 files changed:
include/llvm/MC/MCExpr.h
lib/MC/MCExpr.cpp
lib/MC/MCObjectStreamer.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
lib/Target/ARM/ARMMCExpr.cpp [new file with mode: 0644]
lib/Target/ARM/ARMMCExpr.h [new file with mode: 0644]
lib/Target/ARM/ARMMCInstLower.cpp
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/CMakeLists.txt
test/MC/ARM/elf-movt.s
test/MC/ARM/hilo-16bit-relocations.s [new file with mode: 0644]
utils/TableGen/EDEmitter.cpp

index 49bdfd96cc7314af01e7ff0174f0dbf2d619e06d..0c9cb396b9707ec186faa36195cb130286dae547 100644 (file)
@@ -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;
index 58f2e94dd6263b687dac9df66fc2d40a76cbdd13..d927df396f08c943e16c8385191e1fc192be03b4 100644 (file)
@@ -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)";
index b428e8747b61c45a6a909e02643feb997125a2c2..ecd7257c70a096ec232025b47d6bb208b49a5031 100644 (file)
@@ -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<MCTargetExpr>(Value)->AddValueSymbols(Assembler);
+    break;
+
   case MCExpr::Constant:
     break;
 
index 38386b81bdb0e8189faafad99774bce801de3fbc..895ad7322d9ffc07e715119bff929532b48d105a 100644 (file)
@@ -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;
     }
 
index 91af41ffde647b134d6e8b71121436fe2ce07fce..c615ad9d0f718901c73106f7a68c1c930b0ca346 100644 (file)
@@ -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",
                  []>,
index 1a013dee62f37407b9cd74a2f7456ca0b21ccbe2..4afe79ae3420af4053d0ffb6aae5ead9e2bedbbb 100644 (file)
@@ -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"> {
index 1c6cdad2b9ac05fd7eaeef9dfd5439f71cab5e31..542d24d055816fc741ed6e01d5088c2be938b938 100644 (file)
@@ -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 (file)
index 0000000..2727ba8
--- /dev/null
@@ -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 (file)
index 0000000..d42f766
--- /dev/null
@@ -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
index 78bb22e8a5ced0ab5cebaf470a6341b462327c2f..4f5b952695631cca5bf69f2a81a2d7275bb124be 100644 (file)
@@ -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;
index c8ffa267ac1a51ceb2117c2666b9ec6d13de0a64..4e2f9ce41b893443ecffb7e857c5a6e2b85c812f 100644 (file)
@@ -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;
index cd376e72a93fad92d4c7ed244f63ccae2abf398b..38741eb26f23656044a25d8a3598edd98f7414a2 100644 (file)
@@ -35,6 +35,7 @@ add_llvm_target(ARMCodeGen
   ARMInstrInfo.cpp
   ARMJITInfo.cpp
   ARMMCCodeEmitter.cpp
+  ARMMCExpr.cpp
   ARMLoadStoreOptimizer.cpp
   ARMMCAsmInfo.cpp
   ARMMCInstLower.cpp
index 066b2d1baf4c362a40f95b99148897d3dcc88cb4..485728def36d96e3acf335786e652002ccd43b32 100644 (file)
@@ -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 (file)
index 0000000..46039e5
--- /dev/null
@@ -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
index 7ee1019194ac6bea06c556fe36eaa03bce0b1619..fe97d7385a0fe8eb07229809c1d1c7485bbbb9af 100644 (file)
@@ -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");