diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-02-03 19:12:28 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-02-03 19:12:28 +0000 |
commit | 89c9d8e7f0700d27b1d93dc3832eb1af9b92c221 (patch) | |
tree | 7828a17cf1d18daa07ebba25aaf9396a3d4da268 /lib/CodeGen/CGCall.cpp | |
parent | 598d3f61b6ca854e9d3c2f3359e24468502a61aa (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.cpp | 43 |
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()) |