[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