CodeGen support for aggregate-value function arguments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52156 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-06-09 21:19:23 +00:00
parent 98301c0774
commit f5025cfa68

View File

@ -4573,47 +4573,53 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
unsigned j = 1; unsigned j = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I, ++j) { I != E; ++I, ++j) {
MVT VT = getValueType(I->getType()); SmallVector<MVT, 4> ValueVTs;
ISD::ArgFlagsTy Flags; ComputeValueVTs(*this, I->getType(), ValueVTs);
unsigned OriginalAlignment = for (unsigned Value = 0, NumValues = ValueVTs.size();
getTargetData()->getABITypeAlignment(I->getType()); Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value];
const Type *ArgTy = VT.getTypeForMVT();
ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(ArgTy);
if (F.paramHasAttr(j, ParamAttr::ZExt)) if (F.paramHasAttr(j, ParamAttr::ZExt))
Flags.setZExt(); Flags.setZExt();
if (F.paramHasAttr(j, ParamAttr::SExt)) if (F.paramHasAttr(j, ParamAttr::SExt))
Flags.setSExt(); Flags.setSExt();
if (F.paramHasAttr(j, ParamAttr::InReg)) if (F.paramHasAttr(j, ParamAttr::InReg))
Flags.setInReg(); Flags.setInReg();
if (F.paramHasAttr(j, ParamAttr::StructRet)) if (F.paramHasAttr(j, ParamAttr::StructRet))
Flags.setSRet(); Flags.setSRet();
if (F.paramHasAttr(j, ParamAttr::ByVal)) { if (F.paramHasAttr(j, ParamAttr::ByVal)) {
Flags.setByVal(); Flags.setByVal();
const PointerType *Ty = cast<PointerType>(I->getType()); const PointerType *Ty = cast<PointerType>(I->getType());
const Type *ElementTy = Ty->getElementType(); const Type *ElementTy = Ty->getElementType();
unsigned FrameAlign = getByValTypeAlignment(ElementTy); unsigned FrameAlign = getByValTypeAlignment(ElementTy);
unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy); unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
// For ByVal, alignment should be passed from FE. BE will guess if // For ByVal, alignment should be passed from FE. BE will guess if
// this info is not there but there are cases it cannot get right. // this info is not there but there are cases it cannot get right.
if (F.getParamAlignment(j)) if (F.getParamAlignment(j))
FrameAlign = F.getParamAlignment(j); FrameAlign = F.getParamAlignment(j);
Flags.setByValAlign(FrameAlign); Flags.setByValAlign(FrameAlign);
Flags.setByValSize(FrameSize); Flags.setByValSize(FrameSize);
} }
if (F.paramHasAttr(j, ParamAttr::Nest)) if (F.paramHasAttr(j, ParamAttr::Nest))
Flags.setNest(); Flags.setNest();
Flags.setOrigAlign(OriginalAlignment); Flags.setOrigAlign(OriginalAlignment);
MVT RegisterVT = getRegisterType(VT); MVT RegisterVT = getRegisterType(VT);
unsigned NumRegs = getNumRegisters(VT); unsigned NumRegs = getNumRegisters(VT);
for (unsigned i = 0; i != NumRegs; ++i) { for (unsigned i = 0; i != NumRegs; ++i) {
RetVals.push_back(RegisterVT); RetVals.push_back(RegisterVT);
ISD::ArgFlagsTy MyFlags = Flags; ISD::ArgFlagsTy MyFlags = Flags;
if (NumRegs > 1 && i == 0) if (NumRegs > 1 && i == 0)
MyFlags.setSplit(); MyFlags.setSplit();
// if it isn't first piece, alignment must be 1 // if it isn't first piece, alignment must be 1
else if (i > 0) else if (i > 0)
MyFlags.setOrigAlign(1); MyFlags.setOrigAlign(1);
Ops.push_back(DAG.getArgFlags(MyFlags)); Ops.push_back(DAG.getArgFlags(MyFlags));
}
} }
} }
@ -4646,22 +4652,27 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
unsigned Idx = 1; unsigned Idx = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
++I, ++Idx) { ++I, ++Idx) {
MVT VT = getValueType(I->getType()); SmallVector<MVT, 4> ValueVTs;
MVT PartVT = getRegisterType(VT); ComputeValueVTs(*this, I->getType(), ValueVTs);
for (unsigned Value = 0, NumValues = ValueVTs.size();
Value != NumValues; ++Value) {
MVT VT = ValueVTs[Value];
MVT PartVT = getRegisterType(VT);
unsigned NumParts = getNumRegisters(VT); unsigned NumParts = getNumRegisters(VT);
SmallVector<SDOperand, 4> Parts(NumParts); SmallVector<SDOperand, 4> Parts(NumParts);
for (unsigned j = 0; j != NumParts; ++j) for (unsigned j = 0; j != NumParts; ++j)
Parts[j] = SDOperand(Result, i++); Parts[j] = SDOperand(Result, i++);
ISD::NodeType AssertOp = ISD::DELETED_NODE; ISD::NodeType AssertOp = ISD::DELETED_NODE;
if (F.paramHasAttr(Idx, ParamAttr::SExt)) if (F.paramHasAttr(Idx, ParamAttr::SExt))
AssertOp = ISD::AssertSext; AssertOp = ISD::AssertSext;
else if (F.paramHasAttr(Idx, ParamAttr::ZExt)) else if (F.paramHasAttr(Idx, ParamAttr::ZExt))
AssertOp = ISD::AssertZext; AssertOp = ISD::AssertZext;
Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT, Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT,
AssertOp)); AssertOp));
}
} }
assert(i == NumArgRegs && "Argument register count mismatch!"); assert(i == NumArgRegs && "Argument register count mismatch!");
return Ops; return Ops;
@ -4687,59 +4698,65 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
// Handle all of the outgoing arguments. // Handle all of the outgoing arguments.
for (unsigned i = 0, e = Args.size(); i != e; ++i) { for (unsigned i = 0, e = Args.size(); i != e; ++i) {
MVT VT = getValueType(Args[i].Ty); SmallVector<MVT, 4> ValueVTs;
SDOperand Op = Args[i].Node; ComputeValueVTs(*this, Args[i].Ty, ValueVTs);
ISD::ArgFlagsTy Flags; for (unsigned Value = 0, NumValues = ValueVTs.size();
unsigned OriginalAlignment = Value != NumValues; ++Value) {
getTargetData()->getABITypeAlignment(Args[i].Ty); MVT VT = ValueVTs[Value];
const Type *ArgTy = VT.getTypeForMVT();
SDOperand Op = SDOperand(Args[i].Node.Val, Args[i].Node.ResNo + Value);
ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(ArgTy);
if (Args[i].isZExt) if (Args[i].isZExt)
Flags.setZExt(); Flags.setZExt();
if (Args[i].isSExt) if (Args[i].isSExt)
Flags.setSExt(); Flags.setSExt();
if (Args[i].isInReg) if (Args[i].isInReg)
Flags.setInReg(); Flags.setInReg();
if (Args[i].isSRet) if (Args[i].isSRet)
Flags.setSRet(); Flags.setSRet();
if (Args[i].isByVal) { if (Args[i].isByVal) {
Flags.setByVal(); Flags.setByVal();
const PointerType *Ty = cast<PointerType>(Args[i].Ty); const PointerType *Ty = cast<PointerType>(Args[i].Ty);
const Type *ElementTy = Ty->getElementType(); const Type *ElementTy = Ty->getElementType();
unsigned FrameAlign = getByValTypeAlignment(ElementTy); unsigned FrameAlign = getByValTypeAlignment(ElementTy);
unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy); unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
// For ByVal, alignment should come from FE. BE will guess if this // For ByVal, alignment should come from FE. BE will guess if this
// info is not there but there are cases it cannot get right. // info is not there but there are cases it cannot get right.
if (Args[i].Alignment) if (Args[i].Alignment)
FrameAlign = Args[i].Alignment; FrameAlign = Args[i].Alignment;
Flags.setByValAlign(FrameAlign); Flags.setByValAlign(FrameAlign);
Flags.setByValSize(FrameSize); Flags.setByValSize(FrameSize);
} }
if (Args[i].isNest) if (Args[i].isNest)
Flags.setNest(); Flags.setNest();
Flags.setOrigAlign(OriginalAlignment); Flags.setOrigAlign(OriginalAlignment);
MVT PartVT = getRegisterType(VT); MVT PartVT = getRegisterType(VT);
unsigned NumParts = getNumRegisters(VT); unsigned NumParts = getNumRegisters(VT);
SmallVector<SDOperand, 4> Parts(NumParts); SmallVector<SDOperand, 4> Parts(NumParts);
ISD::NodeType ExtendKind = ISD::ANY_EXTEND; ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
if (Args[i].isSExt) if (Args[i].isSExt)
ExtendKind = ISD::SIGN_EXTEND; ExtendKind = ISD::SIGN_EXTEND;
else if (Args[i].isZExt) else if (Args[i].isZExt)
ExtendKind = ISD::ZERO_EXTEND; ExtendKind = ISD::ZERO_EXTEND;
getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT, ExtendKind); getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT, ExtendKind);
for (unsigned i = 0; i != NumParts; ++i) { for (unsigned i = 0; i != NumParts; ++i) {
// if it isn't first piece, alignment must be 1 // if it isn't first piece, alignment must be 1
ISD::ArgFlagsTy MyFlags = Flags; ISD::ArgFlagsTy MyFlags = Flags;
if (NumParts > 1 && i == 0) if (NumParts > 1 && i == 0)
MyFlags.setSplit(); MyFlags.setSplit();
else if (i != 0) else if (i != 0)
MyFlags.setOrigAlign(1); MyFlags.setOrigAlign(1);
Ops.push_back(Parts[i]); Ops.push_back(Parts[i]);
Ops.push_back(DAG.getArgFlags(MyFlags)); Ops.push_back(DAG.getArgFlags(MyFlags));
}
} }
} }
@ -4888,10 +4905,18 @@ LowerArguments(BasicBlock *LLVMBB, SelectionDAGLowering &SDL) {
unsigned a = 0; unsigned a = 0;
for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end();
AI != E; ++AI, ++a) AI != E; ++AI) {
SmallVector<MVT, 4> ValueVTs;
ComputeValueVTs(TLI, AI->getType(), ValueVTs);
unsigned NumValues = ValueVTs.size();
if (!AI->use_empty()) { if (!AI->use_empty()) {
SDL.setValue(AI, Args[a]); SmallVector<MVT, 4> LegalValueVTs(NumValues);
for (unsigned VI = 0; VI != NumValues; ++VI)
LegalValueVTs[VI] = Args[a + VI].getValueType();
SDL.setValue(AI, SDL.DAG.getNode(ISD::MERGE_VALUES,
SDL.DAG.getVTList(&LegalValueVTs[0],
NumValues),
&Args[a], NumValues));
// If this argument is live outside of the entry block, insert a copy from // If this argument is live outside of the entry block, insert a copy from
// whereever we got it to the vreg that other BB's will reference it as. // whereever we got it to the vreg that other BB's will reference it as.
DenseMap<const Value*, unsigned>::iterator VMI=FuncInfo.ValueMap.find(AI); DenseMap<const Value*, unsigned>::iterator VMI=FuncInfo.ValueMap.find(AI);
@ -4899,6 +4924,8 @@ LowerArguments(BasicBlock *LLVMBB, SelectionDAGLowering &SDL) {
SDL.CopyValueToVirtualRegister(AI, VMI->second); SDL.CopyValueToVirtualRegister(AI, VMI->second);
} }
} }
a += NumValues;
}
// Finally, if the target has anything special to do, allow it to do so. // Finally, if the target has anything special to do, allow it to do so.
// FIXME: this should insert code into the DAG! // FIXME: this should insert code into the DAG!