Index: include/llvm/CodeGen/CallingConvLower.h =================================================================== --- include/llvm/CodeGen/CallingConvLower.h +++ include/llvm/CodeGen/CallingConvLower.h @@ -260,6 +260,10 @@ Locs.push_back(V); } + CCValAssign lastLoc(void) { + return Locs.back(); + } + LLVMContext &getContext() const { return Context; } MachineFunction &getMachineFunction() const { return MF; } CallingConv::ID getCallingConv() const { return CallingConv; } Index: include/llvm/Target/TargetCallingConv.h =================================================================== --- include/llvm/Target/TargetCallingConv.h +++ include/llvm/Target/TargetCallingConv.h @@ -48,6 +48,7 @@ unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate unsigned ByValSize; ///< Byval struct size + EVT OrigVt; ///< Original value type before split public: ArgFlagsTy() @@ -57,7 +58,8 @@ IsSecArgPass(0), ByValAlign(0), OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), IsCopyElisionCandidate(0), ByValSize(0) { - static_assert(sizeof(*this) == 2 * sizeof(unsigned), "flags are too big"); + static_assert(sizeof(*this) == 2 * sizeof(unsigned) + sizeof(EVT), + "flags are too big"); } bool isZExt() const { return IsZExt; } @@ -128,6 +130,9 @@ unsigned getByValSize() const { return ByValSize; } void setByValSize(unsigned S) { ByValSize = S; } + + EVT getOrigVt() const { return OrigVt; } + void setOrigVt(EVT Vt) { OrigVt = Vt; } }; /// InputArg - This struct carries flags and type information about a Index: include/llvm/Target/TargetCallingConv.td =================================================================== --- include/llvm/Target/TargetCallingConv.td +++ include/llvm/Target/TargetCallingConv.td @@ -32,6 +32,12 @@ list VTs = vts; } +/// CCIfSplitFrom - If the current argument is splited from one of the specified +/// types, apply Action A. +class CCIfSplitFrom vts, CCAction A> : CCPredicateAction { + list VTs = vts; +} + /// CCIf - If the predicate matches, apply A. class CCIf : CCPredicateAction { string Predicate = predicate; @@ -150,6 +156,12 @@ ValueType DestTy = destTy; } +/// CCPassIndirectBySamePointer - Just like CCPassIndirect except pass by the +/// same pointer. +class CCPassIndirectBySamePointer : CCAction { + ValueType DestTy = destTy; +} + /// CCDelegateTo - This action invokes the specified sub-calling-convention. It /// is successful if the specified CC matches. class CCDelegateTo : CCAction { Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -8245,6 +8245,7 @@ MyFlags.Flags.setSplitEnd(); } + MyFlags.Flags.setOrigVt(VT); CLI.Outs.push_back(MyFlags); CLI.OutVals.push_back(Parts[j]); } @@ -8701,6 +8702,7 @@ if (i == NumRegs - 1) MyFlags.Flags.setSplitEnd(); } + MyFlags.Flags.setOrigVt(VT); Ins.push_back(MyFlags); } if (NeedsRegBlock && Value == NumValues - 1) Index: utils/TableGen/CallingConvEmitter.cpp =================================================================== --- utils/TableGen/CallingConvEmitter.cpp +++ utils/TableGen/CallingConvEmitter.cpp @@ -92,7 +92,13 @@ if (i != 0) O << " ||\n " << IndentStr; O << "LocVT == " << getEnumName(getValueType(VT)); } - + } else if (Action->isSubClassOf("CCIfSplitFrom")) { + ListInit *VTs = Action->getValueAsListInit("VTs"); + for (unsigned i = 0, e = VTs->size(); i != e; ++i) { + Record *VT = VTs->getElementAsRecord(i); + if (i != 0) O << " ||\n " << IndentStr; + O << "ArgFlags.getOrigVt() == " << getEnumName(getValueType(VT)); + } } else if (Action->isSubClassOf("CCIf")) { O << Action->getValueAsString("Predicate"); } else { @@ -251,6 +257,14 @@ Record *DestTy = Action->getValueAsDef("DestTy"); O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; + } else if (Action->isSubClassOf("CCPassIndirectBySamePointer")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; + O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; + O << IndentStr << "if (!ArgFlags.isSplit()) {\n" + << IndentStr << IndentStr << "State.addLoc(State.lastLoc());\n" + << IndentStr << IndentStr << "return false;\n" + << IndentStr << "}\n"; } else if (Action->isSubClassOf("CCPassIndirect")) { Record *DestTy = Action->getValueAsDef("DestTy"); O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";