summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-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