@@ -3925,9 +3925,6 @@ SDValue PPCTargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG) const {
3925
3925
3926
3926
SDValue PPCTargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
3927
3927
SelectionDAG &DAG) const {
3928
- if (Subtarget.isAIXABI())
3929
- report_fatal_error("ADJUST_TRAMPOLINE operation is not supported on AIX.");
3930
-
3931
3928
return Op.getOperand(0);
3932
3929
}
3933
3930
@@ -3984,16 +3981,72 @@ SDValue PPCTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
3984
3981
3985
3982
SDValue PPCTargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
3986
3983
SelectionDAG &DAG) const {
3987
- if (Subtarget.isAIXABI())
3988
- report_fatal_error("INIT_TRAMPOLINE operation is not supported on AIX.");
3989
-
3990
3984
SDValue Chain = Op.getOperand(0);
3991
3985
SDValue Trmp = Op.getOperand(1); // trampoline
3992
3986
SDValue FPtr = Op.getOperand(2); // nested function
3993
3987
SDValue Nest = Op.getOperand(3); // 'nest' parameter value
3994
3988
SDLoc dl(Op);
3995
3989
3996
3990
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
+
3997
4050
bool isPPC64 = (PtrVT == MVT::i64);
3998
4051
Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
3999
4052
@@ -6865,9 +6918,6 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
6865
6918
if (ValVT == MVT::f128)
6866
6919
report_fatal_error("f128 is unimplemented on AIX.");
6867
6920
6868
- if (ArgFlags.isNest())
6869
- report_fatal_error("Nest arguments are unimplemented.");
6870
-
6871
6921
static const MCPhysReg GPR_32[] = {// 32-bit registers.
6872
6922
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
6873
6923
PPC::R7, PPC::R8, PPC::R9, PPC::R10};
@@ -6882,6 +6932,14 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
6882
6932
6883
6933
const ArrayRef<MCPhysReg> GPRs = IsPPC64 ? GPR_64 : GPR_32;
6884
6934
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
+
6885
6943
if (ArgFlags.isByVal()) {
6886
6944
const Align ByValAlign(ArgFlags.getNonZeroByValAlign());
6887
6945
if (ByValAlign > StackAlign)
0 commit comments