@@ -3925,9 +3925,6 @@ SDValue PPCTargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG) const {
39253925
39263926SDValue PPCTargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
39273927 SelectionDAG &DAG) const {
3928- if (Subtarget.isAIXABI())
3929- report_fatal_error("ADJUST_TRAMPOLINE operation is not supported on AIX.");
3930-
39313928 return Op.getOperand(0);
39323929}
39333930
@@ -3984,16 +3981,72 @@ SDValue PPCTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
39843981
39853982SDValue PPCTargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
39863983 SelectionDAG &DAG) const {
3987- if (Subtarget.isAIXABI())
3988- report_fatal_error("INIT_TRAMPOLINE operation is not supported on AIX.");
3989-
39903984 SDValue Chain = Op.getOperand(0);
39913985 SDValue Trmp = Op.getOperand(1); // trampoline
39923986 SDValue FPtr = Op.getOperand(2); // nested function
39933987 SDValue Nest = Op.getOperand(3); // 'nest' parameter value
39943988 SDLoc dl(Op);
39953989
39963990 EVT PtrVT = getPointerTy(DAG.getDataLayout());
3991+
3992+ if (Subtarget.isAIXABI()) {
3993+ // On AIX we create a trampoline descriptor by combining the
3994+ // entry point and TOC from the global descriptor (FPtr) with the
3995+ // nest argument as the environment pointer.
3996+ uint64_t PointerSize = Subtarget.isPPC64() ? 8 : 4;
3997+ MaybeAlign PointerAlign(PointerSize);
3998+ auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
3999+ ? (MachineMemOperand::MODereferenceable |
4000+ MachineMemOperand::MOInvariant)
4001+ : MachineMemOperand::MONone;
4002+
4003+ uint64_t TOCPointerOffset = 1 * PointerSize;
4004+ uint64_t EnvPointerOffset = 2 * PointerSize;
4005+ SDValue SDTOCPtrOffset = DAG.getConstant(TOCPointerOffset, dl, PtrVT);
4006+ SDValue SDEnvPtrOffset = DAG.getConstant(EnvPointerOffset, dl, PtrVT);
4007+
4008+ const Value *TrampolineAddr =
4009+ cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
4010+ const Function *Func =
4011+ cast<Function>(cast<SrcValueSDNode>(Op.getOperand(5))->getValue());
4012+
4013+ SDValue OutChains[3];
4014+
4015+ // Copy the entry point address from the global descriptor to the
4016+ // trampoline buffer.
4017+ SDValue LoadEntryPoint =
4018+ DAG.getLoad(PtrVT, dl, Chain, FPtr, MachinePointerInfo(Func, 0),
4019+ PointerAlign, MMOFlags);
4020+ SDValue EPLoadChain = LoadEntryPoint.getValue(1);
4021+ OutChains[0] = DAG.getStore(EPLoadChain, dl, LoadEntryPoint, Trmp,
4022+ MachinePointerInfo(TrampolineAddr, 0));
4023+
4024+ // Copy the TOC pointer from the global descriptor to the trampoline
4025+ // buffer.
4026+ SDValue TOCFromDescriptorPtr =
4027+ DAG.getNode(ISD::ADD, dl, PtrVT, FPtr, SDTOCPtrOffset);
4028+ SDValue TOCReg = DAG.getLoad(PtrVT, dl, Chain, TOCFromDescriptorPtr,
4029+ MachinePointerInfo(Func, TOCPointerOffset),
4030+ PointerAlign, MMOFlags);
4031+ SDValue TrampolineTOCPointer =
4032+ DAG.getNode(ISD::ADD, dl, PtrVT, Trmp, SDTOCPtrOffset);
4033+ SDValue TOCLoadChain = TOCReg.getValue(1);
4034+ OutChains[1] =
4035+ DAG.getStore(TOCLoadChain, dl, TOCReg, TrampolineTOCPointer,
4036+ MachinePointerInfo(TrampolineAddr, TOCPointerOffset));
4037+
4038+ // Store the nest argument into the environment pointer in the trampoline
4039+ // buffer.
4040+ SDValue EnvPointer = DAG.getNode(ISD::ADD, dl, PtrVT, Trmp, SDEnvPtrOffset);
4041+ OutChains[2] =
4042+ DAG.getStore(Chain, dl, Nest, EnvPointer,
4043+ MachinePointerInfo(TrampolineAddr, EnvPointerOffset));
4044+
4045+ SDValue TokenFactor =
4046+ DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
4047+ return TokenFactor;
4048+ }
4049+
39974050 bool isPPC64 = (PtrVT == MVT::i64);
39984051 Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
39994052
@@ -6865,9 +6918,6 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
68656918 if (ValVT == MVT::f128)
68666919 report_fatal_error("f128 is unimplemented on AIX.");
68676920
6868- if (ArgFlags.isNest())
6869- report_fatal_error("Nest arguments are unimplemented.");
6870-
68716921 static const MCPhysReg GPR_32[] = {// 32-bit registers.
68726922 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
68736923 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
@@ -6882,6 +6932,14 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
68826932
68836933 const ArrayRef<MCPhysReg> GPRs = IsPPC64 ? GPR_64 : GPR_32;
68846934
6935+ if (ArgFlags.isNest()) {
6936+ MCRegister EnvReg = State.AllocateReg(IsPPC64 ? PPC::X11 : PPC::R11);
6937+ if (!EnvReg)
6938+ report_fatal_error("More then one nest argument.");
6939+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, EnvReg, RegVT, LocInfo));
6940+ return false;
6941+ }
6942+
68856943 if (ArgFlags.isByVal()) {
68866944 const Align ByValAlign(ArgFlags.getNonZeroByValAlign());
68876945 if (ByValAlign > StackAlign)
0 commit comments