diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index 6c14e5adfc8..db1c361c8f9 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -26,31 +26,65 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case FK_Data_4: case FK_Data_8: return Value; + case Sparc::fixup_sparc_wplt30: case Sparc::fixup_sparc_call30: return (Value >> 2) & 0x3fffffff; + case Sparc::fixup_sparc_br22: return (Value >> 2) & 0x3fffff; + case Sparc::fixup_sparc_br19: return (Value >> 2) & 0x7ffff; + case Sparc::fixup_sparc_pc22: case Sparc::fixup_sparc_got22: + case Sparc::fixup_sparc_tls_gd_hi22: + case Sparc::fixup_sparc_tls_ldm_hi22: + case Sparc::fixup_sparc_tls_ie_hi22: case Sparc::fixup_sparc_hi22: return (Value >> 10) & 0x3fffff; + case Sparc::fixup_sparc_pc10: case Sparc::fixup_sparc_got10: + case Sparc::fixup_sparc_tls_gd_lo10: + case Sparc::fixup_sparc_tls_ldm_lo10: + case Sparc::fixup_sparc_tls_ie_lo10: case Sparc::fixup_sparc_lo10: return Value & 0x3ff; + + case Sparc::fixup_sparc_tls_ldo_hix22: + case Sparc::fixup_sparc_tls_le_hix22: + return (~Value >> 10) & 0x3fffff; + + case Sparc::fixup_sparc_tls_ldo_lox10: + case Sparc::fixup_sparc_tls_le_lox10: + return (~(~Value & 0x3ff)) & 0x1fff; + case Sparc::fixup_sparc_h44: return (Value >> 22) & 0x3fffff; + case Sparc::fixup_sparc_m44: return (Value >> 12) & 0x3ff; + case Sparc::fixup_sparc_l44: return Value & 0xfff; + case Sparc::fixup_sparc_hh: return (Value >> 42) & 0x3fffff; + case Sparc::fixup_sparc_hm: return (Value >> 32) & 0x3ff; + + case Sparc::fixup_sparc_tls_gd_add: + case Sparc::fixup_sparc_tls_gd_call: + case Sparc::fixup_sparc_tls_ldm_add: + case Sparc::fixup_sparc_tls_ldm_call: + case Sparc::fixup_sparc_tls_ldo_add: + case Sparc::fixup_sparc_tls_ie_ld: + case Sparc::fixup_sparc_tls_ie_ldx: + case Sparc::fixup_sparc_tls_ie_add: + return 0; } } @@ -81,7 +115,25 @@ namespace { { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_got22", 10, 22, 0 }, { "fixup_sparc_got10", 22, 10, 0 }, - { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel } + { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, + { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, + { "fixup_sparc_tls_gd_add", 0, 0, 0 }, + { "fixup_sparc_tls_gd_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 }, + { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 }, + { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 }, + { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 }, + { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, + { "fixup_sparc_tls_ie_hi22", 10, 22, 0 }, + { "fixup_sparc_tls_ie_lo10", 22, 10, 0 }, + { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, + { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, + { "fixup_sparc_tls_ie_add", 0, 0, 0 }, + { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, + { "fixup_sparc_tls_le_lox10", 0, 0, 0 } }; if (Kind < FirstTargetFixupKind) @@ -101,11 +153,28 @@ namespace { bool &IsResolved) { switch ((Sparc::Fixups)Fixup.getKind()) { default: break; - case Sparc::fixup_sparc_wplt30: IsResolved = false; break; + case Sparc::fixup_sparc_wplt30: + case Sparc::fixup_sparc_tls_gd_hi22: + case Sparc::fixup_sparc_tls_gd_lo10: + case Sparc::fixup_sparc_tls_gd_add: + case Sparc::fixup_sparc_tls_gd_call: + case Sparc::fixup_sparc_tls_ldm_hi22: + case Sparc::fixup_sparc_tls_ldm_lo10: + case Sparc::fixup_sparc_tls_ldm_add: + case Sparc::fixup_sparc_tls_ldm_call: + case Sparc::fixup_sparc_tls_ldo_hix22: + case Sparc::fixup_sparc_tls_ldo_lox10: + case Sparc::fixup_sparc_tls_ldo_add: + case Sparc::fixup_sparc_tls_ie_hi22: + case Sparc::fixup_sparc_tls_ie_lo10: + case Sparc::fixup_sparc_tls_ie_ld: + case Sparc::fixup_sparc_tls_ie_ldx: + case Sparc::fixup_sparc_tls_ie_add: + case Sparc::fixup_sparc_tls_le_hix22: + case Sparc::fixup_sparc_tls_le_lox10: IsResolved = false; break; } } - bool mayNeedRelaxation(const MCInst &Inst) const { // FIXME. return false; diff --git a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp index da1b9999c13..3a9929bc4c0 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -91,6 +91,24 @@ unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, 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_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; + case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL; + case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22; + case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10; + case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD; + case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL; + case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22; + case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10; + case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD; + case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22; + case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10; + case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD; + case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX; + case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD; + case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22; + case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10; } return ELF::R_SPARC_NONE; diff --git a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h index ff6e6cbadd7..005a0242dc9 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -63,6 +63,26 @@ namespace llvm { /// fixup_sparc_wplt30 fixup_sparc_wplt30, + /// fixups for Thread Local Storage + fixup_sparc_tls_gd_hi22, + fixup_sparc_tls_gd_lo10, + fixup_sparc_tls_gd_add, + fixup_sparc_tls_gd_call, + fixup_sparc_tls_ldm_hi22, + fixup_sparc_tls_ldm_lo10, + fixup_sparc_tls_ldm_add, + fixup_sparc_tls_ldm_call, + fixup_sparc_tls_ldo_hix22, + fixup_sparc_tls_ldo_lox10, + fixup_sparc_tls_ldo_add, + fixup_sparc_tls_ie_hi22, + fixup_sparc_tls_ie_lo10, + fixup_sparc_tls_ie_ld, + fixup_sparc_tls_ie_ldx, + fixup_sparc_tls_ie_add, + fixup_sparc_tls_le_hix22, + fixup_sparc_tls_le_lox10, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp index 0328b3f7376..16310d50243 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -82,6 +83,21 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, OS << (char)(Bits >> 24); Bits <<= 8; } + unsigned tlsOpNo = 0; + switch (MI.getOpcode()) { + default: break; + case SP::TLS_CALL: tlsOpNo = 1; break; + case SP::TLS_ADDrr: + case SP::TLS_ADDXrr: + case SP::TLS_LDrr: + case SP::TLS_LDXrr: tlsOpNo = 3; break; + } + if (tlsOpNo != 0) { + const MCOperand &MO = MI.getOperand(tlsOpNo); + uint64_t op = getMachineOpValue(MI, MO, Fixups, STI); + assert(op == 0 && "Unexpected operand value!"); + (void)op; // suppress warning. + } ++MCNumEmitted; // Keep track of the # of mi's emitted. } @@ -122,6 +138,21 @@ getCallTargetOpValue(const MCInst &MI, unsigned OpNo, if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); + if (MI.getOpcode() == SP::TLS_CALL) { + // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in + // EncodeInstruction. +#ifndef NDEBUG + // Verify that the callee is actually __tls_get_addr. + const SparcMCExpr *SExpr = dyn_cast(MO.getExpr()); + assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef && + "Unexpected expression in TLS_CALL"); + const MCSymbolRefExpr *SymExpr = cast(SExpr->getSubExpr()); + assert(SymExpr->getSymbol().getName() == "__tls_get_addr" && + "Unexpected function for TLS_CALL"); +#endif + return 0; + } + MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; if (const SparcMCExpr *SExpr = dyn_cast(MO.getExpr())) { diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp index 4a83c96a924..7f2b25e4081 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -135,6 +135,25 @@ 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_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; + case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add; + case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call; + case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22; + case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10; + case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add; + case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call; + case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22; + case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10; + case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add; + case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22; + case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10; + case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld; + case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx; + case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add; + case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22; + case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10; } } @@ -147,7 +166,33 @@ SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, } static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { - assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!"); + switch (Expr->getKind()) { + case MCExpr::Target: + llvm_unreachable("Can't handle nested target expr!"); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Expr); + fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); + fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); + break; + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &SymRef = *cast(Expr); + MCSymbolData &SD = Asm.getOrCreateSymbolData(SymRef.getSymbol()); + MCELF::SetType(SD, ELF::STT_TLS); + break; + } + + case MCExpr::Unary: + fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); + break; + } + } void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { diff --git a/test/CodeGen/SPARC/tls.ll b/test/CodeGen/SPARC/tls.ll index 6451a462acb..ce3e0053984 100644 --- a/test/CodeGen/SPARC/tls.ll +++ b/test/CodeGen/SPARC/tls.ll @@ -3,6 +3,10 @@ ; RUN: llc <%s -march=sparc -relocation-model=pic | FileCheck %s --check-prefix=pic ; RUN: llc <%s -march=sparcv9 -relocation-model=pic | FileCheck %s --check-prefix=pic +; RUN: llc <%s -march=sparc -relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=v8abs-obj +; RUN: llc <%s -march=sparcv9 -relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=v9abs-obj +; RUN: llc <%s -march=sparc -relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=pic-obj +; RUN: llc <%s -march=sparcv9 -relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=pic-obj @local_symbol = internal thread_local global i32 0 @extern_symbol = external thread_local global i32 @@ -69,3 +73,47 @@ entry: store i32 %1, i32* @extern_symbol, align 4 ret i32 %1 } + + +; v8abs-obj: Relocations [ +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_HIX22 local_symbol 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_LOX10 local_symbol 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_HI22 extern_symbol 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LO10 extern_symbol 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LD extern_symbol 0x0 +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_ADD extern_symbol 0x0 +; v8abs-obj: ] + +; v9abs-obj: Relocations [ +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_HIX22 local_symbol 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_LOX10 local_symbol 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_H44 _GLOBAL_OFFSET_TABLE_ 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_M44 _GLOBAL_OFFSET_TABLE_ 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_L44 _GLOBAL_OFFSET_TABLE_ 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_HI22 extern_symbol 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LO10 extern_symbol 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LDX extern_symbol 0x0 +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_ADD extern_symbol 0x0 +; v9abs-obj: ] + +; pic-obj: Relocations [ +; pic-obj: Section (2) .rela.text { +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_HIX22 local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_LOX10 local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_HI22 local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_LO10 local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_ADD local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_CALL local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_ADD local_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_HI22 extern_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_LO10 extern_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_ADD extern_symbol 0x0 +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_CALL extern_symbol 0x0 +; pic-obj: ] +