mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
[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:
parent
107283d7cb
commit
10914379f6
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 << '(';
|
||||
|
@ -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; }
|
||||
|
54
test/MC/Mips/higher-highest-addressing.s
Normal file
54
test/MC/Mips/higher-highest-addressing.s
Normal file
@ -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)
|
@ -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: ]
|
||||
|
||||
@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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user