[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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205522 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sasa Stankovic
2014-04-03 10:37:45 +00:00
parent 107283d7cb
commit 10914379f6
6 changed files with 142 additions and 73 deletions

View File

@@ -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);