[llvm] r205522 - [mips] Extend MipsMCExpr class to handle %higher(sym1 - sym2 + const) and

Sasa Stankovic Sasa.Stankovic at imgtec.com
Thu Apr 3 03:37:45 PDT 2014


Author: sstankovic
Date: Thu Apr  3 05:37:45 2014
New Revision: 205522

URL: http://llvm.org/viewvc/llvm-project?rev=205522&view=rev
Log:
[mips] Extend MipsMCExpr class to handle %higher(sym1 - sym2 + const) and
%highest(sym1 - sym2 + const) relocations. Remove "ABS_" from VK_Mips_HI
and VK_Mips_LO enums in MipsMCExpr, to be consistent with VK_Mips_HIGHER
and VK_Mips_HIGHEST.

This change also deletes test file test/MC/Mips/higher_highest.ll and moves
its CHECK's to the new test file test/MC/Mips/higher-highest-addressing.s.
The deleted file tests that R_MIPS_HIGHER and R_MIPS_HIGHEST relocations are
emitted in the .o file. Since it uses -force-mips-long-branch option, it was
created when MipsLongBranch's implementation was emitting R_MIPS_HIGHER and
R_MIPS_HIGHEST relocations in the .o file. It was disabled when MipsLongBranch
started to directly calculate offsets.

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

Added:
    llvm/trunk/test/MC/Mips/higher-highest-addressing.s
Removed:
    llvm/trunk/test/MC/Mips/higher_highest.ll
Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h

Modified: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=205522&r1=205521&r2=205522&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Thu Apr  3 05:37:45 2014
@@ -1448,23 +1448,30 @@ const MCExpr *MipsAsmParser::evaluateRel
   const MCExpr *Res;
   // Check the type of the expression.
   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
-    // It's a constant, evaluate lo or hi value.
-    if (RelocStr == "lo") {
-      short Val = MCE->getValue();
-      Res = MCConstantExpr::Create(Val, getContext());
-    } else if (RelocStr == "hi") {
-      int Val = MCE->getValue();
-      int LoSign = Val & 0x8000;
-      Val = (Val & 0xffff0000) >> 16;
-      // Lower part is treated as a signed int, so if it is negative
-      // we must add 1 to the hi part to compensate.
-      if (LoSign)
-        Val++;
-      Res = MCConstantExpr::Create(Val, getContext());
-    } else {
-      llvm_unreachable("Invalid RelocStr value");
+    // It's a constant, evaluate reloc value.
+    int16_t Val;
+    switch (getVariantKind(RelocStr)) {
+    case MCSymbolRefExpr::VK_Mips_ABS_LO:
+      // Get the 1st 16-bits.
+      Val = MCE->getValue() & 0xffff;
+      break;
+    case MCSymbolRefExpr::VK_Mips_ABS_HI:
+      // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
+      // 16 bits being negative.
+      Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
+      break;
+    case MCSymbolRefExpr::VK_Mips_HIGHER:
+      // Get the 3rd 16-bits.
+      Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
+      break;
+    case MCSymbolRefExpr::VK_Mips_HIGHEST:
+      // Get the 4th 16-bits.
+      Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
+      break;
+    default:
+      report_fatal_error("Unsupported reloc value!");
     }
-    return Res;
+    return MCConstantExpr::Create(Val, getContext());
   }
 
   if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
@@ -1478,15 +1485,9 @@ const MCExpr *MipsAsmParser::evaluateRel
   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);

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp?rev=205522&r1=205521&r2=205522&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp Thu Apr  3 05:37:45 2014
@@ -306,11 +306,17 @@ getExprOpValue(const MCExpr *Expr,SmallV
     Mips::Fixups FixupKind = Mips::Fixups(0);
     switch (MipsExpr->getKind()) {
     default: llvm_unreachable("Unsupported fixup kind for target expression!");
-    case MipsMCExpr::VK_Mips_ABS_HI:
+    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_HI:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
                                    : Mips::fixup_Mips_HI16;
       break;
-    case MipsMCExpr::VK_Mips_ABS_LO:
+    case MipsMCExpr::VK_Mips_LO:
       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
                                    : Mips::fixup_Mips_LO16;
       break;

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp?rev=205522&r1=205521&r2=205522&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp Thu Apr  3 05:37:45 2014
@@ -15,17 +15,60 @@
 
 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 = cast<MCBinaryExpr>(BE->getLHS());
+  }
+  return (isa<MCSymbolRefExpr>(BE->getLHS())
+          && isa<MCSymbolRefExpr>(BE->getRHS()));
+}
+
 const MipsMCExpr*
-MipsMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
+MipsMCExpr::Create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr,
                    MCContext &Ctx) {
+  VariantKind Kind;
+  switch (VK) {
+  case MCSymbolRefExpr::VK_Mips_ABS_LO:
+    Kind = VK_Mips_LO;
+    break;
+  case MCSymbolRefExpr::VK_Mips_ABS_HI:
+    Kind = VK_Mips_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_LO: OS << "%lo"; break;
+  case VK_Mips_HI: OS << "%hi"; break;
+  case VK_Mips_HIGHER: OS << "%higher"; break;
+  case VK_Mips_HIGHEST: OS << "%highest"; break;
   }
 
   OS << '(';

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h?rev=205522&r1=205521&r2=205522&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h Thu Apr  3 05:37:45 2014
@@ -20,8 +20,10 @@ class MipsMCExpr : public MCTargetExpr {
 public:
   enum VariantKind {
     VK_Mips_None,
-    VK_Mips_ABS_LO,
-    VK_Mips_ABS_HI
+    VK_Mips_LO,
+    VK_Mips_HI,
+    VK_Mips_HIGHER,
+    VK_Mips_HIGHEST
   };
 
 private:
@@ -32,16 +34,11 @@ private:
     : Kind(Kind), Expr(Expr) {}
 
 public:
-  static const MipsMCExpr *Create(VariantKind Kind, const MCExpr *Expr,
-                                  MCContext &Ctx);
+  static bool isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
+                                    const MCBinaryExpr *BE);
 
-  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; }

Added: llvm/trunk/test/MC/Mips/higher-highest-addressing.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/higher-highest-addressing.s?rev=205522&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/higher-highest-addressing.s (added)
+++ llvm/trunk/test/MC/Mips/higher-highest-addressing.s Thu Apr  3 05:37:45 2014
@@ -0,0 +1,54 @@
+# 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 that R_MIPS_HIGHER and R_MIPS_HIGHEST relocations are created.  By using
+# NEXT we also test that none of the expressions from the test2 generates
+# relocations.
+
+test1:
+# CHECK-LABEL:    test1:
+
+        lui     $5, %highest(func)
+        daddiu  $5, $5, %higher(func)
+
+# CHECK-REL:           Relocations [
+# CHECK-REL-NEXT:      {
+# CHECK-REL-NEXT:          0x{{[0-9,A-F]+}} R_MIPS_HIGHEST
+# CHECK-REL-NEXT:          0x{{[0-9,A-F]+}} R_MIPS_HIGHER
+# CHECK-REL-NEXT:      }
+
+
+# Test the calculation of %higher and %highest:
+# ((x + 0x80008000) >> 32) & 0xffff (higher)
+# ((x + 0x800080008000) >> 48) & 0xffff (highest).
+
+test2:
+# CHECK-LABEL:    test2:
+
+# 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)
+$L2:
+# CHECK:    lui      $6, 3
+# CHECK:    daddiu   $6, $6, 4
+
+
+# Check the case where %higher is modified by adding +1.
+        lui     $7, %highest($L2-$L1+0x300047FFF7FF8)
+        ld      $7, %higher ($L2-$L1+0x300047FFF7FF8)($7)
+# CHECK:    lui     $7, 3
+# CHECK:    ld      $7, 5($7)
+
+
+# Check the case where both %higher and %highest are modified by adding +1.
+        lui     $8, %highest(0x37FFF7FFF8000)
+        ld      $8, %higher (0x37FFF7FFF8000)($8)
+# CHECK:    lui     $8, 4
+# CHECK:    ld      $8, -32768($8)

Removed: llvm/trunk/test/MC/Mips/higher_highest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/higher_highest.ll?rev=205521&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/higher_highest.ll (original)
+++ llvm/trunk/test/MC/Mips/higher_highest.ll (removed)
@@ -1,32 +0,0 @@
-; DISABLE: llc -march=mips64el -mcpu=mips64 -mattr=n64  -force-mips-long-branch -filetype=obj < %s -o - | llvm-readobj -r | FileCheck %s
-; RUN: false
-; XFAIL: *
-; Disabled because currently we don't have a way to generate these relocations.
-;
-; Check that the R_MIPS_HIGHER and R_MIPS_HIGHEST relocations were created.
-
-; CHECK: Relocations [
-; CHECK:     0x{{[0-9,A-F]+}} R_MIPS_HIGHEST
-; CHECK:     0x{{[0-9,A-F]+}} R_MIPS_HIGHEST
-; CHECK:     0x{{[0-9,A-F]+}} R_MIPS_HIGHER
-; CHECK:     0x{{[0-9,A-F]+}} R_MIPS_HIGHER
-; CHECK: ]
-
- at g0 = external global i32
-
-define void @foo1(i32 %s) nounwind {
-entry:
-
-  %tobool = icmp eq i32 %s, 0
-  br i1 %tobool, label %if.end, label %if.then
-
-if.then:                                          ; preds = %entry
-  %0 = load i32* @g0, align 4
-  %add = add nsw i32 %0, 12
-  store i32 %add, i32* @g0, align 4
-  br label %if.end
-
-if.end:                                           ; preds = %entry, %if.then
-  ret void
-}
-





More information about the llvm-commits mailing list