[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:
Daniel Cederman 2018-06-11 05:50:08 +00:00
parent b60532f89a
commit 33f67a256b
10 changed files with 91 additions and 7 deletions

View File

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

View File

@ -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 },

View File

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

View File

@ -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,

View File

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

View File

@ -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,

View File

@ -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()) {
// This is the pic32 code model, the GOT is known to be smaller than 4GB.
SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
SparcMCExpr::VK_Sparc_GOT10, DAG);
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.
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();

View File

@ -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}

View File

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

View File

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