summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
diff options
context:
space:
mode:
authorSasa Stankovic <Sasa.Stankovic@imgtec.com>2014-04-03 10:37:45 +0000
committerSasa Stankovic <Sasa.Stankovic@imgtec.com>2014-04-03 10:37:45 +0000
commit06c4780311df28e9f230889fc04f63f5acb795d6 (patch)
treef92bf3999cd0851a546b707cc139c4f4ec2c7942 /llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
parent3ba640d7aef9fb3f9be143853a48d44053f0b5f3 (diff)
downloadbcm5719-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/MCTargetDesc/MipsMCExpr.cpp')
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp49
1 files changed, 46 insertions, 3 deletions
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 << '(';
OpenPOWER on IntegriCloud