@@ -7338,59 +7338,80 @@ static SDValue LowerFLDEXP(SDValue Op, SelectionDAG &DAG) {
73387338
73397339SDValue AArch64TargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
73407340 SelectionDAG &DAG) const {
7341- // Note: x18 cannot be used for the Nest parameter on Windows and macOS.
7342- if (Subtarget->isTargetDarwin() || Subtarget->isTargetWindows())
7343- report_fatal_error(
7344- "ADJUST_TRAMPOLINE operation is only supported on Linux.");
7345-
73467341 return Op.getOperand(0);
73477342}
73487343
73497344SDValue AArch64TargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
73507345 SelectionDAG &DAG) const {
7351-
7352- // Note: x18 cannot be used for the Nest parameter on Windows and macOS.
7353- if (Subtarget->isTargetDarwin() || Subtarget->isTargetWindows())
7354- report_fatal_error("INIT_TRAMPOLINE operation is only supported on Linux.");
7355-
73567346 SDValue Chain = Op.getOperand(0);
7357- SDValue Trmp = Op.getOperand(1); // trampoline
7347+ SDValue Trmp = Op.getOperand(1); // trampoline, >=32 bytes
73587348 SDValue FPtr = Op.getOperand(2); // nested function
73597349 SDValue Nest = Op.getOperand(3); // 'nest' parameter value
7360- SDLoc dl(Op);
73617350
7362- EVT PtrVT = getPointerTy(DAG.getDataLayout());
7363- Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
7351+ const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
73647352
7365- TargetLowering::ArgListTy Args;
7366- TargetLowering::ArgListEntry Entry;
7353+ // ldr NestReg, .+16
7354+ // ldr x17, .+20
7355+ // br x17
7356+ // .word 0
7357+ // .nest: .qword nest
7358+ // .fptr: .qword fptr
7359+ SDValue OutChains[5];
73677360
7368- Entry.Ty = IntPtrTy;
7369- Entry.Node = Trmp;
7370- Args.push_back(Entry);
7361+ const Function *Func =
7362+ cast<Function>(cast<SrcValueSDNode>(Op.getOperand(5))->getValue());
7363+ CallingConv::ID CC = Func->getCallingConv();
7364+ unsigned NestReg;
73717365
7372- if (auto *FI = dyn_cast<FrameIndexSDNode>(Trmp.getNode())) {
7373- MachineFunction &MF = DAG.getMachineFunction();
7374- MachineFrameInfo &MFI = MF.getFrameInfo();
7375- Entry.Node =
7376- DAG.getConstant(MFI.getObjectSize(FI->getIndex()), dl, MVT::i64);
7377- } else
7378- Entry.Node = DAG.getConstant(36, dl, MVT::i64);
7366+ switch (CC) {
7367+ default:
7368+ NestReg = 0x0f; // X15
7369+ case CallingConv::ARM64EC_Thunk_Native:
7370+ case CallingConv::ARM64EC_Thunk_X64:
7371+ // Must be kept in sync with AArch64CallingConv.td
7372+ NestReg = 0x04; // X4
7373+ break;
7374+ }
73797375
7380- Args.push_back(Entry);
7381- Entry.Node = FPtr;
7382- Args.push_back(Entry);
7383- Entry.Node = Nest;
7384- Args.push_back(Entry);
7376+ const char FptrReg = 0x11; // X17
73857377
7386- // Lower to a call to __trampoline_setup(Trmp, TrampSize, FPtr, ctx_reg)
7387- TargetLowering::CallLoweringInfo CLI(DAG);
7388- CLI.setDebugLoc(dl).setChain(Chain).setLibCallee(
7389- CallingConv::C, Type::getVoidTy(*DAG.getContext()),
7390- DAG.getExternalSymbol("__trampoline_setup", PtrVT), std::move(Args));
7378+ SDValue Addr = Trmp;
73917379
7392- std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
7393- return CallResult.second;
7380+ SDLoc dl(Op);
7381+ OutChains[0] = DAG.getStore(
7382+ Chain, dl, DAG.getConstant(0x58000080u | NestReg, dl, MVT::i32), Addr,
7383+ MachinePointerInfo(TrmpAddr));
7384+
7385+ Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
7386+ DAG.getConstant(4, dl, MVT::i64));
7387+ OutChains[1] = DAG.getStore(
7388+ Chain, dl, DAG.getConstant(0x580000b0u | FptrReg, dl, MVT::i32), Addr,
7389+ MachinePointerInfo(TrmpAddr, 4));
7390+
7391+ Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
7392+ DAG.getConstant(8, dl, MVT::i64));
7393+ OutChains[2] =
7394+ DAG.getStore(Chain, dl, DAG.getConstant(0xd61f0220u, dl, MVT::i32), Addr,
7395+ MachinePointerInfo(TrmpAddr, 8));
7396+
7397+ Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
7398+ DAG.getConstant(16, dl, MVT::i64));
7399+ OutChains[3] =
7400+ DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 16));
7401+
7402+ Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
7403+ DAG.getConstant(24, dl, MVT::i64));
7404+ OutChains[4] =
7405+ DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 24));
7406+
7407+ SDValue StoreToken = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
7408+
7409+ SDValue EndOfTrmp = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
7410+ DAG.getConstant(12, dl, MVT::i64));
7411+
7412+ // Call clear cache on the trampoline instructions.
7413+ return DAG.getNode(ISD::CLEAR_CACHE, dl, MVT::Other, StoreToken, Trmp,
7414+ EndOfTrmp);
73947415}
73957416
73967417SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
0 commit comments