aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h3
-rw-r--r--include/llvm/Intrinsics.td4
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp1
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp34
-rw-r--r--lib/Target/X86/X86ISelLowering.h1
-rw-r--r--test/NaCl/ARM/nacl-read-tp-intrinsic.ll21
-rw-r--r--test/NaCl/X86/lit.local.cfg6
-rw-r--r--test/NaCl/X86/nacl-read-tp-intrinsic.ll36
8 files changed, 105 insertions, 1 deletions
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 95aafb324d..47170e4e58 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -643,6 +643,9 @@ namespace ISD {
// @LOCALMOD-BEGIN
// NACL_* - Native Client instrinsics.
+ // NACL_READ_TP is a fast built-in version of NaCl's tls_get() IRT
+ // interface.
+ NACL_READ_TP,
// These correspond to functions in:
// native_client/src/untrusted/nacl/tls_params.h
NACL_TP_TLS_OFFSET,
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 68d7d4cdf4..42b9da6914 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -467,6 +467,10 @@ def int_nacl_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_ptr_ty]>,
def int_nacl_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>,
GCCBuiltin<"__builtin_nacl_longjmp">;
+// Fast built-in version of NaCl's tls_get() IRT interface.
+def int_nacl_read_tp : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>,
+ GCCBuiltin<"__builtin_nacl_read_tp">;
+
// The following intrinsics provide target-specific implementations of
// the interface in native_client/src/untrusted/nacl/tls_params.h.
// The intrinsic names are basically the functions there without the
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 6cf8473f9d..6ab48f6244 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -2587,6 +2587,7 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG,
DebugLoc dl = Op.getDebugLoc();
switch (IntNo) {
default: return SDValue(); // Don't custom lower most intrinsics.
+ case Intrinsic::nacl_read_tp: // @LOCALMOD
case Intrinsic::arm_thread_pointer: {
EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
return DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index b0fb2f9f68..972913ea1f 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -10129,11 +10129,43 @@ static SDValue getTargetVShiftNode(unsigned Opc, DebugLoc dl, EVT VT,
return DAG.getNode(Opc, dl, VT, SrcOp, ShAmt);
}
-static SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) {
+SDValue X86TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
+ SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
switch (IntNo) {
default: return SDValue(); // Don't custom lower most intrinsics.
+
+ // @LOCALMOD-BEGIN
+ case Intrinsic::nacl_read_tp: {
+ EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+ if (Subtarget->is64Bit() || llvm::TLSUseCall) {
+ // Call __nacl_read_tp() to get the thread pointer.
+ unsigned PtrSize = PtrVT.getSizeInBits();
+ IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize);
+ SDValue ReadTpFunction = DAG.getExternalSymbol("__nacl_read_tp", PtrVT);
+ ArgListTy Args;
+ TargetLowering::CallLoweringInfo CLI(
+ DAG.getEntryNode(), PtrTy,
+ false, false, false, false, 0, CallingConv::C,
+ /*isTailCall=*/false, /*doesNotRet=*/false,
+ /*isReturnValueUsed=*/true,
+ ReadTpFunction, Args, DAG, dl);
+ std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
+ return CallResult.first;
+ } else {
+ // Get %gs:0, which contains the thread pointer on x86-32.
+ unsigned GSAddrSpace = 256;
+ Value *Ptr = Constant::getNullValue(
+ Type::getInt8PtrTy(*DAG.getContext(), GSAddrSpace));
+ return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),
+ DAG.getIntPtrConstant(0),
+ MachinePointerInfo(Ptr),
+ false, false, false, 0);
+ }
+ }
+ // @LOCALMOD-END
+
// Comparison intrinsics.
case Intrinsic::x86_sse_comieq_ss:
case Intrinsic::x86_sse_comilt_ss:
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 9c4fc95b56..39d24c35c7 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -830,6 +830,7 @@ namespace llvm {
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
diff --git a/test/NaCl/ARM/nacl-read-tp-intrinsic.ll b/test/NaCl/ARM/nacl-read-tp-intrinsic.ll
new file mode 100644
index 0000000000..3ad5181149
--- /dev/null
+++ b/test/NaCl/ARM/nacl-read-tp-intrinsic.ll
@@ -0,0 +1,21 @@
+
+; RUN: llc -mtriple=armv7-unknown-nacl -sfi-store -filetype=obj %s -o - \
+; RUN: | llvm-objdump -disassemble -r -triple armv7 - \
+; RUN: | FileCheck -check-prefix=ARM %s
+
+; RUN: llc -mtriple=armv7-unknown-nacl -sfi-store -filetype=obj -mtls-use-call %s -o - \
+; RUN: | llvm-objdump -disassemble -r -triple armv7 - \
+; RUN: | FileCheck -check-prefix=ARM_IRT %s
+
+
+declare i8* @llvm.nacl.read.tp()
+
+define i8* @get_thread_pointer() {
+ %tp = call i8* @llvm.nacl.read.tp()
+ ret i8* %tp
+}
+
+; ARM: ldr r0, [r9]
+
+; ARM_IRT: bl #
+; ARM_IRT-NEXT: __aeabi_read_tp
diff --git a/test/NaCl/X86/lit.local.cfg b/test/NaCl/X86/lit.local.cfg
new file mode 100644
index 0000000000..56bf008595
--- /dev/null
+++ b/test/NaCl/X86/lit.local.cfg
@@ -0,0 +1,6 @@
+config.suffixes = ['.ll', '.s']
+
+targets = set(config.root.targets_to_build.split())
+if not 'X86' in targets:
+ config.unsupported = True
+
diff --git a/test/NaCl/X86/nacl-read-tp-intrinsic.ll b/test/NaCl/X86/nacl-read-tp-intrinsic.ll
new file mode 100644
index 0000000000..2ad27fb6a4
--- /dev/null
+++ b/test/NaCl/X86/nacl-read-tp-intrinsic.ll
@@ -0,0 +1,36 @@
+
+; RUN: llc -mtriple=i386-unknown-nacl -filetype=obj %s -o - \
+; RUN: | llvm-objdump -disassemble r -triple i386 - \
+; RUN: | FileCheck -check-prefix=X32 %s
+
+; RUN: llc -mtriple=i386-unknown-nacl -filetype=obj -mtls-use-call %s -o - \
+; RUN: | llvm-objdump -disassemble -r -triple i386 - \
+; RUN: | FileCheck -check-prefix=X32_IRT %s
+
+; RUN: llc -mtriple=x86_64-unknown-nacl -filetype=obj %s -o - \
+; RUN: | llvm-objdump -disassemble -r -triple x86_64 - \
+; RUN: | FileCheck -check-prefix=X64 %s
+
+; "-mtls-use-call" should not make any difference on x86-64.
+; RUN: llc -mtriple=x86_64-unknown-nacl -filetype=obj -mtls-use-call %s -o - \
+; RUN: | llvm-objdump -disassemble -r -triple x86_64 - \
+; RUN: | FileCheck -check-prefix=X64 %s
+
+
+declare i8* @llvm.nacl.read.tp()
+
+define i8* @get_thread_pointer() {
+ %tp = call i8* @llvm.nacl.read.tp()
+ ret i8* %tp
+}
+
+; X32: movl %gs:0, %eax
+
+; There appears to be a bug in llvm-objdump which stops it from
+; showing the symbol name "__nacl_read_tp" in the relocation output on
+; x86-32.
+; X32_IRT: call
+; X32_IRT-NEXT: R_386_PC32 Unknown
+
+; X64: call
+; X64-NEXT: __nacl_read_tp