diff options
author | Duncan Sands <baldrick@free.fr> | 2008-11-03 20:22:12 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2008-11-03 20:22:12 +0000 |
commit | d821726a91000c1b2de7ca8aafdc27b1a311741b (patch) | |
tree | d4d3c6980336936feced2b0ad8f55c1166108486 /lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | |
parent | 20cd13f54f2b1a6307016c47330045de13b140e2 (diff) |
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
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index e0ea2338ca..653614379d 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -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); - - // 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)); + MVT RegVT = TLI.getRegisterType(VT); + unsigned NumRegs = TLI.getNumRegisters(VT); + // The argument is passed as NumRegs registers of type RegVT. + + 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; } |