mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Handle foreign error conventions in foreign-to-native thunks.
Swift SVN r27737
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user