aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-02-03 19:12:28 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-02-03 19:12:28 +0000
commit89c9d8e7f0700d27b1d93dc3832eb1af9b92c221 (patch)
tree7828a17cf1d18daa07ebba25aaf9396a3d4da268 /lib/CodeGen/CGCall.cpp
parent598d3f61b6ca854e9d3c2f3359e24468502a61aa (diff)
ABI handling: Implement coercion for argument types (in addition to
return types). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63645 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r--lib/CodeGen/CGCall.cpp43
1 files changed, 39 insertions, 4 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index f80ae0dc90..fa967590ba 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -926,6 +926,9 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) {
break;
case ABIArgInfo::Coerce:
+ ArgTys.push_back(AI.getCoerceToType());
+ break;
+
case ABIArgInfo::StructRet:
assert(0 && "Invalid ABI kind for non-return argument");
@@ -1005,9 +1008,11 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
switch (AI.getKind()) {
case ABIArgInfo::StructRet:
- case ABIArgInfo::Coerce:
assert(0 && "Invalid ABI kind for non-return argument");
-
+
+ case ABIArgInfo::Coerce:
+ break;
+
case ABIArgInfo::ByVal:
Attributes |= llvm::Attribute::ByVal;
assert(AI.getByValAlignment() == 0 && "FIXME: alignment unhandled");
@@ -1105,7 +1110,21 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
case ABIArgInfo::Ignore:
break;
- case ABIArgInfo::Coerce:
+ case ABIArgInfo::Coerce: {
+ assert(AI != Fn->arg_end() && "Argument mismatch!");
+ // FIXME: This is very wasteful; EmitParmDecl is just going to
+ // drop the result in a new alloca anyway, so we could just
+ // store into that directly if we broke the abstraction down
+ // more.
+ llvm::Value *V = CreateTempAlloca(ConvertType(Ty), "coerce");
+ CreateCoercedStore(AI, V, *this);
+ // Match to what EmitParmDecl is expecting for this type.
+ if (!CodeGenFunction::hasAggregateLLVMType(Ty))
+ V = Builder.CreateLoad(V);
+ EmitParmDecl(*Arg, V);
+ break;
+ }
+
case ABIArgInfo::StructRet:
assert(0 && "Invalid ABI kind for non-return argument");
}
@@ -1213,8 +1232,23 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::Ignore:
break;
+ case ABIArgInfo::Coerce: {
+ // FIXME: Avoid the conversion through memory if possible.
+ llvm::Value *SrcPtr;
+ if (RV.isScalar()) {
+ SrcPtr = CreateTempAlloca(ConvertType(I->second), "coerce");
+ Builder.CreateStore(RV.getScalarVal(), SrcPtr);
+ } else if (RV.isComplex()) {
+ SrcPtr = CreateTempAlloca(ConvertType(I->second), "coerce");
+ StoreComplexToAddr(RV.getComplexVal(), SrcPtr, false);
+ } else
+ SrcPtr = RV.getAggregateAddr();
+ Args.push_back(CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(),
+ *this));
+ break;
+ }
+
case ABIArgInfo::StructRet:
- case ABIArgInfo::Coerce:
assert(0 && "Invalid ABI kind for non-return argument");
break;
@@ -1266,6 +1300,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
return RValue::get(llvm::UndefValue::get(ConvertType(RetTy)));
case ABIArgInfo::Coerce: {
+ // FIXME: Avoid the conversion through memory if possible.
llvm::Value *V = CreateTempAlloca(ConvertType(RetTy), "coerce");
CreateCoercedStore(CI, V, *this);
if (RetTy->isAnyComplexType())