Handle indirect returns in @objc methods properly.

Use CodeGenABITypes to determine which return values should be indirect
in @objc methods.

Swift SVN r11184
This commit is contained in:
Mark Lacey
2013-12-12 07:22:12 +00:00
parent a55474bc49
commit 973ece4dc9
5 changed files with 129 additions and 5 deletions

View File

@@ -59,6 +59,10 @@
#include "swift/Basic/Fallthrough.h"
#include "swift/Basic/Optional.h"
#include "swift/SIL/SILModule.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
@@ -558,7 +562,19 @@ llvm::Type *SignatureExpansion::expandResult() {
return IGM.VoidTy;
ExplosionSchema schema = IGM.getSchema(resultType, ExplosionLevel);
HasIndirectResult = schema.requiresIndirectResult(IGM);
switch (FnType->getAbstractCC()) {
case AbstractCC::C:
case AbstractCC::ObjCMethod:
HasIndirectResult =
requiresExternalIndirectResult(IGM, FnType, ExplosionLevel);
break;
case AbstractCC::Freestanding:
case AbstractCC::Method:
case AbstractCC::WitnessMethod:
HasIndirectResult = schema.requiresIndirectResult(IGM);
break;
}
if (HasIndirectResult) {
const TypeInfo &resultTI = IGM.getTypeInfo(resultType);
addPointerParameter(resultTI.getStorageType());
@@ -1528,6 +1544,21 @@ void CallEmission::setFromCallee() {
}
}
/// Given a Swift type, attempt to return an appropriate Clang
/// CanQualType for the purpose of generating correct code for the
/// ABI.
static clang::CanQualType getClangABIType(CanType swiftTy) {
// FIXME: ProtocolType generates a struct and might need special
// handling here for some platforms.
if (auto structTy = swiftTy->getAs<StructType>())
if (auto *clangDecl = structTy->getDecl()->getClangDecl()) {
auto *typeDecl = cast<clang::TypeDecl>(clangDecl);
return typeDecl->getTypeForDecl()->getCanonicalTypeUnqualified();
}
return clang::CanQualType();
}
/// Does an ObjC method or C function returning the given type require an
/// sret indirect result?
llvm::PointerType *
@@ -1538,8 +1569,27 @@ irgen::requiresExternalIndirectResult(IRGenModule &IGM,
return IGM.getStoragePointerType(fnType->getIndirectResult().getSILType());
}
// FIXME: we need to consider the target's C calling convention.
return IGM.requiresIndirectResult(fnType->getResult().getSILType(), level);
auto resultTy = fnType->getResult().getSILType();
auto clangTy = getClangABIType(resultTy.getSwiftRValueType());
// We are unable to produce an appropriate Clang type in some cases,
// so fall back on the test used for native Swift types.
if (!clangTy)
return IGM.requiresIndirectResult(fnType->getResult().getSILType(), level);
auto &ABITypes = *IGM.ABITypes;
SmallVector<clang::CanQualType,1> args;
auto extInfo = clang::FunctionType::ExtInfo();
auto &FI = ABITypes.arrangeLLVMFunctionInfo(clangTy, args, extInfo,
clang::CodeGen::RequiredArgs::All);
auto &returnInfo = FI.getReturnInfo();
if (!returnInfo.isIndirect())
return nullptr;
auto &ti = IGM.getTypeInfo(resultTy);
return ti.getStorageType()->getPointerTo();
}
/// Does an argument of this type need to be passed by value on the stack to