Initial codegen support for functions and calls with multiple return values.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48244 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-03-11 21:11:25 +00:00
parent e12ecf272d
commit ef5d194aaa

View File

@ -608,9 +608,7 @@ public:
void visitMemIntrinsic(CallInst &I, unsigned Op);
void visitGetResult(GetResultInst &I) {
assert (0 && "getresult unimplemented");
}
void visitGetResult(GetResultInst &I);
void visitUserOp1(Instruction &I) {
assert(0 && "UserOp1 should not exist at instruction selection time!");
@ -3246,6 +3244,12 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
}
void SelectionDAGLowering::visitGetResult(GetResultInst &I) {
SDOperand Call = getValue(I.getOperand(0));
setValue(&I, SDOperand(Call.Val, I.getIndex()));
}
/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from
/// this value and returns the result as a ValueVT value. This uses
/// Chain/Flag as the input and updates them for the output Chain/Flag.
@ -4233,21 +4237,36 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
}
}
// Figure out the result value types.
MVT::ValueType VT = getValueType(RetTy);
MVT::ValueType RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
SmallVector<MVT::ValueType, 4> RetTys(NumRegs);
for (unsigned i = 0; i != NumRegs; ++i)
RetTys[i] = RegisterVT;
// Figure out the result value types. We start by making a list of
// the high-level LLVM return types.
SmallVector<const Type *, 4> LLVMRetTys;
if (const StructType *ST = dyn_cast<StructType>(RetTy))
// A struct return type in the LLVM IR means we have multiple return values.
LLVMRetTys.insert(LLVMRetTys.end(), ST->element_begin(), ST->element_end());
else
LLVMRetTys.push_back(RetTy);
// Then we translate that to a list of lowered codegen result types.
SmallVector<MVT::ValueType, 4> LoweredRetTys;
SmallVector<MVT::ValueType, 4> RetTys;
for (unsigned I = 0, E = LLVMRetTys.size(); I != E; ++I) {
MVT::ValueType VT = getValueType(LLVMRetTys[I]);
RetTys.push_back(VT);
MVT::ValueType RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
for (unsigned i = 0; i != NumRegs; ++i)
LoweredRetTys.push_back(RegisterVT);
}
RetTys.push_back(MVT::Other); // Always has a chain.
LoweredRetTys.push_back(MVT::Other); // Always has a chain.
// Create the CALL node.
SDOperand Res = DAG.getNode(ISD::CALL,
DAG.getVTList(&RetTys[0], NumRegs + 1),
DAG.getVTList(&LoweredRetTys[0],
LoweredRetTys.size()),
&Ops[0], Ops.size());
Chain = Res.getValue(NumRegs);
Chain = Res.getValue(LoweredRetTys.size() - 1);
// Gather up the call result into a single value.
if (RetTy != Type::VoidTy) {
@ -4258,11 +4277,25 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
else if (RetZExt)
AssertOp = ISD::AssertZext;
SmallVector<SDOperand, 4> Results(NumRegs);
for (unsigned i = 0; i != NumRegs; ++i)
Results[i] = Res.getValue(i);
Res = getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT,
AssertOp);
SmallVector<SDOperand, 4> ReturnValues;
unsigned RegNo = 0;
for (unsigned I = 0, E = LLVMRetTys.size(); I != E; ++I) {
MVT::ValueType VT = getValueType(LLVMRetTys[I]);
MVT::ValueType RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT);
unsigned RegNoEnd = NumRegs + RegNo;
SmallVector<SDOperand, 4> Results;
for (; RegNo != RegNoEnd; ++RegNo)
Results.push_back(Res.getValue(RegNo));
SDOperand ReturnValue =
getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT,
AssertOp);
ReturnValues.push_back(ReturnValue);
}
Res = ReturnValues.size() == 1 ? ReturnValues.front() :
DAG.getNode(ISD::MERGE_VALUES,
DAG.getVTList(&RetTys[0], RetTys.size()),
&ReturnValues[0], ReturnValues.size());
}
return std::make_pair(Res, Chain);