Index: lib/Target/X86/X86MCInstLower.cpp =================================================================== --- lib/Target/X86/X86MCInstLower.cpp +++ lib/Target/X86/X86MCInstLower.cpp @@ -683,16 +683,9 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI) { - - bool is64Bits = MI.getOpcode() == X86::TLS_addr64 || + bool Is64Bits = MI.getOpcode() == X86::TLS_addr64 || MI.getOpcode() == X86::TLS_base_addr64; - - bool needsPadding = MI.getOpcode() == X86::TLS_addr64; - - MCContext &context = OutStreamer->getContext(); - - if (needsPadding) - EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); + MCContext &Ctx = OutStreamer->getContext(); MCSymbolRefExpr::VariantKind SRVK; switch (MI.getOpcode()) { @@ -710,51 +703,78 @@ llvm_unreachable("unexpected opcode"); } - MCSymbol *sym = MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)); - const MCSymbolRefExpr *symRef = MCSymbolRefExpr::create(sym, SRVK, context); + const MCSymbolRefExpr *Sym = MCSymbolRefExpr::create( + MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)), SRVK, Ctx); + bool UseGot = MMI->getModule()->getRtLibUseGOT(); - MCInst LEA; - if (is64Bits) { - LEA.setOpcode(X86::LEA64r); - LEA.addOperand(MCOperand::createReg(X86::RDI)); // dest - LEA.addOperand(MCOperand::createReg(X86::RIP)); // base - LEA.addOperand(MCOperand::createImm(1)); // scale - LEA.addOperand(MCOperand::createReg(0)); // index - LEA.addOperand(MCOperand::createExpr(symRef)); // disp - LEA.addOperand(MCOperand::createReg(0)); // seg - } else if (SRVK == MCSymbolRefExpr::VK_TLSLDM) { - LEA.setOpcode(X86::LEA32r); - LEA.addOperand(MCOperand::createReg(X86::EAX)); // dest - LEA.addOperand(MCOperand::createReg(X86::EBX)); // base - LEA.addOperand(MCOperand::createImm(1)); // scale - LEA.addOperand(MCOperand::createReg(0)); // index - LEA.addOperand(MCOperand::createExpr(symRef)); // disp - LEA.addOperand(MCOperand::createReg(0)); // seg + if (Is64Bits) { + if (SRVK == MCSymbolRefExpr::VK_TLSGD) + EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); + EmitAndCountInstruction(MCInstBuilder(X86::LEA64r) + .addReg(X86::RDI) + .addReg(X86::RIP) + .addImm(1) + .addReg(0) + .addExpr(Sym) + .addReg(0)); + const MCSymbol *TlsGetAddr = Ctx.getOrCreateSymbol("__tls_get_addr"); + if (SRVK == MCSymbolRefExpr::VK_TLSGD) { + if (!UseGot) + EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); + EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); + EmitAndCountInstruction(MCInstBuilder(X86::REX64_PREFIX)); + } + if (UseGot) { + const MCExpr *Expr = MCSymbolRefExpr::create( + TlsGetAddr, MCSymbolRefExpr::VK_GOTPCREL, Ctx); + EmitAndCountInstruction(MCInstBuilder(X86::CALL64m) + .addReg(X86::RIP) + .addImm(1) + .addReg(0) + .addExpr(Expr) + .addReg(0)); + } else { + EmitAndCountInstruction( + MCInstBuilder(X86::CALL64pcrel32) + .addExpr(MCSymbolRefExpr::create(TlsGetAddr, + MCSymbolRefExpr::VK_PLT, Ctx))); + } } else { - LEA.setOpcode(X86::LEA32r); - LEA.addOperand(MCOperand::createReg(X86::EAX)); // dest - LEA.addOperand(MCOperand::createReg(0)); // base - LEA.addOperand(MCOperand::createImm(1)); // scale - LEA.addOperand(MCOperand::createReg(X86::EBX)); // index - LEA.addOperand(MCOperand::createExpr(symRef)); // disp - LEA.addOperand(MCOperand::createReg(0)); // seg - } - EmitAndCountInstruction(LEA); + if (SRVK == MCSymbolRefExpr::VK_TLSGD && !UseGot) { + EmitAndCountInstruction(MCInstBuilder(X86::LEA32r) + .addReg(X86::EAX) + .addReg(0) + .addImm(1) + .addReg(X86::EBX) + .addExpr(Sym) + .addReg(0)); + } else { + EmitAndCountInstruction(MCInstBuilder(X86::LEA32r) + .addReg(X86::EAX) + .addReg(X86::EBX) + .addImm(1) + .addReg(0) + .addExpr(Sym) + .addReg(0)); + } - if (needsPadding) { - EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); - EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); - EmitAndCountInstruction(MCInstBuilder(X86::REX64_PREFIX)); + const MCSymbol *TlsGetAddr = Ctx.getOrCreateSymbol("___tls_get_addr"); + if (UseGot) { + const MCExpr *Expr = + MCSymbolRefExpr::create(TlsGetAddr, MCSymbolRefExpr::VK_GOT, Ctx); + EmitAndCountInstruction(MCInstBuilder(X86::CALL32m) + .addReg(X86::EBX) + .addImm(1) + .addReg(0) + .addExpr(Expr) + .addReg(0)); + } else { + EmitAndCountInstruction( + MCInstBuilder(X86::CALLpcrel32) + .addExpr(MCSymbolRefExpr::create(TlsGetAddr, + MCSymbolRefExpr::VK_PLT, Ctx))); + } } - - StringRef name = is64Bits ? "__tls_get_addr" : "___tls_get_addr"; - MCSymbol *tlsGetAddr = context.getOrCreateSymbol(name); - const MCSymbolRefExpr *tlsRef = - MCSymbolRefExpr::create(tlsGetAddr, MCSymbolRefExpr::VK_PLT, context); - - EmitAndCountInstruction( - MCInstBuilder(is64Bits ? X86::CALL64pcrel32 : X86::CALLpcrel32) - .addExpr(tlsRef)); } /// Emit the largest nop instruction smaller than or equal to \p NumBytes Index: test/CodeGen/X86/tls-no-plt.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/tls-no-plt.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -mtriple=i386-linux-musl -relocation-model=pic | FileCheck --check-prefixes=CHECK,X86 %s +; RUN: llc < %s -mtriple=x86_64-linux-musl -relocation-model=pic | FileCheck --check-prefixes=CHECK,X64 %s + +@gd = thread_local global i32 0, align 4 +@ld = internal thread_local global i32 0, align 4 + +define i32* @get_gd() { +entry: +; CHECK-LABEL: get_gd: +; X86: leal gd@TLSGD(%ebx), %eax +; X86: calll *___tls_get_addr@GOT(%ebx) + +; X64: leaq gd@TLSGD(%rip), %rdi +; X64: callq *__tls_get_addr@GOTPCREL(%rip) + ret i32* @gd +} + +define i32* @get_ld() { +; FIXME: This function uses a single thread-local variable, we might want to fall back to general-dynamic. +; CHECK-LABEL: get_ld: +; X86: leal ld@TLSLDM(%ebx), %eax +; X86: calll *___tls_get_addr@GOT(%ebx) + +; X64: leaq ld@TLSLD(%rip), %rdi +; X64: callq *__tls_get_addr@GOTPCREL(%rip) + ret i32* @ld +} + +!llvm.module.flags = !{!1} +!1 = !{i32 7, !"RtLibUseGOT", i32 1}