diff options
author | Sasa Stankovic <Sasa.Stankovic@imgtec.com> | 2014-04-03 10:37:45 +0000 |
---|---|---|
committer | Sasa Stankovic <Sasa.Stankovic@imgtec.com> | 2014-04-03 10:37:45 +0000 |
commit | 06c4780311df28e9f230889fc04f63f5acb795d6 (patch) | |
tree | f92bf3999cd0851a546b707cc139c4f4ec2c7942 /llvm/lib/Target/Mips | |
parent | 3ba640d7aef9fb3f9be143853a48d44053f0b5f3 (diff) | |
download | bcm5719-llvm-06c4780311df28e9f230889fc04f63f5acb795d6.tar.gz bcm5719-llvm-06c4780311df28e9f230889fc04f63f5acb795d6.zip |
[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
llvm-svn: 205522
Diffstat (limited to 'llvm/lib/Target/Mips')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 51 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h | 19 |
4 files changed, 88 insertions, 41 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 736c910e45a..911a1190437 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1448,23 +1448,30 @@ const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, 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::evaluateRelocExpr(const MCExpr *Expr, 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); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 6730bedb9f5..edd21469d2e 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -306,11 +306,17 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, 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; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 22ce41100a0..c7ba12d0417 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -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 << '('; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h index 0ec17554c0b..722bba71e9b 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h @@ -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; } |