@@ -6841,9 +6841,6 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
6841
6841
if (ValVT == MVT::f128)
6842
6842
report_fatal_error("f128 is unimplemented on AIX.");
6843
6843
6844
- if (ArgFlags.isByVal())
6845
- report_fatal_error("Passing structure by value is unimplemented.");
6846
-
6847
6844
if (ArgFlags.isNest())
6848
6845
report_fatal_error("Nest arguments are unimplemented.");
6849
6846
@@ -6857,6 +6854,29 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
6857
6854
PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6858
6855
PPC::X7, PPC::X8, PPC::X9, PPC::X10};
6859
6856
6857
+ if (ArgFlags.isByVal()) {
6858
+ if (ArgFlags.getNonZeroByValAlign() > PtrByteSize)
6859
+ report_fatal_error("Pass-by-value arguments with alignment greater than "
6860
+ "register width are not supported.");
6861
+
6862
+ const unsigned ByValSize = ArgFlags.getByValSize();
6863
+
6864
+ // An empty aggregate parameter takes up no storage and no registers.
6865
+ if (ByValSize == 0)
6866
+ return false;
6867
+
6868
+ if (ByValSize <= PtrByteSize) {
6869
+ State.AllocateStack(PtrByteSize, PtrByteSize);
6870
+ if (unsigned Reg = State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32)) {
6871
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, RegVT, LocInfo));
6872
+ return false;
6873
+ }
6874
+ }
6875
+
6876
+ report_fatal_error(
6877
+ "Pass-by-value arguments are only supported in a single register.");
6878
+ }
6879
+
6860
6880
// Arguments always reserve parameter save area.
6861
6881
switch (ValVT.SimpleTy) {
6862
6882
default:
@@ -7130,9 +7150,59 @@ SDValue PPCTargetLowering::LowerCall_AIX(
7130
7150
CCValAssign &VA = ArgLocs[I++];
7131
7151
7132
7152
SDValue Arg = OutVals[VA.getValNo()];
7153
+ ISD::ArgFlagsTy Flags = Outs[VA.getValNo()].Flags;
7154
+ const MVT LocVT = VA.getLocVT();
7155
+ const MVT ValVT = VA.getValVT();
7156
+
7157
+ if (Flags.isByVal()) {
7158
+ const unsigned ByValSize = Flags.getByValSize();
7159
+ assert(
7160
+ VA.isRegLoc() && ByValSize > 0 && ByValSize <= PtrByteSize &&
7161
+ "Pass-by-value arguments are only supported in a single register.");
7162
+
7163
+ // Loads must be a power-of-2 size and cannot be larger than the
7164
+ // ByValSize. For example: a 7 byte by-val arg requires 4, 2 and 1 byte
7165
+ // loads.
7166
+ SDValue RegVal;
7167
+ for (unsigned Bytes = 0; Bytes != ByValSize;) {
7168
+ unsigned N = PowerOf2Floor(ByValSize - Bytes);
7169
+ const MVT VT =
7170
+ N == 1 ? MVT::i8
7171
+ : ((N == 2) ? MVT::i16 : (N == 4 ? MVT::i32 : MVT::i64));
7172
+
7173
+ SDValue LoadAddr = Arg;
7174
+ if (Bytes != 0) {
7175
+ // Adjust the load offset by the number of bytes read so far.
7176
+ SDNodeFlags Flags;
7177
+ Flags.setNoUnsignedWrap(true);
7178
+ LoadAddr = DAG.getNode(ISD::ADD, dl, LocVT, Arg,
7179
+ DAG.getConstant(Bytes, dl, LocVT), Flags);
7180
+ }
7181
+ SDValue Load = DAG.getExtLoad(ISD::ZEXTLOAD, dl, PtrVT, Chain, LoadAddr,
7182
+ MachinePointerInfo(), VT);
7183
+ MemOpChains.push_back(Load.getValue(1));
7133
7184
7134
- if (!VA.isRegLoc() && !VA.isMemLoc())
7135
- report_fatal_error("Unexpected ___location for function call argument.");
7185
+ Bytes += N;
7186
+ assert(LocVT.getSizeInBits() >= (Bytes * 8));
7187
+ if (unsigned NumSHLBits = LocVT.getSizeInBits() - (Bytes * 8)) {
7188
+ // By-val arguments are passed left-justfied in register.
7189
+ EVT ShiftAmountTy =
7190
+ getShiftAmountTy(Load->getValueType(0), DAG.getDataLayout());
7191
+ SDValue SHLAmt = DAG.getConstant(NumSHLBits, dl, ShiftAmountTy);
7192
+ SDValue ShiftedLoad =
7193
+ DAG.getNode(ISD::SHL, dl, Load.getValueType(), Load, SHLAmt);
7194
+ RegVal = RegVal ? DAG.getNode(ISD::OR, dl, LocVT, RegVal, ShiftedLoad)
7195
+ : ShiftedLoad;
7196
+ } else {
7197
+ assert(!RegVal && Bytes == ByValSize &&
7198
+ "Pass-by-value argument handling unexpectedly incomplete.");
7199
+ RegVal = Load;
7200
+ }
7201
+ }
7202
+
7203
+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), RegVal));
7204
+ continue;
7205
+ }
7136
7206
7137
7207
switch (VA.getLocInfo()) {
7138
7208
default:
@@ -7165,20 +7235,20 @@ SDValue PPCTargetLowering::LowerCall_AIX(
7165
7235
// Custom handling is used for GPR initializations for vararg float
7166
7236
// arguments.
7167
7237
assert(VA.isRegLoc() && VA.needsCustom() && CFlags.IsVarArg &&
7168
- VA.getValVT(). isFloatingPoint() && VA.getLocVT() .isInteger() &&
7238
+ ValVT. isFloatingPoint() && LocVT .isInteger() &&
7169
7239
"Unexpected register handling for calling convention.");
7170
7240
7171
7241
SDValue ArgAsInt =
7172
- DAG.getBitcast(MVT::getIntegerVT(VA.getValVT() .getSizeInBits()), Arg);
7242
+ DAG.getBitcast(MVT::getIntegerVT(ValVT .getSizeInBits()), Arg);
7173
7243
7174
- if (Arg.getValueType().getStoreSize() == VA.getLocVT() .getStoreSize())
7244
+ if (Arg.getValueType().getStoreSize() == LocVT .getStoreSize())
7175
7245
// f32 in 32-bit GPR
7176
7246
// f64 in 64-bit GPR
7177
7247
RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgAsInt));
7178
- else if (Arg.getValueType().getSizeInBits() < VA.getLocVT() .getSizeInBits())
7248
+ else if (Arg.getValueType().getSizeInBits() < LocVT .getSizeInBits())
7179
7249
// f32 in 64-bit GPR.
7180
7250
RegsToPass.push_back(std::make_pair(
7181
- VA.getLocReg(), DAG.getZExtOrTrunc(ArgAsInt, dl, VA.getLocVT() )));
7251
+ VA.getLocReg(), DAG.getZExtOrTrunc(ArgAsInt, dl, LocVT )));
7182
7252
else {
7183
7253
// f64 in two 32-bit GPRs
7184
7254
// The 2 GPRs are marked custom and expected to be adjacent in ArgLocs.
0 commit comments