Skip to content

Commit 9fc2909

Browse files
committed
[Sparc] Teach SparcAsmParser to emit correct relocations for PIC code.
llvm-svn: 202571
1 parent 552d9e4 commit 9fc2909

File tree

3 files changed

+104
-3
lines changed

3 files changed

+104
-3
lines changed

llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
#include "llvm/ADT/STLExtras.h"
1313
#include "llvm/MC/MCContext.h"
1414
#include "llvm/MC/MCInst.h"
15+
#include "llvm/MC/MCObjectFileInfo.h"
1516
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
1617
#include "llvm/MC/MCStreamer.h"
1718
#include "llvm/MC/MCSubtargetInfo.h"
19+
#include "llvm/MC/MCSymbol.h"
1820
#include "llvm/MC/MCTargetAsmParser.h"
1921
#include "llvm/Support/TargetRegistry.h"
2022

@@ -66,7 +68,7 @@ class SparcAsmParser : public MCTargetAsmParser {
6668
StringRef Name);
6769

6870
OperandMatchResultTy
69-
parseSparcAsmOperand(SparcOperand *&Operand);
71+
parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false);
7072

7173
// returns true if Tok is matched to a register and returns register in RegNo.
7274
bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
@@ -623,7 +625,7 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
623625
}
624626

625627
SparcOperand *Op = 0;
626-
ResTy = parseSparcAsmOperand(Op);
628+
ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call"));
627629
if (ResTy != MatchOperand_Success || !Op)
628630
return MatchOperand_ParseFail;
629631

@@ -634,7 +636,7 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
634636
}
635637

636638
SparcAsmParser::OperandMatchResultTy
637-
SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
639+
SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall)
638640
{
639641

640642
SMLoc S = Parser.getTok().getLoc();
@@ -695,6 +697,10 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
695697

696698
const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
697699
getContext());
700+
if (isCall &&
701+
getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_)
702+
Res = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_WPLT30, Res,
703+
getContext());
698704
Op = SparcOperand::CreateImm(Res, S, E);
699705
}
700706
break;
@@ -813,6 +819,31 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
813819
return false;
814820
}
815821

822+
static bool hasGOTReference(const MCExpr *Expr) {
823+
switch (Expr->getKind()) {
824+
case MCExpr::Target:
825+
if (const SparcMCExpr *SE = dyn_cast<SparcMCExpr>(Expr))
826+
return hasGOTReference(SE->getSubExpr());
827+
break;
828+
829+
case MCExpr::Constant:
830+
break;
831+
832+
case MCExpr::Binary: {
833+
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
834+
return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS());
835+
}
836+
837+
case MCExpr::SymbolRef: {
838+
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
839+
return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_");
840+
}
841+
842+
case MCExpr::Unary:
843+
return hasGOTReference(cast<MCUnaryExpr>(Expr)->getSubExpr());
844+
}
845+
return false;
846+
}
816847

817848
bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
818849
SMLoc &EndLoc)
@@ -836,6 +867,23 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
836867
const MCExpr *subExpr;
837868
if (Parser.parseParenExpression(subExpr, EndLoc))
838869
return false;
870+
871+
bool isPIC = getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
872+
873+
switch(VK) {
874+
default: break;
875+
case SparcMCExpr::VK_Sparc_LO:
876+
VK = (hasGOTReference(subExpr)
877+
? SparcMCExpr::VK_Sparc_PC10
878+
: (isPIC ? SparcMCExpr::VK_Sparc_GOT10 : VK));
879+
break;
880+
case SparcMCExpr::VK_Sparc_HI:
881+
VK = (hasGOTReference(subExpr)
882+
? SparcMCExpr::VK_Sparc_PC22
883+
: (isPIC ? SparcMCExpr::VK_Sparc_GOT22 : VK));
884+
break;
885+
}
886+
839887
EVal = SparcMCExpr::Create(VK, subExpr, getContext());
840888
return true;
841889
}

llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
#include "MCTargetDesc/SparcFixupKinds.h"
1212
#include "MCTargetDesc/SparcMCTargetDesc.h"
1313
#include "llvm/MC/MCELFObjectWriter.h"
14+
#include "llvm/MC/MCExpr.h"
1415
#include "llvm/MC/MCFixupKindInfo.h"
1516
#include "llvm/MC/MCObjectWriter.h"
17+
#include "llvm/MC/MCValue.h"
1618
#include "llvm/Support/TargetRegistry.h"
1719

1820
using namespace llvm;
@@ -154,6 +156,8 @@ namespace {
154156
switch ((Sparc::Fixups)Fixup.getKind()) {
155157
default: break;
156158
case Sparc::fixup_sparc_wplt30:
159+
if (Target.getSymA()->getSymbol().isTemporary())
160+
return;
157161
case Sparc::fixup_sparc_tls_gd_hi22:
158162
case Sparc::fixup_sparc_tls_gd_lo10:
159163
case Sparc::fixup_sparc_tls_gd_add:

llvm/test/MC/Sparc/sparc-pic.s

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s
2+
3+
4+
! CHECK: Relocations [
5+
! CHECK-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC
6+
! CHECK: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
7+
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
8+
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
9+
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
10+
! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
11+
! CHECK: ]
12+
13+
.text
14+
.globl foo
15+
.align 4
16+
.type foo,@function
17+
foo:
18+
.cfi_startproc
19+
save %sp, -176, %sp
20+
.cfi_def_cfa_register %fp
21+
.cfi_window_save
22+
.cfi_register 15, 31
23+
.Ltmp4:
24+
call .Ltmp5
25+
.Ltmp6:
26+
sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp6-.Ltmp4)), %i1
27+
.Ltmp5:
28+
or %i1, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp5-.Ltmp4)), %i1
29+
add %i1, %o7, %i1
30+
sethi %hi(AGlobalVar), %i2
31+
add %i2, %lo(AGlobalVar), %i2
32+
ldx [%i1+%i2], %i1
33+
ldx [%i1], %i1
34+
call bar
35+
add %i0, %i1, %o0
36+
ret
37+
restore %g0, %o0, %o0
38+
.Ltmp7:
39+
.size foo, .Ltmp7-foo
40+
.cfi_endproc
41+
42+
.type AGlobalVar,@object ! @AGlobalVar
43+
.section .bss
44+
.globl AGlobalVar
45+
.align 8
46+
AGlobalVar:
47+
.xword 0 ! 0x0
48+
.size AGlobalVar, 8
49+

0 commit comments

Comments
 (0)