Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Expr.h"
#include "swift/AST/Type.h"
#define DEBUG_TYPE "libsil"

#include "swift/AST/AnyFunctionRef.h"
Expand Down Expand Up @@ -4341,10 +4343,12 @@ static CanSILFunctionType getUncachedSILFunctionTypeForConstant(
// The type of the native-to-foreign thunk for a swift closure.
if (constant.isForeign && constant.hasClosureExpr() &&
shouldStoreClangType(TC.getDeclRefRepresentation(constant))) {
auto clangType = TC.Context.getClangFunctionType(
origLoweredInterfaceType->getParams(),
origLoweredInterfaceType->getResult(),
FunctionTypeRepresentation::CFunctionPointer);
auto clangType = extInfoBuilder.getClangTypeInfo().getType();
if (!clangType)
clangType = TC.Context.getClangFunctionType(
origLoweredInterfaceType->getParams(),
origLoweredInterfaceType->getResult(),
FunctionTypeRepresentation::CFunctionPointer);
AbstractionPattern pattern =
AbstractionPattern(origLoweredInterfaceType, clangType);
return getSILFunctionTypeForAbstractCFunction(
Expand Down Expand Up @@ -4850,15 +4854,21 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
}

static AbstractionPattern
getAbstractionPatternForConstant(ASTContext &ctx, SILDeclRef constant,
CanAnyFunctionType fnType,
getAbstractionPatternForConstant(TypeConverter &converter, ASTContext &ctx,
SILDeclRef constant, CanAnyFunctionType fnType,
unsigned numParameterLists) {
if (!constant.isForeign)
return AbstractionPattern(fnType);

if (auto *expr = constant.getAbstractClosureExpr()) {
auto &info = converter.getClosureTypeInfo(expr);
return info.OrigType;
}

auto bridgedFn = getBridgedFunction(constant);
if (!bridgedFn)
return AbstractionPattern(fnType);

const clang::Decl *clangDecl = bridgedFn->getClangDecl();
if (!clangDecl)
return AbstractionPattern(fnType);
Expand Down Expand Up @@ -4901,9 +4911,8 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
unsigned numParameterLists = constant.getParameterListCount();

// Form an abstraction pattern for bridging purposes.
AbstractionPattern bridgingFnPattern =
getAbstractionPatternForConstant(Context, constant, fnType,
numParameterLists);
AbstractionPattern bridgingFnPattern = getAbstractionPatternForConstant(
*this, Context, constant, fnType, numParameterLists);

auto extInfo = fnType->getExtInfo();
SILFunctionTypeRepresentation rep = getDeclRefRepresentation(constant);
Expand Down
31 changes: 22 additions & 9 deletions lib/SILGen/Conversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
#ifndef SWIFT_LOWERING_CONVERSION_H
#define SWIFT_LOWERING_CONVERSION_H

#include "swift/Basic/Assertions.h"
#include "swift/Basic/ExternalUnion.h"
#include "Initialization.h"
#include "SGFContext.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/ExternalUnion.h"
#include "swift/SIL/AbstractionPattern.h"
#include <optional>

namespace swift {
namespace Lowering {
Expand Down Expand Up @@ -115,6 +117,7 @@ class Conversion {

struct BridgingStorage {
bool IsExplicit;
AbstractionPattern InputOrigType;
};

/// The types we store for reabstracting contexts. In general, when
Expand Down Expand Up @@ -161,11 +164,11 @@ class Conversion {
static_assert(decltype(Types)::union_is_trivially_copyable,
"define the special members if this changes");

Conversion(KindTy kind, CanType sourceType, CanType resultType,
SILType loweredResultTy, bool isExplicit)
Conversion(KindTy kind, AbstractionPattern inputOrigType, CanType sourceType,
CanType resultType, SILType loweredResultTy, bool isExplicit)
: Kind(kind), SourceType(sourceType), ResultType(resultType),
LoweredResultType(loweredResultTy) {
Types.emplaceAggregate<BridgingStorage>(kind, isExplicit);
Types.emplaceAggregate<BridgingStorage>(kind, isExplicit, inputOrigType);
}

Conversion(AbstractionPattern inputOrigType, CanType inputSubstType,
Expand Down Expand Up @@ -236,13 +239,19 @@ class Conversion {
outputOrigType, outputSubstType, outputLoweredTy);
}

static Conversion getBridging(KindTy kind, CanType origType,
CanType resultType, SILType loweredResultTy,
bool isExplicit = false) {
static Conversion
getBridging(KindTy kind, CanType origType, CanType resultType,
SILType loweredResultTy,
std::optional<AbstractionPattern> inputOrigType = std::nullopt,
bool isExplicit = false) {
assert(isBridgingKind(kind));
assert((kind != Subtype || isAllowedConversion(origType, resultType)) &&
"disallowed conversion for subtype relationship");
return Conversion(kind, origType, resultType, loweredResultTy, isExplicit);
if (inputOrigType)
return Conversion(kind, *inputOrigType, origType, resultType,
loweredResultTy, isExplicit);
return Conversion(kind, AbstractionPattern(origType), origType, resultType,
loweredResultTy, isExplicit);
}

static Conversion getSubtype(CanType origType, CanType substType,
Expand Down Expand Up @@ -290,6 +299,10 @@ class Conversion {
return Types.get<BridgingStorage>(Kind).IsExplicit;
}

AbstractionPattern getBridgingOriginalInputType() const {
return Types.get<BridgingStorage>(Kind).InputOrigType;
}

CanType getSourceType() const {
return SourceType;
}
Expand Down
8 changes: 4 additions & 4 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4259,10 +4259,10 @@ class ArgEmitter {
loweredSubstArgType,
param.getSILStorageInterfaceType());
case SILFunctionLanguage::C:
return Conversion::getBridging(Conversion::BridgeToObjC,
arg.getSubstRValueType(),
origParamType.getType(),
param.getSILStorageInterfaceType());
return Conversion::getBridging(
Conversion::BridgeToObjC, arg.getSubstRValueType(),
origParamType.getType(), param.getSILStorageInterfaceType(),
origParamType);
}
llvm_unreachable("bad language");
}();
Expand Down
11 changes: 9 additions & 2 deletions lib/SILGen/SILGenBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1315,8 +1315,10 @@ static SILValue emitObjCUnconsumedArgument(SILGenFunction &SGF,
SILLocation loc,
SILValue arg) {
auto &lowering = SGF.getTypeLowering(arg->getType());
// If address-only, make a +1 copy and operate on that.
if (lowering.isAddressOnly() && SGF.useLoweredAddresses()) {
// If arg is non-trivial and has an address type, make a +1 copy and operate
// on that.
if (!lowering.isTrivial() && arg->getType().isAddress() &&
SGF.useLoweredAddresses()) {
auto tmp = SGF.emitTemporaryAllocation(loc, arg->getType().getObjectType());
SGF.B.createCopyAddr(loc, arg, tmp, IsNotTake, IsInitialization);
return tmp;
Expand Down Expand Up @@ -1453,6 +1455,11 @@ emitObjCThunkArguments(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk,
auto buf = SGF.emitTemporaryAllocation(loc, native.getType());
native.forwardInto(SGF, loc, buf);
native = SGF.emitManagedBufferWithCleanup(buf);
} else if (!fnConv.isSILIndirect(nativeInputs[i]) &&
native.getType().isAddress() && SGF.useLoweredAddresses()) {
// Load the value if the argument has an address type and the native
// function expects the argument to be passed directly.
native = SGF.emitManagedLoadCopy(loc, native.getValue());
}

if (nativeInputs[i].isConsumedInCaller()) {
Expand Down
19 changes: 9 additions & 10 deletions lib/SILGen/SILGenConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1348,10 +1348,9 @@ Conversion::adjustForInitialOptionalInjection() const {
case BridgeFromObjC:
case BridgeResultFromObjC:
return OptionalInjectionConversion::forInjection(
getBridging(getKind(), getSourceType().getOptionalObjectType(),
getResultType(), getLoweredResultType(),
isBridgingExplicit())
);
getBridging(getKind(), getSourceType().getOptionalObjectType(),
getResultType(), getLoweredResultType(),
getBridgingOriginalInputType(), isBridgingExplicit()));
}
llvm_unreachable("bad kind");
}
Expand All @@ -1373,9 +1372,9 @@ Conversion::adjustForInitialOptionalConversions(CanType newSourceType) const {
case BridgeToObjC:
case BridgeFromObjC:
case BridgeResultFromObjC:
return Conversion::getBridging(getKind(), newSourceType,
getResultType(), getLoweredResultType(),
isBridgingExplicit());
return Conversion::getBridging(
getKind(), newSourceType, getResultType(), getLoweredResultType(),
getBridgingOriginalInputType(), isBridgingExplicit());
}
llvm_unreachable("bad kind");
}
Expand All @@ -1394,9 +1393,9 @@ std::optional<Conversion> Conversion::adjustForInitialForceValue() const {

case BridgeToObjC: {
auto sourceOptType = getSourceType().wrapInOptionalType();
return Conversion::getBridging(ForceAndBridgeToObjC,
sourceOptType, getResultType(),
getLoweredResultType(),
return Conversion::getBridging(ForceAndBridgeToObjC, sourceOptType,
getResultType(), getLoweredResultType(),
getBridgingOriginalInputType(),
isBridgingExplicit());
}
}
Expand Down
86 changes: 53 additions & 33 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "swift/Basic/Defer.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/type_traits.h"
#include "swift/SIL/AbstractionPattern.h"
#include "swift/SIL/Consumption.h"
#include "swift/SIL/DynamicCasts.h"
#include "swift/SIL/SILArgument.h"
Expand Down Expand Up @@ -751,10 +752,10 @@ tryEmitAsBridgingConversion(SILGenFunction &SGF, Expr *E, bool isExplicit,
auto subExpr = result.SubExpr;

CanType resultType = E->getType()->getCanonicalType();
Conversion conversion =
Conversion::getBridging(kind, subExpr->getType()->getCanonicalType(),
resultType, SGF.getLoweredType(resultType),
isExplicit);
Conversion conversion = Conversion::getBridging(
kind, subExpr->getType()->getCanonicalType(), resultType,
SGF.getLoweredType(resultType), AbstractionPattern(subExpr->getType()),
isExplicit);

// Only use this special pattern for AnyErasure conversions when we're
// emitting into a peephole.
Expand Down Expand Up @@ -1731,11 +1732,21 @@ static ManagedValue emitAnyClosureExpr(SILGenFunction &SGF, Expr *e,
}
}

static ManagedValue convertCFunctionSignature(SILGenFunction &SGF,
FunctionConversionExpr *e,
SILType loweredResultTy,
llvm::function_ref<ManagedValue ()> fnEmitter) {
SILType loweredDestTy = SGF.getLoweredType(e->getType());
static ManagedValue
convertCFunctionSignature(SILGenFunction &SGF, FunctionConversionExpr *e,
SILType loweredResultTy, SGFContext C,
llvm::function_ref<ManagedValue()> fnEmitter) {
SILType loweredDestTy;
auto destTy = e->getType();
if (const auto init = C.getAsConversion()) {
SILType loweredDestOptTy = init->getConversion().getLoweredResultType();
if (auto objTy = loweredDestOptTy.getOptionalObjectType())
loweredDestTy = objTy;
else
loweredDestTy = loweredDestOptTy;
} else
loweredDestTy = SGF.getLoweredType(destTy);

ManagedValue result;

// We're converting between C function pointer types. They better be
Expand Down Expand Up @@ -1770,9 +1781,9 @@ static ManagedValue convertCFunctionSignature(SILGenFunction &SGF,
return result;
}

static
ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
FunctionConversionExpr *conversionExpr) {
static ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
FunctionConversionExpr *conversionExpr,
SGFContext C) {
auto expr = conversionExpr->getSubExpr();

// Look through base-ignored exprs to get to the function ref.
Expand Down Expand Up @@ -1806,20 +1817,33 @@ ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
#endif
semanticExpr = conv->getSubExpr()->getSemanticsProvidingExpr();
}


const clang::Type *destFnType = nullptr;

if (auto declRef = dyn_cast<DeclRefExpr>(semanticExpr)) {
setLocFromConcreteDeclRef(declRef->getDeclRef());
} else if (auto memberRef = dyn_cast<MemberRefExpr>(semanticExpr)) {
setLocFromConcreteDeclRef(memberRef->getMember());
} else if (isAnyClosureExpr(semanticExpr)) {
(void) emitAnyClosureExpr(SGF, semanticExpr,
[&](AbstractClosureExpr *closure) {
// Emit the closure body.
SGF.SGM.emitClosure(closure, SGF.getClosureTypeInfo(closure));

loc = closure;
return ManagedValue();
});
if (auto init = C.getAsConversion()) {
auto conv = init->getConversion();
auto origParamType = conv.getBridgingOriginalInputType();
if (origParamType.isClangType())
destFnType = origParamType.getClangType();
}
(void)emitAnyClosureExpr(
SGF, semanticExpr, [&](AbstractClosureExpr *closure) {
// Emit the closure body.
auto functionInfo = SGF.getClosureTypeInfo(closure);
if (destFnType) {
functionInfo.OrigType =
AbstractionPattern(functionInfo.OrigType.getType(), destFnType);
SGF.SGM.Types.withClosureTypeInfo(closure, functionInfo, [] {});
}
SGF.SGM.emitClosure(closure, functionInfo);
loc = closure;
return ManagedValue::forInContext();
});
} else {
llvm_unreachable("c function pointer converted from a non-concrete decl ref");
}
Expand Down Expand Up @@ -1855,13 +1879,10 @@ ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
}

return convertCFunctionSignature(
SGF, conversionExpr,
constantInfo.getSILType(),
[&]() -> ManagedValue {
SILValue cRef = SGF.emitGlobalFunctionRef(expr, constant);
return ManagedValue::forObjectRValueWithoutOwnership(
cRef);
});
SGF, conversionExpr, constantInfo.getSILType(), C, [&]() -> ManagedValue {
SILValue cRef = SGF.emitGlobalFunctionRef(expr, constant);
return ManagedValue::forObjectRValueWithoutOwnership(cRef);
});
}

// Change the representation without changing the signature or
Expand Down Expand Up @@ -2118,7 +2139,7 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
FunctionTypeRepresentation::CFunctionPointer) {
// A "conversion" of a DeclRef a C function pointer is done by referencing
// the thunk (or original C function) with the C calling convention.
result = emitCFunctionPointer(SGF, e);
result = emitCFunctionPointer(SGF, e, C);
} else {
// Ok, we're converting a C function pointer value to another C function
// pointer.
Expand All @@ -2128,10 +2149,9 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,

// Possibly bitcast the C function pointer to account for ABI-compatible
// parameter and result type conversions
result = convertCFunctionSignature(SGF, e, result.getType(),
[&]() -> ManagedValue {
return result;
});
result =
convertCFunctionSignature(SGF, e, result.getType(), C,
[&]() -> ManagedValue { return result; });
}
return RValue(SGF, e, result);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/SILGen/SILGenProlog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1658,7 +1658,8 @@ uint16_t SILGenFunction::emitBasicProlog(
emitIndirectResultParameters(*this, resultType, origResultType, DC);

std::optional<AbstractionPattern> origErrorType;
if (origClosureType && !origClosureType->isTypeParameterOrOpaqueArchetype()) {
if (origClosureType && !origClosureType->isTypeParameterOrOpaqueArchetype() &&
!origClosureType->isClangType()) {
origErrorType = origClosureType->getFunctionThrownErrorType();
if (origErrorType && !errorType)
errorType = origErrorType->getEffectiveThrownErrorType();
Expand Down
3 changes: 0 additions & 3 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8519,9 +8519,6 @@ class SwiftToClangBasicReader :

llvm::Expected<const clang::Type *>
ModuleFile::getClangType(ClangTypeID TID) {
if (!getContext().LangOpts.UseClangFunctionTypes)
return nullptr;

if (TID == 0)
return nullptr;

Expand Down
Loading