summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp14
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp8
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp2
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h6
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp5
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h2
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp19
-rw-r--r--llvm/test/CodeGen/SPARC/pic.ll14
-rw-r--r--llvm/test/MC/Sparc/sparc-pic.s23
-rw-r--r--llvm/test/MC/Sparc/sparc-relocations.s5
10 files changed, 91 insertions, 7 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 35d92a96abe..c7a5a1e8e6e 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -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;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index 4b6c1de7d85..5f5e2ef7d45 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -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 },
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
index 173ef8674c1..5a730947796 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -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;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
index 8d79396d936..99aa63fe229 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
@@ -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,
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
index 2b80293df12..f736a37a266 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
@@ -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;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
index 13f08195c76..cf2db067749 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
@@ -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,
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 34e0297fe9f..14a99c085f8 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -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();
diff --git a/llvm/test/CodeGen/SPARC/pic.ll b/llvm/test/CodeGen/SPARC/pic.ll
new file mode 100644
index 00000000000..4edbffcc12b
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/pic.ll
@@ -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}
diff --git a/llvm/test/MC/Sparc/sparc-pic.s b/llvm/test/MC/Sparc/sparc-pic.s
index f51e1e93b50..a16ed807afc 100644
--- a/llvm/test/MC/Sparc/sparc-pic.s
+++ b/llvm/test/MC/Sparc/sparc-pic.s
@@ -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
diff --git a/llvm/test/MC/Sparc/sparc-relocations.s b/llvm/test/MC/Sparc/sparc-relocations.s
index 58ad37e1da5..18fc123fac0 100644
--- a/llvm/test/MC/Sparc/sparc-relocations.s
+++ b/llvm/test/MC/Sparc/sparc-relocations.s
@@ -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
OpenPOWER on IntegriCloud