mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-30 16:53:02 +00:00
Add support for implicit TLS model used with MS VC runtime.
Patch by Kai Nacke! llvm-svn: 150307
This commit is contained in:
parent
9a10a94e1a
commit
5996573d4b
@ -162,6 +162,7 @@ public:
|
||||
VK_TPOFF,
|
||||
VK_DTPOFF,
|
||||
VK_TLVP, // Mach-O thread local variable relocation
|
||||
VK_SECREL,
|
||||
// FIXME: We'd really like to use the generic Kinds listed above for these.
|
||||
VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT
|
||||
VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF
|
||||
|
@ -109,7 +109,7 @@ protected:
|
||||
const MCSection *TLSExtraDataSection;
|
||||
|
||||
/// TLSDataSection - Section directive for Thread Local data.
|
||||
/// ELF and MachO only.
|
||||
/// ELF, MachO and COFF.
|
||||
const MCSection *TLSDataSection; // Defaults to ".tdata".
|
||||
|
||||
/// TLSBSSSection - Section directive for Thread Local uninitialized data.
|
||||
|
@ -588,6 +588,11 @@ getCOFFSectionFlags(SectionKind K) {
|
||||
COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_MEM_WRITE;
|
||||
else if (K.isThreadLocal())
|
||||
Flags |=
|
||||
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_MEM_WRITE;
|
||||
else if (K.isReadOnly())
|
||||
Flags |=
|
||||
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
@ -614,6 +619,8 @@ static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
|
||||
return ".text$";
|
||||
if (Kind.isBSS ())
|
||||
return ".bss$";
|
||||
if (Kind.isThreadLocal())
|
||||
return ".tls$";
|
||||
if (Kind.isWriteable())
|
||||
return ".data$";
|
||||
return ".rdata$";
|
||||
@ -623,7 +630,6 @@ static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
|
||||
const MCSection *TargetLoweringObjectFileCOFF::
|
||||
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
Mangler *Mang, const TargetMachine &TM) const {
|
||||
assert(!Kind.isThreadLocal() && "Doesn't support TLS");
|
||||
|
||||
// If this global is linkonce/weak and the target handles this by emitting it
|
||||
// into a 'uniqued' section name, create and return the section now.
|
||||
@ -644,6 +650,9 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
if (Kind.isText())
|
||||
return getTextSection();
|
||||
|
||||
if (Kind.isThreadLocal())
|
||||
return getTLSDataSection();
|
||||
|
||||
return getDataSection();
|
||||
}
|
||||
|
||||
|
@ -188,6 +188,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
|
||||
case VK_TPOFF: return "TPOFF";
|
||||
case VK_DTPOFF: return "DTPOFF";
|
||||
case VK_TLVP: return "TLVP";
|
||||
case VK_SECREL: return "SECREL";
|
||||
case VK_ARM_PLT: return "(PLT)";
|
||||
case VK_ARM_GOT: return "(GOT)";
|
||||
case VK_ARM_GOTOFF: return "(GOTOFF)";
|
||||
|
@ -495,6 +495,12 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_MEM_WRITE,
|
||||
SectionKind::getDataRel());
|
||||
TLSDataSection =
|
||||
Ctx->getCOFFSection(".tls$",
|
||||
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ |
|
||||
COFF::IMAGE_SCN_MEM_WRITE,
|
||||
SectionKind::getDataRel());
|
||||
}
|
||||
|
||||
void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm,
|
||||
|
@ -164,7 +164,13 @@ namespace X86II {
|
||||
/// is some TLS offset from the picbase.
|
||||
///
|
||||
/// This is the 32-bit TLS offset for Darwin TLS in PIC mode.
|
||||
MO_TLVP_PIC_BASE
|
||||
MO_TLVP_PIC_BASE,
|
||||
|
||||
/// MO_SECREL - On a symbol operand this indicates that the immediate is
|
||||
/// the offset from beginning of section.
|
||||
///
|
||||
/// This is the TLS offset for the COFF/Windows TLS mechanism.
|
||||
MO_SECREL
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -222,6 +222,7 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size,
|
||||
|
||||
// If we have an immoffset, add it to the expression.
|
||||
if ((FixupKind == FK_Data_4 ||
|
||||
FixupKind == FK_Data_8 ||
|
||||
FixupKind == MCFixupKind(X86::reloc_signed_4byte))) {
|
||||
GlobalOffsetTableExprKind Kind = StartsWithGlobalOffsetTable(Expr);
|
||||
if (Kind != GOT_None) {
|
||||
@ -230,6 +231,11 @@ EmitImmediate(const MCOperand &DispOp, SMLoc Loc, unsigned Size,
|
||||
FixupKind = MCFixupKind(X86::reloc_global_offset_table);
|
||||
if (Kind == GOT_Normal)
|
||||
ImmOffset = CurByte;
|
||||
} else if (Expr->getKind() == MCExpr::SymbolRef) {
|
||||
const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
|
||||
if (Ref->getKind() == MCSymbolRefExpr::VK_SECREL) {
|
||||
FixupKind = MCFixupKind(FK_SecRel_4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ unsigned X86WinCOFFObjectWriter::getRelocType(unsigned FixupKind) const {
|
||||
return COFF::IMAGE_REL_AMD64_ADDR64;
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
case FK_SecRel_4:
|
||||
return Is64Bit ? COFF::IMAGE_REL_AMD64_SREL32 : COFF::IMAGE_REL_I386_SECREL;
|
||||
return Is64Bit ? COFF::IMAGE_REL_AMD64_SECREL : COFF::IMAGE_REL_I386_SECREL;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
}
|
||||
|
@ -199,6 +199,7 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO,
|
||||
case X86II::MO_TLVP_PIC_BASE:
|
||||
O << "@TLVP" << '-' << *MF->getPICBaseSymbol();
|
||||
break;
|
||||
case X86II::MO_SECREL: O << "@SECREL"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7355,6 +7355,68 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
|
||||
unsigned Reg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
|
||||
return DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(),
|
||||
Chain.getValue(1));
|
||||
} else if (Subtarget->isTargetWindows()) {
|
||||
// Just use the implicit TLS architecture
|
||||
// Need to generate someting similar to:
|
||||
// mov rdx, qword [gs:abs 58H]; Load pointer to ThreadLocalStorage
|
||||
// ; from TEB
|
||||
// mov ecx, dword [rel _tls_index]: Load index (from C runtime)
|
||||
// mov rcx, qword [rdx+rcx*8]
|
||||
// mov eax, .tls$:tlsvar
|
||||
// [rax+rcx] contains the address
|
||||
// Windows 64bit: gs:0x58
|
||||
// Windows 32bit: fs:__tls_array
|
||||
|
||||
// If GV is an alias then use the aliasee for determining
|
||||
// thread-localness.
|
||||
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
|
||||
GV = GA->resolveAliasedGlobal(false);
|
||||
DebugLoc dl = GA->getDebugLoc();
|
||||
SDValue Chain = DAG.getEntryNode();
|
||||
|
||||
// Get the Thread Pointer, which is %fs:__tls_array (32-bit) or
|
||||
// %gs:0x58 (64-bit).
|
||||
Value *Ptr = Constant::getNullValue(Subtarget->is64Bit()
|
||||
? Type::getInt8PtrTy(*DAG.getContext(),
|
||||
256)
|
||||
: Type::getInt32PtrTy(*DAG.getContext(),
|
||||
257));
|
||||
|
||||
SDValue ThreadPointer = DAG.getLoad(getPointerTy(), dl, Chain,
|
||||
Subtarget->is64Bit()
|
||||
? DAG.getIntPtrConstant(0x58)
|
||||
: DAG.getExternalSymbol("_tls_array",
|
||||
getPointerTy()),
|
||||
MachinePointerInfo(Ptr),
|
||||
false, false, false, 0);
|
||||
|
||||
// Load the _tls_index variable
|
||||
SDValue IDX = DAG.getExternalSymbol("_tls_index", getPointerTy());
|
||||
if (Subtarget->is64Bit())
|
||||
IDX = DAG.getExtLoad(ISD::ZEXTLOAD, dl, getPointerTy(), Chain,
|
||||
IDX, MachinePointerInfo(), MVT::i32,
|
||||
false, false, 0);
|
||||
else
|
||||
IDX = DAG.getLoad(getPointerTy(), dl, Chain, IDX, MachinePointerInfo(),
|
||||
false, false, false, 0);
|
||||
|
||||
SDValue Scale = DAG.getConstant(Log2_64_Ceil(TD->getPointerSize()),
|
||||
getPointerTy());
|
||||
IDX = DAG.getNode(ISD::SHL, dl, getPointerTy(), IDX, Scale);
|
||||
|
||||
SDValue res = DAG.getNode(ISD::ADD, dl, getPointerTy(), ThreadPointer, IDX);
|
||||
res = DAG.getLoad(getPointerTy(), dl, Chain, res, MachinePointerInfo(),
|
||||
false, false, false, 0);
|
||||
|
||||
// Get the offset of start of .tls section
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
|
||||
GA->getValueType(0),
|
||||
GA->getOffset(), X86II::MO_SECREL);
|
||||
SDValue Offset = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), TGA);
|
||||
|
||||
// The address of the thread local variable is the add of the thread
|
||||
// pointer with the offset of the variable.
|
||||
return DAG.getNode(ISD::ADD, dl, getPointerTy(), res, Offset);
|
||||
}
|
||||
|
||||
llvm_unreachable("TLS not implemented for this target.");
|
||||
|
@ -154,6 +154,7 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
|
||||
Ctx),
|
||||
Ctx);
|
||||
break;
|
||||
case X86II::MO_SECREL: RefKind = MCSymbolRefExpr::VK_SECREL; break;
|
||||
case X86II::MO_TLSGD: RefKind = MCSymbolRefExpr::VK_TLSGD; break;
|
||||
case X86II::MO_GOTTPOFF: RefKind = MCSymbolRefExpr::VK_GOTTPOFF; break;
|
||||
case X86II::MO_INDNTPOFF: RefKind = MCSymbolRefExpr::VK_INDNTPOFF; break;
|
||||
@ -230,7 +231,8 @@ static void LowerUnaryToTwoAddr(MCInst &OutMI, unsigned NewOpc) {
|
||||
/// a short fixed-register form.
|
||||
static void SimplifyShortImmForm(MCInst &Inst, unsigned Opcode) {
|
||||
unsigned ImmOp = Inst.getNumOperands() - 1;
|
||||
assert(Inst.getOperand(0).isReg() && Inst.getOperand(ImmOp).isImm() &&
|
||||
assert(Inst.getOperand(0).isReg() &&
|
||||
(Inst.getOperand(ImmOp).isImm() || Inst.getOperand(ImmOp).isExpr()) &&
|
||||
((Inst.getNumOperands() == 3 && Inst.getOperand(1).isReg() &&
|
||||
Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) ||
|
||||
Inst.getNumOperands() == 2) && "Unexpected instruction!");
|
||||
|
@ -1,7 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movl %gs:i@NTPOFF, %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movl %fs:i@TPOFF, %eax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = thread_local global i32 15
|
||||
|
||||
@ -10,3 +10,11 @@ entry:
|
||||
%tmp1 = load i32* @i
|
||||
ret i32 %tmp1
|
||||
}
|
||||
; X32_LINUX: movl %gs:i@NTPOFF, %eax
|
||||
; X64_LINUX: movl %fs:i@TPOFF, %eax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: movl _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movabsq $i@SECREL, %rcx
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movzwl %gs:i@NTPOFF, %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movzwl %fs:i@TPOFF, %eax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = thread_local global i16 15
|
||||
|
||||
@ -10,3 +10,12 @@ entry:
|
||||
%tmp1 = load i16* @i
|
||||
ret i16 %tmp1
|
||||
}
|
||||
; X32_LINUX: movzwl %gs:i@NTPOFF, %eax
|
||||
; X64_LINUX: movzwl %fs:i@TPOFF, %eax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: movzwl _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movq %gs:88, %rcx
|
||||
; X64_WIN: movabsq $i@SECREL, %rcx
|
||||
; X64_WIN: movzwl (%rax,%rcx), %eax
|
||||
|
@ -1,7 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movb %gs:i@NTPOFF, %al} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movb %fs:i@TPOFF, %al} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = thread_local global i8 15
|
||||
|
||||
@ -10,3 +10,12 @@ entry:
|
||||
%tmp1 = load i8* @i
|
||||
ret i8 %tmp1
|
||||
}
|
||||
; X32_LINUX: movb %gs:i@NTPOFF, %al
|
||||
; X64_LINUX: movb %fs:i@TPOFF, %al
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: movb _i@SECREL(%eax), %al
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movq %gs:88, %rcx
|
||||
; X64_WIN: movabsq $i@SECREL, %rcx
|
||||
; X64_WIN: movb (%rax,%rcx), %al
|
||||
|
@ -1,9 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movswl %gs:i@NTPOFF, %eax} %t
|
||||
; RUN: grep {movzwl %gs:j@NTPOFF, %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movswl %fs:i@TPOFF, %edi} %t2
|
||||
; RUN: grep {movzwl %fs:j@TPOFF, %edi} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = thread_local global i16 0
|
||||
@j = thread_local global i16 0
|
||||
@ -22,3 +20,14 @@ entry:
|
||||
declare void @g(i32)
|
||||
|
||||
declare void @h(i32)
|
||||
|
||||
; X32_LINUX: movswl %gs:i@NTPOFF, %eax
|
||||
; X32_LINUX: movzwl %gs:j@NTPOFF, %eax
|
||||
; X64_LINUX: movswl %fs:i@TPOFF, %edi
|
||||
; X64_LINUX: movzwl %fs:j@TPOFF, %edi
|
||||
; X32_WIN: movswl _i@SECREL(%esi), %eax
|
||||
; X32_WIN: movzwl _j@SECREL(%esi), %eax
|
||||
; X64_WIN: movabsq $i@SECREL, %rax
|
||||
; X64_WIN: movswl (%rsi,%rax), %ecx
|
||||
; X64_WIN: movabsq $j@SECREL, %rax
|
||||
; X64_WIN: movzwl (%rsi,%rax), %ecx
|
||||
|
@ -1,9 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movsbl %gs:i@NTPOFF, %eax} %t
|
||||
; RUN: grep {movzbl %gs:j@NTPOFF, %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movsbl %fs:i@TPOFF, %edi} %t2
|
||||
; RUN: grep {movzbl %fs:j@TPOFF, %edi} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = thread_local global i8 0
|
||||
@j = thread_local global i8 0
|
||||
@ -22,3 +20,14 @@ entry:
|
||||
declare void @g(i32)
|
||||
|
||||
declare void @h(i32)
|
||||
|
||||
; X32_LINUX: movsbl %gs:i@NTPOFF, %eax
|
||||
; X32_LINUX: movzbl %gs:j@NTPOFF, %eax
|
||||
; X64_LINUX: movsbl %fs:i@TPOFF, %edi
|
||||
; X64_LINUX: movzbl %fs:j@TPOFF, %edi
|
||||
; X32_WIN: movsbl _i@SECREL(%esi), %eax
|
||||
; X32_WIN: movzbl _j@SECREL(%esi), %eax
|
||||
; X64_WIN: movabsq $i@SECREL, %rax
|
||||
; X64_WIN: movsbl (%rsi,%rax), %ecx
|
||||
; X64_WIN: movabsq $j@SECREL, %rax
|
||||
; X64_WIN: movzbl (%rsi,%rax), %ecx
|
||||
|
@ -1,9 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movl %gs:0, %eax} %t
|
||||
; RUN: grep {leal i@NTPOFF(%eax), %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movq %fs:0, %rax} %t2
|
||||
; RUN: grep {leaq i@TPOFF(%rax), %rax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = thread_local global i32 15
|
||||
|
||||
@ -11,3 +9,13 @@ define i32* @f() {
|
||||
entry:
|
||||
ret i32* @i
|
||||
}
|
||||
; X32_LINUX: movl %gs:0, %eax
|
||||
; X32_LINUX: leal i@NTPOFF(%eax), %eax
|
||||
; X64_LINUX: movq %fs:0, %rax
|
||||
; X64_LINUX: leaq i@TPOFF(%rax), %rax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: leal _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movq %gs:88, %rcx
|
||||
; X64_WIN: addq $i@SECREL, %rax
|
||||
|
@ -1,9 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movl i@INDNTPOFF, %eax} %t
|
||||
; RUN: grep {movl %gs:(%eax), %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movq i@GOTTPOFF(%rip), %rax} %t2
|
||||
; RUN: grep {movl %fs:(%rax), %eax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = external thread_local global i32 ; <i32*> [#uses=2]
|
||||
|
||||
@ -12,3 +10,12 @@ entry:
|
||||
%tmp1 = load i32* @i ; <i32> [#uses=1]
|
||||
ret i32 %tmp1
|
||||
}
|
||||
; X32_LINUX: movl i@INDNTPOFF, %eax
|
||||
; X32_LINUX: movl %gs:(%eax), %eax
|
||||
; X64_LINUX: movq i@GOTTPOFF(%rip), %rax
|
||||
; X64_LINUX: movl %fs:(%rax), %eax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: movl _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movabsq $i@SECREL, %rcx
|
||||
|
@ -1,9 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movl %gs:0, %eax} %t
|
||||
; RUN: grep {addl i@INDNTPOFF, %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movq %fs:0, %rax} %t2
|
||||
; RUN: grep {addq i@GOTTPOFF(%rip), %rax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = external thread_local global i32 ; <i32*> [#uses=2]
|
||||
|
||||
@ -11,3 +9,13 @@ define i32* @f() {
|
||||
entry:
|
||||
ret i32* @i
|
||||
}
|
||||
; X32_LINUX: movl %gs:0, %eax
|
||||
; X32_LINUX: addl i@INDNTPOFF, %eax
|
||||
; X64_LINUX: movq %fs:0, %rax
|
||||
; X64_LINUX: addq i@GOTTPOFF(%rip), %rax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: leal _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movq %gs:88, %rcx
|
||||
; X64_WIN: addq $i@SECREL, %rax
|
||||
|
@ -1,7 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movl %gs:i@NTPOFF, %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movl %fs:i@TPOFF, %eax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
|
||||
@i = internal thread_local global i32 15
|
||||
|
||||
@ -10,3 +10,10 @@ entry:
|
||||
%tmp1 = load i32* @i
|
||||
ret i32 %tmp1
|
||||
}
|
||||
; X32_LINUX: movl %gs:i@NTPOFF, %eax
|
||||
; X64_LINUX: movl %fs:i@TPOFF, %eax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: movl _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movabsq $i@SECREL, %rcx
|
||||
|
@ -1,9 +1,7 @@
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu > %t
|
||||
; RUN: grep {movl %gs:0, %eax} %t
|
||||
; RUN: grep {leal i@NTPOFF(%eax), %eax} %t
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu > %t2
|
||||
; RUN: grep {movq %fs:0, %rax} %t2
|
||||
; RUN: grep {leaq i@TPOFF(%rax), %rax} %t2
|
||||
; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
|
||||
; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
|
||||
@i = internal thread_local global i32 15
|
||||
|
||||
@ -11,3 +9,13 @@ define i32* @f() {
|
||||
entry:
|
||||
ret i32* @i
|
||||
}
|
||||
; X32_LINUX: movl %gs:0, %eax
|
||||
; X32_LINUX: leal i@NTPOFF(%eax), %eax
|
||||
; X64_LINUX: movq %fs:0, %rax
|
||||
; X64_LINUX: leaq i@TPOFF(%rax), %rax
|
||||
; X32_WIN: movl __tls_index, %eax
|
||||
; X32_WIN: movl %fs:__tls_array, %ecx
|
||||
; X32_WIN: leal _i@SECREL(%eax), %eax
|
||||
; X64_WIN: movl _tls_index(%rip), %eax
|
||||
; X64_WIN: movq %gs:88, %rcx
|
||||
; X64_WIN: addq $i@SECREL, %rax
|
||||
|
Loading…
x
Reference in New Issue
Block a user