[PATCH] Extend MipsMCExpr class to handle %higher(sym1 - sym2 + const) and %highest(sym1 - sym2 + const) relocations.

Sasa Stankovic Sasa.Stankovic at imgtec.com
Mon Mar 31 11:01:09 PDT 2014


Hi mseaborn,

[mips] Extend MipsMCExpr class to handle %higher(sym1 - sym2 + const) and %highest(sym1 - sym2 + const) relocations.

http://llvm-reviews.chandlerc.com/D3230

Files:
  lib/Target/Mips/AsmParser/MipsAsmParser.cpp
  lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
  lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
  lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
  test/MC/Mips/higher-highest.s

Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp
===================================================================
--- lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -1406,15 +1406,9 @@
   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
     MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
 
-    // Check for %hi(sym1-sym2) and %lo(sym1-sym2) expressions.
-    if (isa<MCSymbolRefExpr>(BE->getLHS()) && isa<MCSymbolRefExpr>(BE->getRHS())
-        && (VK == MCSymbolRefExpr::VK_Mips_ABS_HI
-            || VK == MCSymbolRefExpr::VK_Mips_ABS_LO)) {
-      // Create target expression for %hi(sym1-sym2) and %lo(sym1-sym2).
-      if (VK == MCSymbolRefExpr::VK_Mips_ABS_HI)
-        return MipsMCExpr::CreateHi(Expr, getContext());
-      return MipsMCExpr::CreateLo(Expr, getContext());
-    }
+    // Try to create target expression.
+    if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
+      return MipsMCExpr::Create(VK, Expr, getContext());
 
     const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
     const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -306,6 +306,12 @@
     Mips::Fixups FixupKind = Mips::Fixups(0);
     switch (MipsExpr->getKind()) {
     default: llvm_unreachable("Unsupported fixup kind for target expression!");
+    case MipsMCExpr::VK_Mips_HIGHEST:
+      FixupKind = Mips::fixup_Mips_HIGHEST;
+      break;
+    case MipsMCExpr::VK_Mips_HIGHER:
+      FixupKind = Mips::fixup_Mips_HIGHER;
+      break;
     case MipsMCExpr::VK_Mips_ABS_HI:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
                                    : Mips::fixup_Mips_HI16;
Index: lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
@@ -15,17 +15,66 @@
 
 using namespace llvm;
 
+bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
+                                       const MCBinaryExpr *BE) {
+  switch (VK) {
+  case MCSymbolRefExpr::VK_Mips_ABS_LO:
+  case MCSymbolRefExpr::VK_Mips_ABS_HI:
+  case MCSymbolRefExpr::VK_Mips_HIGHER:
+  case MCSymbolRefExpr::VK_Mips_HIGHEST:
+    break;
+  default:
+    return false;
+  }
+
+  // We support expressions of the form "sym1 binop1 sym2 binop2 const",
+  // where "binop2 const" is optional.
+  if (isa<MCBinaryExpr>(BE->getLHS())) {
+    if (!isa<MCConstantExpr>(BE->getRHS()))
+      return false;
+    BE = dyn_cast<MCBinaryExpr>(BE->getLHS());
+  }
+  return (isa<MCSymbolRefExpr>(BE->getLHS())
+          && isa<MCSymbolRefExpr>(BE->getRHS()));
+}
+
 const MipsMCExpr*
 MipsMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
                    MCContext &Ctx) {
   return new (Ctx) MipsMCExpr(Kind, Expr);
 }
 
+const MipsMCExpr*
+MipsMCExpr::Create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr,
+                   MCContext &Ctx) {
+  VariantKind Kind;
+  switch (VK) {
+  case MCSymbolRefExpr::VK_Mips_ABS_LO:
+    Kind = VK_Mips_ABS_LO;
+    break;
+  case MCSymbolRefExpr::VK_Mips_ABS_HI:
+    Kind = VK_Mips_ABS_HI;
+    break;
+  case MCSymbolRefExpr::VK_Mips_HIGHER:
+    Kind = VK_Mips_HIGHER;
+    break;
+  case MCSymbolRefExpr::VK_Mips_HIGHEST:
+    Kind = VK_Mips_HIGHEST;
+    break;
+  default:
+    llvm_unreachable("Invalid kind!");
+  }
+
+  return new (Ctx) MipsMCExpr(Kind, Expr);
+}
+
 void MipsMCExpr::PrintImpl(raw_ostream &OS) const {
   switch (Kind) {
   default: llvm_unreachable("Invalid kind!");
   case VK_Mips_ABS_LO: OS << "%lo"; break;
   case VK_Mips_ABS_HI: OS << "%hi"; break;
+  case VK_Mips_HIGHER: OS << "%higher"; break;
+  case VK_Mips_HIGHEST: OS << "%highest"; break;
   }
 
   OS << '(';
Index: lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
+++ lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
@@ -21,7 +21,9 @@
   enum VariantKind {
     VK_Mips_None,
     VK_Mips_ABS_LO,
-    VK_Mips_ABS_HI
+    VK_Mips_ABS_HI,
+    VK_Mips_HIGHER,
+    VK_Mips_HIGHEST
   };
 
 private:
@@ -32,16 +34,14 @@
     : Kind(Kind), Expr(Expr) {}
 
 public:
+  static bool isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
+                                    const MCBinaryExpr *BE);
+
   static const MipsMCExpr *Create(VariantKind Kind, const MCExpr *Expr,
                                   MCContext &Ctx);
 
-  static const MipsMCExpr *CreateLo(const MCExpr *Expr, MCContext &Ctx) {
-    return Create(VK_Mips_ABS_LO, Expr, Ctx);
-  }
-
-  static const MipsMCExpr *CreateHi(const MCExpr *Expr, MCContext &Ctx) {
-    return Create(VK_Mips_ABS_HI, Expr, Ctx);
-  }
+  static const MipsMCExpr *Create(MCSymbolRefExpr::VariantKind VK,
+                                  const MCExpr *Expr, MCContext &Ctx);
 
   /// getOpcode - Get the kind of this expression.
   VariantKind getKind() const { return Kind; }
Index: test/MC/Mips/higher-highest.s
===================================================================
--- /dev/null
+++ test/MC/Mips/higher-highest.s
@@ -0,0 +1,44 @@
+# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux -mcpu=mips64r2 %s \
+# RUN:  | llvm-objdump -disassemble -triple mips64el - | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux -mcpu=mips64r2 %s \
+# RUN:  | llvm-readobj -r | FileCheck %s -check-prefix=CHECK-REL
+
+
+# Test the %higher and %highest relocations on difference of two labels.
+# They are computed using the expressions
+# ((x + 0x80008000) >> 32) & 0xffff (higher) and
+# ((x + 0x800080008000) >> 48) & 0xffff (highest).
+
+
+# Check the case where relocations are not modified by adding +1.  The constant
+# is chosen so that it is just below the value that triggers the addition of +1
+# to %higher.
+$L1:
+        lui     $6,    %highest($L2-$L1+0x300047FFF7FF7)
+        daddiu  $6, $6, %higher($L2-$L1+0x300047FFF7FF7)
+# CHECK:    lui      $6, 3
+# CHECK:    daddiu   $6, $6, 4
+
+
+# Check the case where %higher is modified by adding +1.
+$L2:
+        lui     $7, %highest($L3-$L2+0x300047FFF7FF8)
+        ld      $7, %higher ($L3-$L2+0x300047FFF7FF8)($7)
+# CHECK:    lui     $7, 3
+# CHECK:    ld      $7, 5($7)
+
+
+# Check the case where both %higher and %highest are modified by adding +1.
+$L3:
+        lui     $8, %highest($L4-$L3+0x37FFF7FFF7FF8)
+        ld      $8, %higher ($L4-$L3+0x37FFF7FFF7FF8)($8)
+# CHECK:    lui     $8, 4
+# CHECK:    ld      $8, -32768($8)
+$L4:
+
+
+# Check that relocation is not emitted for %highest(label1 - label2 + const) and
+# %higher(label1 - label2 + const) expressions.
+
+# CHECK-REL-NOT:    R_MIPS
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3230.1.patch
Type: text/x-patch
Size: 6987 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140331/c4755f8c/attachment.bin>


More information about the llvm-commits mailing list