Handle foreign error conventions in foreign-to-native thunks.

Swift SVN r27737
This commit is contained in:
John McCall
2015-04-26 00:12:52 +00:00
parent f6090c1c89
commit d84a95f325
7 changed files with 188 additions and 122 deletions

View File

@@ -756,117 +756,6 @@ void SILGenFunction::emitCurryThunk(FuncDecl *fd,
B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(fd), toClosure);
}
static SILValue
getThunkedForeignFunctionRef(SILGenFunction &gen,
SILLocation loc,
SILDeclRef foreign,
ArrayRef<ManagedValue> args) {
assert(!foreign.isCurried
&& "should not thunk calling convention when curried");
// Produce a class_method when thunking ObjC methods.
auto foreignTy = gen.SGM.getConstantType(foreign);
if (foreignTy.castTo<SILFunctionType>()->getRepresentation()
== SILFunctionTypeRepresentation::ObjCMethod) {
SILValue thisArg = args.back().getValue();
return gen.B.createClassMethod(loc, thisArg, foreign,
gen.SGM.getConstantType(foreign),
/*volatile*/ true);
}
// Otherwise, emit a function_ref.
return gen.emitGlobalFunctionRef(loc, foreign);
}
void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
assert(!thunk.isForeign && "foreign-to-native thunks only");
// Wrap the function in its original form.
auto fd = cast<AbstractFunctionDecl>(thunk.getDecl());
auto ci = getConstantInfo(thunk);
auto resultTy = ci.LoweredInterfaceType->getResult();
// Forward the arguments.
auto forwardedPatterns = fd->getBodyParamPatterns();
// For allocating constructors, 'self' is a metatype, not the 'self' value
// formally present in the constructor body.
Type allocatorSelfType;
if (thunk.kind == SILDeclRef::Kind::Allocator) {
allocatorSelfType = forwardedPatterns[0]->getType();
forwardedPatterns = forwardedPatterns.slice(1);
}
SmallVector<SILValue, 8> args;
for (auto *paramPattern : reversed(forwardedPatterns))
bindParametersForForwarding(paramPattern, args);
if (allocatorSelfType) {
auto selfMetatype = CanMetatypeType::get(allocatorSelfType->getCanonicalType(),
MetatypeRepresentation::Thick);
auto selfArg = new (F.getModule()) SILArgument(
F.begin(),
SILType::getPrimitiveObjectType(selfMetatype),
fd->getImplicitSelfDecl());
args.push_back(selfArg);
}
SILValue result;
{
CleanupLocation cleanupLoc(fd);
Scope scope(Cleanups, fd);
SILDeclRef original = thunk.asForeign(!thunk.isForeign);
auto originalInfo = getConstantInfo(original);
auto thunkFnTy = ci.getSILType().castTo<SILFunctionType>();
auto originalFnTy = originalInfo.getSILType().castTo<SILFunctionType>();
// Bridge all the arguments.
SmallVector<ManagedValue, 8> managedArgs;
for (unsigned i : indices(args)) {
auto arg = args[i];
auto thunkParam = thunkFnTy->getParameters()[i];
// Bring the argument to +1.
// TODO: Could avoid a retain if the bridged parameter is also +0 and
// doesn't require a bridging conversion.
ManagedValue mv;
switch (thunkParam.getConvention()) {
case ParameterConvention::Direct_Owned:
mv = emitManagedRValueWithCleanup(arg);
break;
case ParameterConvention::Direct_Guaranteed:
case ParameterConvention::Direct_Unowned:
mv = emitManagedRetain(fd, arg);
break;
case ParameterConvention::Direct_Deallocating:
mv = ManagedValue::forUnmanaged(arg);
break;
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Indirect_Out:
case ParameterConvention::Indirect_Inout:
llvm_unreachable("indirect args in foreign thunked method not implemented");
}
auto origArg = originalFnTy->getParameters()[i].getSILType();
managedArgs.push_back(emitNativeToBridgedValue(fd, mv,
SILFunctionTypeRepresentation::CFunctionPointer,
AbstractionPattern(mv.getSwiftType()),
mv.getSwiftType(),
origArg.getSwiftRValueType()));
}
// Call the original.
auto fn = getThunkedForeignFunctionRef(*this, fd, original,
managedArgs);
result = emitMonomorphicApply(fd, ManagedValue::forUnmanaged(fn),
managedArgs, resultTy->getCanonicalType())
.forward(*this);
}
B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(fd), result);
}
void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) {
MagicFunctionName = SILGenModule::getMagicFunctionName(function);