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