forked from OSchip/llvm-project
[Sparc] Add support for 13-bit PIC
Summary: When compiling with -fpic, in contrast to -fPIC, use only the immediate field to index into the GOT. This saves space if the GOT is known to be small. The linker will warn if the GOT is too large for this method. Reviewers: jyknight, venkatra Reviewed By: jyknight Subscribers: brad, fedor.sergeev, jrtc27, llvm-commits Differential Revision: https://reviews.llvm.org/D47136 llvm-svn: 334383
This commit is contained in:
parent
b60532f89a
commit
33f67a256b
|
@ -885,9 +885,17 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,
|
|||
|
||||
const MCExpr *Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
|
||||
getContext());
|
||||
if (isCall && getContext().getObjectFileInfo()->isPositionIndependent())
|
||||
Res = SparcMCExpr::create(SparcMCExpr::VK_Sparc_WPLT30, Res,
|
||||
getContext());
|
||||
SparcMCExpr::VariantKind Kind = SparcMCExpr::VK_Sparc_13;
|
||||
|
||||
if (getContext().getObjectFileInfo()->isPositionIndependent()) {
|
||||
if (isCall)
|
||||
Kind = SparcMCExpr::VK_Sparc_WPLT30;
|
||||
else
|
||||
Kind = SparcMCExpr::VK_Sparc_GOT13;
|
||||
}
|
||||
|
||||
Res = SparcMCExpr::create(Kind, Res, getContext());
|
||||
|
||||
Op = SparcOperand::CreateImm(Res, S, E);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -54,6 +54,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||
case Sparc::fixup_sparc_hi22:
|
||||
return (Value >> 10) & 0x3fffff;
|
||||
|
||||
case Sparc::fixup_sparc_got13:
|
||||
case Sparc::fixup_sparc_13:
|
||||
return Value & 0x1fff;
|
||||
|
||||
case Sparc::fixup_sparc_pc10:
|
||||
case Sparc::fixup_sparc_got10:
|
||||
case Sparc::fixup_sparc_tls_gd_lo10:
|
||||
|
@ -120,6 +124,7 @@ namespace {
|
|||
{ "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_13", 19, 13, 0 },
|
||||
{ "fixup_sparc_hi22", 10, 22, 0 },
|
||||
{ "fixup_sparc_lo10", 22, 10, 0 },
|
||||
{ "fixup_sparc_h44", 10, 22, 0 },
|
||||
|
@ -131,6 +136,7 @@ namespace {
|
|||
{ "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_got22", 10, 22, 0 },
|
||||
{ "fixup_sparc_got10", 22, 10, 0 },
|
||||
{ "fixup_sparc_got13", 19, 13, 0 },
|
||||
{ "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_tls_gd_hi22", 10, 22, 0 },
|
||||
{ "fixup_sparc_tls_gd_lo10", 22, 10, 0 },
|
||||
|
@ -159,6 +165,7 @@ namespace {
|
|||
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br16_14", 0, 14, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_13", 0, 13, 0 },
|
||||
{ "fixup_sparc_hi22", 0, 22, 0 },
|
||||
{ "fixup_sparc_lo10", 0, 10, 0 },
|
||||
{ "fixup_sparc_h44", 0, 22, 0 },
|
||||
|
@ -170,6 +177,7 @@ namespace {
|
|||
{ "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_got22", 0, 22, 0 },
|
||||
{ "fixup_sparc_got10", 0, 10, 0 },
|
||||
{ "fixup_sparc_got13", 0, 13, 0 },
|
||||
{ "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_tls_gd_hi22", 0, 22, 0 },
|
||||
{ "fixup_sparc_tls_gd_lo10", 0, 10, 0 },
|
||||
|
|
|
@ -79,6 +79,7 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
|
|||
case FK_Data_8: return ((Fixup.getOffset() % 8)
|
||||
? ELF::R_SPARC_UA64
|
||||
: ELF::R_SPARC_64);
|
||||
case Sparc::fixup_sparc_13: return ELF::R_SPARC_13;
|
||||
case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22;
|
||||
case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10;
|
||||
case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44;
|
||||
|
@ -88,6 +89,7 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
|
|||
case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10;
|
||||
case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22;
|
||||
case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10;
|
||||
case Sparc::fixup_sparc_got13: return ELF::R_SPARC_GOT13;
|
||||
case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22;
|
||||
case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10;
|
||||
case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD;
|
||||
|
|
|
@ -30,6 +30,9 @@ namespace llvm {
|
|||
fixup_sparc_br16_2,
|
||||
fixup_sparc_br16_14,
|
||||
|
||||
/// fixup_sparc_13 - 13-bit fixup
|
||||
fixup_sparc_13,
|
||||
|
||||
/// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo)
|
||||
/// for sethi
|
||||
fixup_sparc_hi22,
|
||||
|
@ -64,6 +67,9 @@ namespace llvm {
|
|||
/// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo)
|
||||
fixup_sparc_got10,
|
||||
|
||||
/// fixup_sparc_got13 - 13-bit fixup corresponding to %got13(foo)
|
||||
fixup_sparc_got13,
|
||||
|
||||
/// fixup_sparc_wplt30
|
||||
fixup_sparc_wplt30,
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind)
|
|||
// FIXME: use %got22/%got10, if system assembler supports them.
|
||||
case VK_Sparc_GOT22: OS << "%hi("; break;
|
||||
case VK_Sparc_GOT10: OS << "%lo("; break;
|
||||
case VK_Sparc_GOT13: closeParen = false; break;
|
||||
case VK_Sparc_13: closeParen = false; break;
|
||||
case VK_Sparc_WPLT30: closeParen = false; break;
|
||||
case VK_Sparc_R_DISP32: OS << "%r_disp32("; break;
|
||||
case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break;
|
||||
|
@ -96,6 +98,7 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
|
|||
.Case("pc10", VK_Sparc_PC10)
|
||||
.Case("got22", VK_Sparc_GOT22)
|
||||
.Case("got10", VK_Sparc_GOT10)
|
||||
.Case("got13", VK_Sparc_GOT13)
|
||||
.Case("r_disp32", VK_Sparc_R_DISP32)
|
||||
.Case("tgd_hi22", VK_Sparc_TLS_GD_HI22)
|
||||
.Case("tgd_lo10", VK_Sparc_TLS_GD_LO10)
|
||||
|
@ -132,6 +135,8 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
|
|||
case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10;
|
||||
case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22;
|
||||
case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10;
|
||||
case VK_Sparc_GOT13: return Sparc::fixup_sparc_got13;
|
||||
case VK_Sparc_13: return Sparc::fixup_sparc_13;
|
||||
case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30;
|
||||
case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22;
|
||||
case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10;
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
VK_Sparc_PC10,
|
||||
VK_Sparc_GOT22,
|
||||
VK_Sparc_GOT10,
|
||||
VK_Sparc_GOT13,
|
||||
VK_Sparc_13,
|
||||
VK_Sparc_WPLT30,
|
||||
VK_Sparc_R_DISP32,
|
||||
VK_Sparc_TLS_GD_HI22,
|
||||
|
|
|
@ -1980,11 +1980,22 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
|
|||
|
||||
// Handle PIC mode first. SPARC needs a got load for every variable!
|
||||
if (isPositionIndependent()) {
|
||||
const Module *M = DAG.getMachineFunction().getFunction().getParent();
|
||||
PICLevel::Level picLevel = M->getPICLevel();
|
||||
SDValue Idx;
|
||||
|
||||
if (picLevel == PICLevel::SmallPIC) {
|
||||
// This is the pic13 code model, the GOT is known to be smaller than 8KiB.
|
||||
Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(),
|
||||
withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG));
|
||||
} else {
|
||||
// This is the pic32 code model, the GOT is known to be smaller than 4GB.
|
||||
SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
|
||||
Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
|
||||
SparcMCExpr::VK_Sparc_GOT10, DAG);
|
||||
}
|
||||
|
||||
SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
|
||||
SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo);
|
||||
SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx);
|
||||
// GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
|
||||
// function has calls.
|
||||
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
; RUN: llc < %s -relocation-model=pic -mtriple=sparc | FileCheck %s
|
||||
|
||||
@value = external global i32
|
||||
|
||||
define i32 @test() nounwind {
|
||||
; CHECK: ld [%i0+value], %i0
|
||||
entry:
|
||||
%0 = load i32, i32* @value
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
|
||||
!0 = !{i32 7, !"PIC Level", i32 1}
|
|
@ -15,6 +15,7 @@
|
|||
! 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: 0x{{[0-9,A-F]+}} R_SPARC_GOT13 value 0x0
|
||||
! PIC: ]
|
||||
|
||||
! NOPIC: Relocations [
|
||||
|
@ -30,6 +31,7 @@
|
|||
! 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: 0x{{[0-9,A-F]+}} R_SPARC_13 value 0x0
|
||||
! NOPIC: ]
|
||||
|
||||
.section ".rodata"
|
||||
|
@ -78,3 +80,24 @@ foo:
|
|||
AGlobalVar:
|
||||
.xword 0 ! 0x0
|
||||
.size AGlobalVar, 8
|
||||
|
||||
.section ".text"
|
||||
.text
|
||||
.globl pic13
|
||||
.align 4
|
||||
.type pic13,@function
|
||||
pic13:
|
||||
save %sp, -128, %sp
|
||||
.Ltmp0:
|
||||
call .Ltmp1
|
||||
.Ltmp2:
|
||||
sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.Ltmp0)), %i0
|
||||
.Ltmp1:
|
||||
or %i0, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.Ltmp0)), %i0
|
||||
add %i0, %o7, %i0
|
||||
ldx [%i0+value], %i0
|
||||
ld [%i0], %i0
|
||||
ret
|
||||
restore
|
||||
.Lfunc_end0:
|
||||
.size pic13, .Lfunc_end0-pic13
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
|
||||
! CHECK-ELF: ]
|
||||
|
||||
! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A]
|
||||
|
@ -44,3 +45,7 @@
|
|||
! CHECK: or %g1, %hm(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %hm(sym), kind: fixup_sparc_hm
|
||||
or %g1, %hm(sym), %g3
|
||||
|
||||
! CHECK: or %g1, sym, %g3 ! encoding: [0x86,0x10,0b011AAAAA,A]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: sym, kind: fixup_sparc_13
|
||||
or %g1, sym, %g3
|
||||
|
|
Loading…
Reference in New Issue