diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-02-25 00:59:14 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-02-25 00:59:14 +0000 |
commit | fab1e89de90902e0713b8af320fc83a412ef2dad (patch) | |
tree | 921cb2409f929d4180bb4ffcbed5b94fff5366d6 /clang/lib/CodeGen/CGCall.cpp | |
parent | 1ce017e8cb0262730b0dcf8f722c62818752757c (diff) | |
download | bcm5719-llvm-fab1e89de90902e0713b8af320fc83a412ef2dad.tar.gz bcm5719-llvm-fab1e89de90902e0713b8af320fc83a412ef2dad.zip |
MS ABI: Return sret parameters when using inalloca
Previously the X86 backend would look for the sret attribute and handle
this for us. inalloca takes that all away, so we have to do the return
ourselves now.
llvm-svn: 202097
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a21e4783b60..756b0b2b605 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -940,7 +940,15 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { break; case ABIArgInfo::InAlloca: - resultType = llvm::Type::getVoidTy(getLLVMContext()); + if (retAI.getInAllocaSRet()) { + // sret things on win32 aren't void, they return the sret pointer. + QualType ret = FI.getReturnType(); + llvm::Type *ty = ConvertType(ret); + unsigned addressSpace = Context.getTargetAddressSpace(ret); + resultType = llvm::PointerType::get(ty, addressSpace); + } else { + resultType = llvm::Type::getVoidTy(getLLVMContext()); + } break; case ABIArgInfo::Indirect: { @@ -1779,7 +1787,17 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, switch (RetAI.getKind()) { case ABIArgInfo::InAlloca: - // Do nothing; aggregrates get evaluated directly into the destination. + // Aggregrates get evaluated directly into the destination. Sometimes we + // need to return the sret value in a register, though. + assert(hasAggregateEvaluationKind(RetTy)); + if (RetAI.getInAllocaSRet()) { + llvm::Function::arg_iterator EI = CurFn->arg_end(); + --EI; + llvm::Value *ArgStruct = EI; + llvm::Value *SRet = + Builder.CreateStructGEP(ArgStruct, RetAI.getInAllocaFieldIndex()); + RV = Builder.CreateLoad(SRet, "sret"); + } break; case ABIArgInfo::Indirect: { |