Index: lib/Target/Mips/MipsISelLowering.cpp |
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp |
index ff2bfb371807c4dafe00a050eccbfcc22fe52125..e27a2ff183c7fd0b2441a702de6f0d4764639fcf 100644 |
--- a/lib/Target/Mips/MipsISelLowering.cpp |
+++ b/lib/Target/Mips/MipsISelLowering.cpp |
@@ -340,6 +340,13 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, |
setOperationAction(ISD::VACOPY, MVT::Other, Expand); |
setOperationAction(ISD::VAEND, MVT::Other, Expand); |
+ // @LOCALMOD-BEGIN |
+ if (Subtarget.isTargetNaCl()) |
+ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); |
+ else |
+ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); |
+ // @LOCALMOD-END |
+ |
// Use the default for now |
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); |
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); |
@@ -1622,6 +1629,50 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, |
Subtarget.isABI_N32() || Subtarget.isABI_N64()); |
} |
+// @LOCALMOD-BEGIN |
+SDValue MipsTargetLowering:: |
+GetNaClThreadPointer(SelectionDAG &DAG, SDLoc DL) const { |
+ EVT PtrVT = getPointerTy(); |
+ SDValue ThreadPointer; |
+ if (llvm::TLSUseCall) { |
+ unsigned PtrSize = PtrVT.getSizeInBits(); |
+ IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); |
+ |
+ // We must check whether the __nacl_read_tp is defined in the module because |
+ // local and global pic functions are called differently. If the function |
+ // is local the address is calculated with %got and %lo relocations. |
+ // Otherwise, the address is calculated with %call16 relocation. |
+ const Function *NaClReadTp = NULL; |
+ const Module *M = DAG.getMachineFunction().getFunction()->getParent(); |
+ for (Module::const_iterator I = M->getFunctionList().begin(), |
+ E = M->getFunctionList().end(); I != E; ++I) { |
+ if (I->getName() == "__nacl_read_tp") { |
+ NaClReadTp = I; |
+ break; |
+ } |
+ } |
+ |
+ SDValue TlsReadTp; |
+ if (NaClReadTp == NULL) |
+ TlsReadTp = DAG.getExternalSymbol("__nacl_read_tp", PtrVT); |
+ else |
+ TlsReadTp = DAG.getGlobalAddress(NaClReadTp, DL, PtrVT); |
+ |
+ ArgListTy Args; |
+ TargetLowering::CallLoweringInfo CLI(DAG); |
+ CLI.setDebugLoc(DL).setChain(DAG.getEntryNode()) |
+ .setCallee(CallingConv::C, PtrTy, TlsReadTp, std::move(Args), 0); |
+ std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); |
+ |
+ ThreadPointer = CallResult.first; |
+ } else { |
+ ThreadPointer = DAG.getCopyFromReg(DAG.getEntryNode(), DL, |
+ Mips::T8, PtrVT); |
+ } |
+ return ThreadPointer; |
+} |
+// @LOCALMOD-END |
+ |
SDValue MipsTargetLowering:: |
lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const |
{ |
@@ -1636,6 +1687,27 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const |
TLSModel::Model model = getTargetMachine().getTLSModel(GV); |
+ // @LOCALMOD-BEGIN |
+ if (Subtarget.isTargetNaCl()) { |
+ SDVTList VTs = DAG.getVTList(MVT::i32); |
+ SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0, |
+ MipsII::MO_TPREL_HI); |
+ SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0, |
+ MipsII::MO_TPREL_LO); |
+ SDValue Hi = DAG.getNode(MipsISD::Hi, DL, VTs, TGAHi); |
+ SDValue Lo = DAG.getNode(MipsISD::Lo, DL, MVT::i32, TGALo); |
+ SDValue Offset = DAG.getNode(ISD::ADD, DL, MVT::i32, Hi, Lo); |
+ |
+ SDValue ThreadPointer = GetNaClThreadPointer(DAG, DL); |
+ // tprel_hi and tprel_lo relocations expect that thread pointer is offset |
+ // by 0x7000 from the start of the TLS data area. |
+ SDValue TPOffset = DAG.getConstant(0x7000, MVT::i32); |
+ SDValue ThreadPointer2 = DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, |
+ TPOffset); |
+ return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer2, Offset); |
+ } |
+ // @LOCALMOD-END |
+ |
if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { |
// General Dynamic and Local Dynamic TLS Model. |
unsigned Flag = (model == TLSModel::LocalDynamic) ? MipsII::MO_TLSLDM |