Fix relocation used for GOT references in non-PIC mode. Fix relocations

for "set" pseudo op in PIC mode.

Differential Revision: http://reviews.llvm.org/D13173


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249086 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Joerg Sonnenberger 2015-10-01 22:08:20 +00:00
parent 52c0444e5e
commit fd813994db
2 changed files with 66 additions and 39 deletions

View File

@ -69,6 +69,10 @@ class SparcAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseBranchModifiers(OperandVector &Operands);
// Helper function for dealing with %lo / %hi in PIC mode.
const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK,
const MCExpr *subExpr);
// returns true if Tok is matched to a register and returns register in RegNo.
bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
unsigned &RegKind);
@ -466,8 +470,7 @@ void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
// In either case, start with the 'sethi'.
if (!IsEffectivelyImm13) {
MCInst TmpInst;
const MCExpr *Expr =
SparcMCExpr::create(SparcMCExpr::VK_Sparc_HI, ValExpr, getContext());
const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr);
TmpInst.setLoc(IDLoc);
TmpInst.setOpcode(SP::SETHIi);
TmpInst.addOperand(MCRegOp);
@ -492,8 +495,7 @@ void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
if (IsEffectivelyImm13)
Expr = ValExpr;
else
Expr =
SparcMCExpr::create(SparcMCExpr::VK_Sparc_LO, ValExpr, getContext());
Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr);
TmpInst.setLoc(IDLoc);
TmpInst.setOpcode(SP::ORri);
TmpInst.addOperand(MCRegOp);
@ -1054,6 +1056,32 @@ static bool hasGOTReference(const MCExpr *Expr) {
return false;
}
const SparcMCExpr *
SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK,
const MCExpr *subExpr)
{
// When in PIC mode, "%lo(...)" and "%hi(...)" behave differently.
// If the expression refers contains _GLOBAL_OFFSETE_TABLE, it is
// actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted
// as %got10 or %got22 relocation.
if (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) {
switch(VK) {
default: break;
case SparcMCExpr::VK_Sparc_LO:
VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC10
: SparcMCExpr::VK_Sparc_GOT10);
break;
case SparcMCExpr::VK_Sparc_HI:
VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC22
: SparcMCExpr::VK_Sparc_GOT22);
break;
}
}
return SparcMCExpr::create(VK, subExpr, getContext());
}
bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
SMLoc &EndLoc)
{
@ -1077,30 +1105,7 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
if (Parser.parseParenExpression(subExpr, EndLoc))
return false;
bool isPIC = getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
// Ugly: if a sparc assembly expression says "%hi(...)" but the
// expression within contains _GLOBAL_OFFSET_TABLE_, it REALLY means
// %pc22. Same with %lo -> %pc10. Worse, if it doesn't contain that,
// the meaning depends on whether the assembler was invoked with
// -KPIC or not: if so, it really means %got22/%got10; if not, it
// actually means what it said! Sigh, historical mistakes...
switch(VK) {
default: break;
case SparcMCExpr::VK_Sparc_LO:
VK = (hasGOTReference(subExpr)
? SparcMCExpr::VK_Sparc_PC10
: (isPIC ? SparcMCExpr::VK_Sparc_GOT10 : VK));
break;
case SparcMCExpr::VK_Sparc_HI:
VK = (hasGOTReference(subExpr)
? SparcMCExpr::VK_Sparc_PC22
: (isPIC ? SparcMCExpr::VK_Sparc_GOT22 : VK));
break;
}
EVal = SparcMCExpr::create(VK, subExpr, getContext());
EVal = adjustPICRelocation(VK, subExpr);
return true;
}

View File

@ -1,16 +1,36 @@
! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s
! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck --check-prefix=PIC %s
! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck --check-prefix=NOPIC %s
! CHECK: Relocations [
! CHECK-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC
! CHECK: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 .LC0 0x0
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 .LC0 0x0
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
! CHECK: ]
! PIC: Relocations [
! PIC-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC
! PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 .LC0 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 .LC0 0x0
! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
! PIC: ]
! NOPIC: Relocations [
! NOPIC-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC
! NOPIC: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x4
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x8
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 AGlobalVar 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 AGlobalVar 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 AGlobalVar 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 AGlobalVar 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 .rodata 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 .rodata 0x0
! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0
! NOPIC: ]
.section ".rodata"
.align 8
@ -33,9 +53,11 @@ foo:
sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp6-.Ltmp4)), %i1
.Ltmp5:
or %i1, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp5-.Ltmp4)), %i1
set _GLOBAL_OFFSET_TABLE_, %i1
add %i1, %o7, %i1
sethi %hi(AGlobalVar), %i2
add %i2, %lo(AGlobalVar), %i2
set AGlobalVar, %i2
ldx [%i1+%i2], %i3
ldx [%i3], %i3
sethi %hi(.LC0), %i2