mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-04 01:42:09 +00:00
Make VAARG promotion work correctly with large funky
sized integers like i129, and also reduce the number of assumptions made about how vaarg is implemented. This still doesn't work correctly for small integers like (eg) i1 on x86, since x86 passes each of them (essentially an i8) in a 4 byte stack slot, so the pointer needs to be advanced by 4 bytes not by 1 byte as now. But this is no longer a LegalizeTypes problem (it was also wrong in LT before): it is a bug in the operation expansion in LegalizeDAG: now LegalizeTypes turns an i1 vaarg into an i8 vaarg which would work fine if only the i8 vaarg was turned into correct code later. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58635 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20cd13f54f
commit
d821726a91
@ -532,29 +532,37 @@ SDValue DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) {
|
||||
SDValue Ptr = N->getOperand(1); // Get the pointer.
|
||||
MVT VT = N->getValueType(0);
|
||||
|
||||
const Value *V = cast<SrcValueSDNode>(N->getOperand(2))->getValue();
|
||||
SDValue VAList = DAG.getLoad(TLI.getPointerTy(), Chain, Ptr, V, 0);
|
||||
MVT RegVT = TLI.getRegisterType(VT);
|
||||
unsigned NumRegs = TLI.getNumRegisters(VT);
|
||||
// The argument is passed as NumRegs registers of type RegVT.
|
||||
|
||||
// Increment the arg pointer, VAList, to the next vaarg
|
||||
// FIXME: should the ABI size be used for the increment? Think of
|
||||
// x86 long double (10 bytes long, but aligned on 4 or 8 bytes) or
|
||||
// integers of unusual size (such MVT::i1, which gives an increment
|
||||
// of zero here!).
|
||||
unsigned Increment = VT.getSizeInBits() / 8;
|
||||
SDValue Tmp = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList,
|
||||
DAG.getIntPtrConstant(Increment));
|
||||
SmallVector<SDValue, 8> Parts(NumRegs);
|
||||
for (unsigned i = 0; i < NumRegs; ++i) {
|
||||
Parts[i] = DAG.getVAArg(RegVT, Chain, Ptr, N->getOperand(2));
|
||||
Chain = Parts[i].getValue(1);
|
||||
}
|
||||
|
||||
// Store the incremented VAList to the pointer.
|
||||
Tmp = DAG.getStore(VAList.getValue(1), Tmp, Ptr, V, 0);
|
||||
// Handle endianness of the load.
|
||||
if (TLI.isBigEndian())
|
||||
std::reverse(Parts.begin(), Parts.end());
|
||||
|
||||
// Load the actual argument out of the arg pointer VAList.
|
||||
Tmp = DAG.getExtLoad(ISD::EXTLOAD, TLI.getTypeToTransformTo(VT), Tmp,
|
||||
VAList, NULL, 0, VT);
|
||||
// Assemble the parts in the promoted type.
|
||||
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
|
||||
SDValue Res = DAG.getNode(ISD::ZERO_EXTEND, NVT, Parts[0]);
|
||||
for (unsigned i = 1; i < NumRegs; ++i) {
|
||||
SDValue Part = DAG.getNode(ISD::ZERO_EXTEND, NVT, Parts[i]);
|
||||
// Shift it to the right position and "or" it in.
|
||||
Part = DAG.getNode(ISD::SHL, NVT, Part,
|
||||
DAG.getConstant(i * RegVT.getSizeInBits(),
|
||||
TLI.getShiftAmountTy()));
|
||||
Res = DAG.getNode(ISD::OR, NVT, Res, Part);
|
||||
}
|
||||
|
||||
// Legalized the chain result - switch anything that used the old chain to
|
||||
// Modified the chain result - switch anything that used the old chain to
|
||||
// use the new one.
|
||||
ReplaceValueWith(SDValue(N, 1), Tmp.getValue(1));
|
||||
return Tmp;
|
||||
ReplaceValueWith(SDValue(N, 1), Chain);
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user