diff options
Diffstat (limited to 'lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 349 |
1 files changed, 295 insertions, 54 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1f729e3133..5610bb5ba3 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -146,6 +146,12 @@ static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) { if (Subtarget->isTargetLinux()) return new X86LinuxTargetObjectFile(); + + // @LOCALMOD-BEGIN + if (Subtarget->isTargetNaCl()) + return new TargetLoweringObjectFileNaCl(); + // @LOCALMOD-END + if (Subtarget->isTargetELF()) return new TargetLoweringObjectFileELF(); if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho()) @@ -158,6 +164,9 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) Subtarget = &TM.getSubtarget<X86Subtarget>(); X86ScalarSSEf64 = Subtarget->hasSSE2(); X86ScalarSSEf32 = Subtarget->hasSSE1(); + // @LOCALMOD-START + X86StackPtr = Subtarget->has64BitPointers() ? X86::RSP : X86::ESP; + // @LOCALMOD-END RegInfo = TM.getRegisterInfo(); TD = getDataLayout(); @@ -179,7 +188,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setSchedulingPreference(Sched::ILP); else setSchedulingPreference(Sched::RegPressure); - setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister()); + setStackPointerRegisterToSaveRestore(X86StackPtr); // @LOCALMOD // Bypass i32 with i8 on Atom when compiling with O2 if (Subtarget->hasSlowDivide() && TM.getOptLevel() >= CodeGenOpt::Default) @@ -542,7 +551,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setOperationAction(ISD::EHSELECTION, MVT::i64, Expand); setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); - if (Subtarget->is64Bit()) { + if (Subtarget->has64BitPointers()) { setExceptionPointerRegister(X86::RAX); setExceptionSelectorRegister(X86::RDX); } else { @@ -573,13 +582,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho()) - setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ? + setOperationAction(ISD::DYNAMIC_STACKALLOC, + Subtarget->has64BitPointers() ? // @LOCALMOD MVT::i64 : MVT::i32, Custom); else if (TM.Options.EnableSegmentedStacks) - setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ? + setOperationAction(ISD::DYNAMIC_STACKALLOC, + Subtarget->has64BitPointers() ? // @LOCALMOD MVT::i64 : MVT::i32, Custom); else - setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ? + setOperationAction(ISD::DYNAMIC_STACKALLOC, + Subtarget->has64BitPointers() ? // @LOCALMOD MVT::i64 : MVT::i32, Expand); if (!TM.Options.UseSoftFloat && X86ScalarSSEf64) { @@ -1273,6 +1285,14 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setTargetDAGCombine(ISD::MUL); setTargetDAGCombine(ISD::XOR); + // @LOCALMOD-BEGIN + if (Subtarget->isTargetNaCl()) { + setOperationAction(ISD::NACL_TP_TLS_OFFSET, MVT::i32, Custom); + setOperationAction(ISD::NACL_TP_TDB_OFFSET, MVT::i32, Custom); + setOperationAction(ISD::NACL_TARGET_ARCH, MVT::i32, Custom); + } + // @LOCALMOD-END + computeRegisterProperties(); // On Darwin, -Os means optimize for size without hurting performance, @@ -1617,7 +1637,16 @@ X86TargetLowering::LowerReturn(SDValue Chain, "SRetReturnReg should have been set in LowerFormalArguments()."); SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy()); - Chain = DAG.getCopyToReg(Chain, dl, X86::RAX, Val, Flag); + // @LOCALMOD-START + if (Subtarget->isTargetNaCl()) { + // NaCl 64 uses 32-bit pointers, so there might be some zero-ext needed. + SDValue Zext = DAG.getZExtOrTrunc(Val, dl, MVT::i64); + Chain = DAG.getCopyToReg(Chain, dl, X86::RAX, Zext, Flag); + } else { + Chain = DAG.getCopyToReg(Chain, dl, X86::RAX, Val, Flag); + } + // @LOCALMOD-END + Flag = Chain.getValue(1); // RAX now acts like a return value. @@ -1981,7 +2010,9 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>(); unsigned Reg = FuncInfo->getSRetReturnReg(); if (!Reg) { - Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); + // @LOCALMOD + Reg = MF.getRegInfo().createVirtualRegister( + getRegClassFor(getPointerTy())); FuncInfo->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); @@ -2350,7 +2381,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } else if (!IsSibcall && (!isTailCall || isByVal)) { assert(VA.isMemLoc()); if (StackPtr.getNode() == 0) - StackPtr = DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(), + StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr, // @LOCALMOD getPointerTy()); MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg, dl, DAG, VA, Flags)); @@ -2440,7 +2471,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SDValue Source = DAG.getIntPtrConstant(VA.getLocMemOffset()); if (StackPtr.getNode() == 0) StackPtr = DAG.getCopyFromReg(Chain, dl, - RegInfo->getStackRegister(), + X86StackPtr, // @LOCALMOD getPointerTy()); Source = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, Source); @@ -3049,7 +3080,8 @@ SDValue X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const { FuncInfo->setRAIndex(ReturnAddrIndex); } - return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy()); + return DAG.getFrameIndex(ReturnAddrIndex, // @LOCALMOD + Subtarget->is64Bit() ? MVT::i64 : MVT::i32); } @@ -7563,7 +7595,8 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { static SDValue GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, SDValue *InFlag, const EVT PtrVT, unsigned ReturnReg, - unsigned char OperandFlags, bool LocalDynamic = false) { + unsigned char OperandFlags, + unsigned Opcode = X86ISD::TLSADDR) { // @LOCALMOD MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); DebugLoc dl = GA->getDebugLoc(); @@ -7571,16 +7604,12 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, GA->getValueType(0), GA->getOffset(), OperandFlags); - - X86ISD::NodeType CallType = LocalDynamic ? X86ISD::TLSBASEADDR - : X86ISD::TLSADDR; - if (InFlag) { SDValue Ops[] = { Chain, TGA, *InFlag }; - Chain = DAG.getNode(CallType, dl, NodeTys, Ops, 3); + Chain = DAG.getNode(Opcode, dl, NodeTys, Ops, 3); // @LOCALMOD } else { SDValue Ops[] = { Chain, TGA }; - Chain = DAG.getNode(CallType, dl, NodeTys, Ops, 2); + Chain = DAG.getNode(Opcode, dl, NodeTys, Ops, 2); // @LOCALMOD } // TLSADDR will be codegen'ed as call. Inform MFI that function has calls. @@ -7612,6 +7641,52 @@ LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG, X86::RAX, X86II::MO_TLSGD); } +// Lower ISD::GlobalTLSAddress using the "initial exec" or "local exec" model. +static SDValue +LowerToTLSExecCall(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const EVT PtrVT, TLSModel::Model model, bool is64Bit) { + + // See: http://code.google.com/p/nativeclient/issues/detail?id=1685 + unsigned char TargetFlag; + unsigned Opcode; + if (model == TLSModel::LocalExec) { + TargetFlag = is64Bit ? X86II::MO_TPOFF : X86II::MO_NTPOFF; + Opcode = X86ISD::TLSADDR_LE; + } else if (model == TLSModel::InitialExec) { + TargetFlag = is64Bit ? X86II::MO_GOTTPOFF : X86II::MO_INDNTPOFF; + Opcode = X86ISD::TLSADDR_IE; + } else { + llvm_unreachable("Unknown TLS model"); + } + + return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, + X86::EAX, // PtrVT is 32-bit. + TargetFlag, Opcode); +} + +// @LOCALMOD-START +// Lower TLS accesses to a function call, rather than use segment registers. +// Lower ISD::GlobalTLSAddress for NaCl 64 bit. +static SDValue +LowerToTLSNaCl64(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const EVT PtrVT, TLSModel::Model model) { + + // See: http://code.google.com/p/nativeclient/issues/detail?id=1685 + unsigned char TargetFlag; + unsigned Opcode; + if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { + TargetFlag = X86II::MO_TLSGD; + Opcode = X86ISD::TLSADDR; + } else { + return LowerToTLSExecCall(GA, DAG, PtrVT, model, true); + } + + return GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, + X86::EAX, // PtrVT is 32-bit. + TargetFlag, Opcode); +} +// @LOCALMOD-END + static SDValue LowerToTLSLocalDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, const EVT PtrVT, @@ -7626,14 +7701,16 @@ static SDValue LowerToTLSLocalDynamicModel(GlobalAddressSDNode *GA, SDValue Base; if (is64Bit) { Base = GetTLSADDR(DAG, DAG.getEntryNode(), GA, NULL, PtrVT, X86::RAX, - X86II::MO_TLSLD, /*LocalDynamic=*/true); + X86II::MO_TLSLD, + /*Opcode=*/X86ISD::TLSBASEADDR); // @LOCALMOD } else { SDValue InFlag; SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, X86::EBX, DAG.getNode(X86ISD::GlobalBaseReg, DebugLoc(), PtrVT), InFlag); InFlag = Chain.getValue(1); Base = GetTLSADDR(DAG, Chain, GA, &InFlag, PtrVT, X86::EAX, - X86II::MO_TLSLDM, /*LocalDynamic=*/true); + X86II::MO_TLSLDM, + /*Opcode=*/X86ISD::TLSBASEADDR); // @LOCALMOD } // Note: the CleanupLocalDynamicTLSPass will remove redundant computations @@ -7717,6 +7794,11 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { if (Subtarget->isTargetELF()) { TLSModel::Model model = getTargetMachine().getTLSModel(GV); + // @LOCALMOD-START + if (Subtarget->isTargetNaCl64()) + return LowerToTLSNaCl64(GA, DAG, getPointerTy(), model); + // @LOCALMOD-END + switch (model) { case TLSModel::GeneralDynamic: if (Subtarget->is64Bit()) @@ -7727,9 +7809,16 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { Subtarget->is64Bit()); case TLSModel::InitialExec: case TLSModel::LocalExec: - return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, + // @LOCALMOD-START + if (llvm::TLSUseCall) { + return LowerToTLSExecCall(GA, DAG, getPointerTy(), model, + Subtarget->is64Bit()); + } else { + return LowerToTLSExecModel(GA, DAG, getPointerTy(), model, Subtarget->is64Bit(), getTargetMachine().getRelocationModel() == Reloc::PIC_); + } + // @LOCALMOD-END } llvm_unreachable("Unknown TLS model."); } @@ -8667,13 +8756,31 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, break; } + // @LOCALMOD-BEGIN + // This function only peeks at the data dependencies of the DAG to find + // an arith op that also defines EFLAGS. However, function calls may + // clobber EFLAGS and the data dependencies do not show that. + // When that occurs, EFLAGS must be copied via PUSHF and POPF. + // The problem is that NaCl does not allow PUSHF and POPF. + // We could try to detect such clobbers for NaCl, but for now, we + // keep this code simple, and bail out for NaCl. A further + // PeepholeOptimizer pass can do a similar optimization + // (see optimizeCompareInstr in X86InstrInfo.cpp), so it's not *so* + // bad. This function also converts "add op, -1" to DEC, which can + // help fold load/stores: + // (store m, (add (load m), -1)) -> (dec m) + // So we lose out on that. + // BUG=http://code.google.com/p/nativeclient/issues/detail?id=2711 + bool ConservativeForNaCl = Subtarget->isTargetNaCl(); + // See if we can use the EFLAGS value from the operand instead of // doing a separate TEST. TEST always sets OF and CF to 0, so unless // we prove that the arithmetic won't overflow, we can't use OF or CF. - if (Op.getResNo() != 0 || NeedOF || NeedCF) + if (Op.getResNo() != 0 || NeedOF || NeedCF || ConservativeForNaCl) // Emit a CMP with 0, which is the TEST pattern. return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op, DAG.getConstant(0, Op.getValueType())); + // @LOCALMOD-END unsigned Opcode = 0; unsigned NumOperands = 0; @@ -8903,6 +9010,10 @@ SDValue X86TargetLowering::ConvertCmpIfNecessary(SDValue Cmp, /// if it's possible. SDValue X86TargetLowering::LowerToBT(SDValue And, ISD::CondCode CC, DebugLoc dl, SelectionDAG &DAG) const { + // @LOCALMOD: NaCl validator rejects BT, BTS, and BTC. + if (Subtarget->isTargetNaCl()) + return SDValue(); + SDValue Op0 = And.getOperand(0); SDValue Op1 = And.getOperand(1); if (Op0.getOpcode() == ISD::TRUNCATE) @@ -9734,14 +9845,14 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SDValue Size = Op.getOperand(1); // FIXME: Ensure alignment here - bool Is64Bit = Subtarget->is64Bit(); - EVT SPTy = Is64Bit ? MVT::i64 : MVT::i32; + bool Has64BitPointers = Subtarget->has64BitPointers(); // @LOCALMOD + EVT SPTy = Has64BitPointers ? MVT::i64 : MVT::i32; // @LOCALMOD if (getTargetMachine().Options.EnableSegmentedStacks) { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &MRI = MF.getRegInfo(); - if (Is64Bit) { + if (Subtarget->is64Bit()) { // @LOCALMOD // The 64 bit implementation of segmented stacks needs to clobber both r10 // r11. This makes it impossible to use it along with nested parameters. const Function *F = MF.getFunction(); @@ -9754,7 +9865,7 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, } const TargetRegisterClass *AddrRegClass = - getRegClassFor(Subtarget->is64Bit() ? MVT::i64:MVT::i32); + getRegClassFor(Has64BitPointers ? MVT::i64:MVT::i32); // @LOCALMOD unsigned Vreg = MRI.createVirtualRegister(AddrRegClass); Chain = DAG.getCopyToReg(Chain, dl, Vreg, Size); SDValue Value = DAG.getNode(X86ISD::SEG_ALLOCA, dl, SPTy, Chain, @@ -9763,7 +9874,7 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, return DAG.getMergeValues(Ops1, 2, dl); } else { SDValue Flag; - unsigned Reg = (Subtarget->is64Bit() ? X86::RAX : X86::EAX); + unsigned Reg = (Has64BitPointers ? X86::RAX : X86::EAX); // @LOCALMOD Chain = DAG.getCopyToReg(Chain, dl, Reg, Size, Flag); Flag = Chain.getValue(1); @@ -9772,7 +9883,7 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Flag); Flag = Chain.getValue(1); - Chain = DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(), + Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, // @LOCALMOD SPTy).getValue(1); SDValue Ops1[2] = { Chain.getValue(0), Chain }; @@ -9801,6 +9912,7 @@ SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { // fp_offset (48 - 48 + 8 * 16) // overflow_arg_area (point to parameters coming in memory). // reg_save_area + unsigned PointerSize = TD->getPointerSize(0); // @LOCALMOD SmallVector<SDValue, 8> MemOps; SDValue FIN = Op.getOperand(1); // Store gp_offset @@ -9823,7 +9935,7 @@ SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { FIN = DAG.getNode(ISD::ADD, DL, getPointerTy(), FIN, DAG.getIntPtrConstant(4)); SDValue OVFIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), - getPointerTy()); + getPointerTy()); // @LOCALMOD Store = DAG.getStore(Op.getOperand(0), DL, OVFIN, FIN, MachinePointerInfo(SV, 8), false, false, 0); @@ -9831,11 +9943,12 @@ SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { // Store ptr to reg_save_area. FIN = DAG.getNode(ISD::ADD, DL, getPointerTy(), - FIN, DAG.getIntPtrConstant(8)); + FIN, DAG.getIntPtrConstant(PointerSize)); // @LOCALMOD SDValue RSFIN = DAG.getFrameIndex(FuncInfo->getRegSaveFrameIndex(), - getPointerTy()); + getPointerTy()); // @LOCALMOD Store = DAG.getStore(Op.getOperand(0), DL, RSFIN, FIN, - MachinePointerInfo(SV, 16), false, false, 0); + MachinePointerInfo(SV, 8+PointerSize), // @LOCALMOD + false, false, 0); MemOps.push_back(Store); return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, &MemOps[0], MemOps.size()); @@ -9845,7 +9958,8 @@ SDValue X86TargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) const { assert(Subtarget->is64Bit() && "LowerVAARG only handles 64-bit va_arg!"); assert((Subtarget->isTargetLinux() || - Subtarget->isTargetDarwin()) && + Subtarget->isTargetDarwin() || + Subtarget->isTargetNaCl()) && // @LOCALMOD "Unhandled target in LowerVAARG"); assert(Op.getNode()->getNumOperands() == 4); SDValue Chain = Op.getOperand(0); @@ -9920,11 +10034,56 @@ static SDValue LowerVACOPY(SDValue Op, const X86Subtarget *Subtarget, DebugLoc DL = Op.getDebugLoc(); return DAG.getMemcpy(Chain, DL, DstPtr, SrcPtr, - DAG.getIntPtrConstant(24), 8, /*isVolatile*/false, + // @LOCALMOD-START + // Size is actually 8 + 2 * pointer size and align + // is the pointer ABI alignment but we don't have a + // pointer to TD in this static function + DAG.getIntPtrConstant(Subtarget->has64BitPointers() ? + 24 : 16), + Subtarget->has64BitPointers() ? 8 : 4, + /*isVolatile*/false, + // @LOCALMOD-END false, MachinePointerInfo(DstSV), MachinePointerInfo(SrcSV)); } +////////////////////////////////////////////////////////////////////// +// NaCl TLS setup / layout intrinsics. +// See: native_client/src/untrusted/stubs/tls_params.h +SDValue X86TargetLowering::LowerNaClTpTlsOffset(SDValue Op, + SelectionDAG &DAG) const { + // ssize_t __nacl_tp_tls_offset (size_t tls_size) { + // return -tls_size; + // } + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ISD::SUB, dl, Op.getValueType().getSimpleVT(), + DAG.getConstant(0, Op.getValueType().getSimpleVT()), + Op.getOperand(0)); +} + +SDValue X86TargetLowering::LowerNaClTpTdbOffset(SDValue Op, + SelectionDAG &DAG) const { + // ssize_t __nacl_tp_tdb_offset (size_t tdb_size) { + // return 0; + // } + return DAG.getConstant(0, Op.getValueType().getSimpleVT()); +} + +SDValue +X86TargetLowering::LowerNaClTargetArch(SDValue Op, SelectionDAG &DAG) const { + // int __nacl_target_arch () { + // return (is_64_bit ? + // PnaclTargetArchitectureX86_64 : + // PnaclTargetArchitectureX86_32); + // } + return DAG.getConstant((Subtarget->is64Bit() ? + PnaclTargetArchitectureX86_64 : + PnaclTargetArchitectureX86_32), + Op.getValueType().getSimpleVT()); +} + +////////////////////////////////////////////////////////////////////// + // getTargetVShiftNOde - Handle vector element shifts where the shift amount // may or may not be a constant. Takes immediate version of shift as input. static SDValue getTargetVShiftNode(unsigned Opc, DebugLoc dl, EVT VT, @@ -9970,11 +10129,37 @@ 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. + return DAG.getNode(X86ISD::THREAD_POINTER_FROM_GS, dl, PtrVT); + } + } + // @LOCALMOD-END + // Comparison intrinsics. case Intrinsic::x86_sse_comieq_ss: case Intrinsic::x86_sse_comilt_ss: @@ -10570,7 +10755,7 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); - unsigned FrameReg = Subtarget->is64Bit() ? X86::RBP : X86::EBP; + unsigned FrameReg = Subtarget->has64BitPointers() ? X86::RBP : X86::EBP; // @LOCALMOD SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); while (Depth--) FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, @@ -10590,10 +10775,13 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { SDValue Handler = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); + // @LOCALMOD-START + bool Has64BitPointers = Subtarget->has64BitPointers(); SDValue Frame = DAG.getCopyFromReg(DAG.getEntryNode(), dl, - Subtarget->is64Bit() ? X86::RBP : X86::EBP, + Has64BitPointers ? X86::RBP : X86::EBP, getPointerTy()); - unsigned StoreAddrReg = (Subtarget->is64Bit() ? X86::RCX : X86::ECX); + unsigned StoreAddrReg = (Has64BitPointers ? X86::RCX : X86::ECX); + // @LOCALMOD-END SDValue StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(), Frame, DAG.getIntPtrConstant(RegInfo->getSlotSize())); @@ -11674,6 +11862,11 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); case ISD::ADD: return LowerADD(Op, DAG); case ISD::SUB: return LowerSUB(Op, DAG); + // @LOCALMOD-BEGIN + case ISD::NACL_TP_TLS_OFFSET: return LowerNaClTpTlsOffset(Op, DAG); + case ISD::NACL_TP_TDB_OFFSET: return LowerNaClTpTdbOffset(Op, DAG); + case ISD::NACL_TARGET_ARCH: return LowerNaClTargetArch(Op, DAG); + // @LOCALMOD-END } } @@ -11957,6 +12150,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::FRCP: return "X86ISD::FRCP"; case X86ISD::TLSADDR: return "X86ISD::TLSADDR"; case X86ISD::TLSBASEADDR: return "X86ISD::TLSBASEADDR"; + case X86ISD::TLSADDR_LE: return "X86ISD::TLSADDR_LE"; // @LOCALMOD + case X86ISD::TLSADDR_IE: return "X86ISD::TLSADDR_IE"; // @LOCALMOD case X86ISD::TLSCALL: return "X86ISD::TLSCALL"; case X86ISD::EH_SJLJ_SETJMP: return "X86ISD::EH_SJLJ_SETJMP"; case X86ISD::EH_SJLJ_LONGJMP: return "X86ISD::EH_SJLJ_LONGJMP"; @@ -12967,9 +13162,11 @@ X86TargetLowering::EmitVAARG64WithCustomInserter( MachineInstr::mmo_iterator MMOEnd = MI->memoperands_end(); // Machine Information + bool IsNaCl = Subtarget->isTargetNaCl(); // @LOCALMOD const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - const TargetRegisterClass *AddrRegClass = getRegClassFor(MVT::i64); + const TargetRegisterClass *AddrRegClass = + getRegClassFor(getPointerTy()); // @LOCALMOD const TargetRegisterClass *OffsetRegClass = getRegClassFor(MVT::i32); DebugLoc DL = MI->getDebugLoc(); @@ -12997,7 +13194,7 @@ X86TargetLowering::EmitVAARG64WithCustomInserter( MachineBasicBlock *overflowMBB; MachineBasicBlock *offsetMBB; MachineBasicBlock *endMBB; - + unsigned OffsetDestReg = 0; // Argument address computed by offsetMBB unsigned OverflowDestReg = 0; // Argument address computed by overflowMBB unsigned OffsetReg = 0; @@ -13078,29 +13275,39 @@ X86TargetLowering::EmitVAARG64WithCustomInserter( } // In offsetMBB, emit code to use the reg_save_area. + unsigned Opc; // @LOCALMOD if (offsetMBB) { assert(OffsetReg != 0); // Read the reg_save_area address. unsigned RegSaveReg = MRI.createVirtualRegister(AddrRegClass); - BuildMI(offsetMBB, DL, TII->get(X86::MOV64rm), RegSaveReg) + Opc = IsNaCl ? X86::MOV32rm : X86::MOV64rm; // @LOCALMOD + BuildMI(offsetMBB, DL, TII->get(Opc), RegSaveReg) // @LOCALMOD .addOperand(Base) .addOperand(Scale) .addOperand(Index) - .addDisp(Disp, 16) + .addDisp(Disp, 8+TD->getPointerSize(0)) // @LOCALMOD .addOperand(Segment) .setMemRefs(MMOBegin, MMOEnd); // Zero-extend the offset - unsigned OffsetReg64 = MRI.createVirtualRegister(AddrRegClass); - BuildMI(offsetMBB, DL, TII->get(X86::SUBREG_TO_REG), OffsetReg64) - .addImm(0) - .addReg(OffsetReg) - .addImm(X86::sub_32bit); + // @LOCALMOD-BEGIN + unsigned OffsetRegExt; + if (IsNaCl) { + OffsetRegExt = OffsetReg; + } else { + OffsetRegExt = MRI.createVirtualRegister(AddrRegClass); + BuildMI(offsetMBB, DL, TII->get(X86::SUBREG_TO_REG), OffsetRegExt) + .addImm(0) + .addReg(OffsetReg) + .addImm(X86::sub_32bit); + } + // @LOCALMOD-END // Add the offset to the reg_save_area to get the final address. - BuildMI(offsetMBB, DL, TII->get(X86::ADD64rr), OffsetDestReg) - .addReg(OffsetReg64) + Opc = IsNaCl ? X86::ADD32rr : X86::ADD64rr; // @LOCALMOD + BuildMI(offsetMBB, DL, TII->get(Opc), OffsetDestReg) + .addReg(OffsetRegExt) // @LOCALMOD .addReg(RegSaveReg); // Compute the offset for the next argument @@ -13130,7 +13337,8 @@ X86TargetLowering::EmitVAARG64WithCustomInserter( // Load the overflow_area address into a register. unsigned OverflowAddrReg = MRI.createVirtualRegister(AddrRegClass); - BuildMI(overflowMBB, DL, TII->get(X86::MOV64rm), OverflowAddrReg) + Opc = IsNaCl ? X86::MOV32rm : X86::MOV64rm; // @LOCALMOD + BuildMI(overflowMBB, DL, TII->get(Opc), OverflowAddrReg) .addOperand(Base) .addOperand(Scale) .addOperand(Index) @@ -13146,11 +13354,13 @@ X86TargetLowering::EmitVAARG64WithCustomInserter( unsigned TmpReg = MRI.createVirtualRegister(AddrRegClass); // aligned_addr = (addr + (align-1)) & ~(align-1) - BuildMI(overflowMBB, DL, TII->get(X86::ADD64ri32), TmpReg) + Opc = IsNaCl ? X86::ADD32ri : X86::ADD64ri32; // @LOCALMOD + BuildMI(overflowMBB, DL, TII->get(Opc), TmpReg) .addReg(OverflowAddrReg) .addImm(Align-1); - BuildMI(overflowMBB, DL, TII->get(X86::AND64ri32), OverflowDestReg) + Opc = IsNaCl ? X86::AND32ri : X86::AND64ri32; // @LOCALMOD + BuildMI(overflowMBB, DL, TII->get(Opc), OverflowDestReg) .addReg(TmpReg) .addImm(~(uint64_t)(Align-1)); } else { @@ -13161,12 +13371,14 @@ X86TargetLowering::EmitVAARG64WithCustomInserter( // Compute the next overflow address after this argument. // (the overflow address should be kept 8-byte aligned) unsigned NextAddrReg = MRI.createVirtualRegister(AddrRegClass); - BuildMI(overflowMBB, DL, TII->get(X86::ADD64ri32), NextAddrReg) + Opc = IsNaCl ? X86::ADD32ri : X86::ADD64ri32; // @LOCALMOD + BuildMI(overflowMBB, DL, TII->get(Opc), NextAddrReg) .addReg(OverflowDestReg) .addImm(ArgSizeA8); // Store the new overflow address. - BuildMI(overflowMBB, DL, TII->get(X86::MOV64mr)) + Opc = IsNaCl ? X86::MOV32mr : X86::MOV64mr; // @LOCALMOD + BuildMI(overflowMBB, DL, TII->get(Opc)) .addOperand(Base) .addOperand(Scale) .addOperand(Index) @@ -13541,6 +13753,25 @@ X86TargetLowering::EmitLoweredWinAlloca(MachineInstr *MI, return BB; } +// @LOCALMOD-BEGIN +MachineBasicBlock * +X86TargetLowering::EmitLoweredThreadPointerFromGs(MachineInstr *MI, + MachineBasicBlock *BB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + // This generates "movl %gs:0, %DEST", which fetches the thread + // pointer on x86-32. + BuildMI(*BB, MI, DL, TII->get(X86::MOV32rm), MI->getOperand(0).getReg()) + .addReg(/*Base=*/0) + .addImm(/*Scale=*/1) + .addReg(/*IndexReg=*/0) + .addImm(/*Disp=*/0) + .addReg(/*Segment=*/X86::GS); + MI->eraseFromParent(); + return BB; +} +// @LOCALMOD-END + MachineBasicBlock * X86TargetLowering::EmitLoweredTLSCall(MachineInstr *MI, MachineBasicBlock *BB) const { @@ -13816,6 +14047,10 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, return EmitLoweredSegAlloca(MI, BB, false); case X86::SEG_ALLOCA_64: return EmitLoweredSegAlloca(MI, BB, true); + // @LOCALMOD-BEGIN + case X86::THREAD_POINTER_FROM_GS: + return EmitLoweredThreadPointerFromGs(MI, BB); + // @LOCALMOD-END case X86::TLSCall_32: case X86::TLSCall_64: return EmitLoweredTLSCall(MI, BB); @@ -14012,6 +14247,7 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, return EmitVAStartSaveXMMRegsWithCustomInserter(MI, BB); case X86::VAARG_64: + case X86::NACL_CG_VAARG_64: return EmitVAARG64WithCustomInserter(MI, BB); case X86::EH_SjLj_SetJmp32: @@ -15698,6 +15934,12 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG, } unsigned Bits = VT.getSizeInBits(); + // @LOCALMOD-START + // Due to a limitation in NaCl's 32-bit validator, + // 16-bit shld instructions are illegal in 32-bit NaCl. + if (Subtarget->isTargetNaCl() && !Subtarget->is64Bit() && Bits == 16) + return SDValue(); + // @LOCALMOD-END if (ShAmt1.getOpcode() == ISD::SUB) { SDValue Sum = ShAmt1.getOperand(0); if (ConstantSDNode *SumC = dyn_cast<ConstantSDNode>(Sum)) { @@ -17801,4 +18043,3 @@ unsigned X86VectorTargetTransformInfo::getCastInstrCost(unsigned Opcode, return VectorTargetTransformImpl::getCastInstrCost(Opcode, Dst, Src); } - |