summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-02-25 00:59:14 +0000
committerReid Kleckner <reid@kleckner.net>2014-02-25 00:59:14 +0000
commitfab1e89de90902e0713b8af320fc83a412ef2dad (patch)
tree921cb2409f929d4180bb4ffcbed5b94fff5366d6 /clang/lib/CodeGen
parent1ce017e8cb0262730b0dcf8f722c62818752757c (diff)
downloadbcm5719-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')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp22
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp2
2 files changed, 22 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: {
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 05cb21dd190..e1c586a7d28 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1061,6 +1061,8 @@ void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI) const {
if (Ret.isIndirect() && !Ret.getInReg()) {
CanQualType PtrTy = getContext().getPointerType(FI.getReturnType());
addFieldToArgStruct(FrameFields, StackOffset, Ret, PtrTy);
+ // On Windows, the hidden sret parameter is always returned in eax.
+ Ret.setInAllocaSRet(IsWin32StructABI);
}
// Skip the 'this' parameter in ecx.
OpenPOWER on IntegriCloud