Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -62,6 +62,9 @@ case Sparc::fixup_sparc_lo10: return Value & 0x3ff; + case Sparc::fixup_sparc_got13: + return Value & 0x1fff; + case Sparc::fixup_sparc_h44: return (Value >> 22) & 0x3fffff; @@ -132,6 +135,7 @@ { "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 }, @@ -171,6 +175,7 @@ { "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 }, Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -88,6 +88,7 @@ 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; Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -64,6 +64,9 @@ /// 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, Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -36,6 +36,7 @@ VK_Sparc_PC10, VK_Sparc_GOT22, VK_Sparc_GOT10, + VK_Sparc_GOT13, VK_Sparc_WPLT30, VK_Sparc_R_DISP32, VK_Sparc_TLS_GD_HI22, Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -58,6 +58,7 @@ // 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_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 +97,7 @@ .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 +134,7 @@ 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_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; Index: lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- lib/Target/Sparc/SparcISelLowering.cpp +++ lib/Target/Sparc/SparcISelLowering.cpp @@ -1975,11 +1975,22 @@ // 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(); Index: test/CodeGen/SPARC/pic.ll =================================================================== --- /dev/null +++ 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}