Skip to content

Commit ab5a0d2

Browse files
committed
Don't map Bool back to ObjCBool for SIL types in unbridged contexts.
When the Clang importer imports the components of a C function pointer type, it generally translates foreign types into their native equivalents, just for the convenience of Swift code working with those functions. However, this translation must be unambiguously reversible, so (among other things) it cannot do this when the native type is also a valid foreign type. Specifically, this means that the Clang importer cannot import ObjCBool as Swift.Bool in these positions because Swift.Bool corresponds directly to the C type _Bool. SIL type lowering manually reverses the type-import process using a combination of duplicated logic and an abstraction pattern which includes information about the original Clang type that was imported. This abstraction pattern is generally able to tell SIL type lowering exactly what type to reverse to. However, @convention(c) function types may appear in positions from which it is impossible to recover the original Clang function type; therefore the reversal must be faithful to the proper rules. To do this we must propagate bridgeability just as the imported would. This reversal system is absolutely crazy, and we should really just - record an unbridged function type for imported declarations and - record an unbridged function type and Clang function type for @convention (c) function types whenever we create them. But for now, it's what we've got. rdar://43656704
1 parent af392c4 commit ab5a0d2

File tree

12 files changed

+114
-44
lines changed

12 files changed

+114
-44
lines changed

include/swift/AST/ModuleLoader.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ class NominalTypeDecl;
3838

3939
enum class KnownProtocolKind : uint8_t;
4040

41+
enum class Bridgeability : unsigned {
42+
/// This context does not permit bridging at all. For example, the
43+
/// target of a C pointer.
44+
None,
45+
46+
/// This context permits all kinds of bridging. For example, the
47+
/// imported result of a method declaration.
48+
Full
49+
};
50+
4151
/// Records dependencies on files outside of the current module;
4252
/// implemented in terms of a wrapped clang::DependencyCollector.
4353
class DependencyTracker {

include/swift/SIL/TypeLowering.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace clang {
3131

3232
namespace swift {
3333
class AnyFunctionRef;
34+
enum class Bridgeability : unsigned;
3435
class ForeignErrorConvention;
3536
enum IsInitialization_t : bool;
3637
enum IsTake_t : bool;
@@ -851,6 +852,7 @@ class TypeConverter {
851852
/// Map an AST-level type to the corresponding foreign representation type we
852853
/// implicitly convert to for a given calling convention.
853854
Type getLoweredBridgedType(AbstractionPattern pattern, Type t,
855+
Bridgeability bridging,
854856
SILFunctionTypeRepresentation rep,
855857
BridgedTypePurpose purpose);
856858

@@ -871,7 +873,8 @@ class TypeConverter {
871873
/// Given a function type, yield its bridged formal type.
872874
CanAnyFunctionType getBridgedFunctionType(AbstractionPattern fnPattern,
873875
CanAnyFunctionType fnType,
874-
AnyFunctionType::ExtInfo extInfo);
876+
AnyFunctionType::ExtInfo extInfo,
877+
Bridgeability bridging);
875878

876879
/// Given a referenced value and the substituted formal type of a
877880
/// resulting l-value expression, produce the substituted formal
@@ -977,22 +980,26 @@ class TypeConverter {
977980
CanType getLoweredRValueType(AbstractionPattern origType, CanType substType);
978981

979982
Type getLoweredCBridgedType(AbstractionPattern pattern, Type t,
980-
bool canBridgeBool,
981-
bool bridgedCollectionsAreOptional);
983+
Bridgeability bridging,
984+
SILFunctionTypeRepresentation rep,
985+
BridgedTypePurpose purpose);
982986

983987
AnyFunctionType::Param
984988
getBridgedParam(SILFunctionTypeRepresentation rep,
985989
AbstractionPattern pattern,
986-
AnyFunctionType::Param param);
990+
AnyFunctionType::Param param,
991+
Bridgeability bridging);
987992

988993
void getBridgedParams(SILFunctionTypeRepresentation rep,
989994
AbstractionPattern pattern,
990995
ArrayRef<AnyFunctionType::Param> params,
991-
SmallVectorImpl<AnyFunctionType::Param> &bridged);
996+
SmallVectorImpl<AnyFunctionType::Param> &bridged,
997+
Bridgeability bridging);
992998

993999
CanType getBridgedResultType(SILFunctionTypeRepresentation rep,
9941000
AbstractionPattern pattern,
9951001
CanType result,
1002+
Bridgeability bridging,
9961003
bool suppressOptional);
9971004
};
9981005

lib/ClangImporter/ImporterImpl.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,6 @@ enum class ImportTypeKind {
181181
Enum
182182
};
183183

184-
enum class Bridgeability {
185-
/// This context does not permit bridging at all. For example, the
186-
/// target of a C pointer.
187-
None,
188-
189-
/// This context permits all kinds of bridging. For example, the
190-
/// imported result of a method declaration.
191-
Full
192-
};
193-
194184
/// Controls whether a typedef for \p type should name the fully-bridged Swift
195185
/// type or the original Clang type.
196186
///

lib/SIL/AbstractionPattern.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ static const clang::Type *getClangType(const clang::Decl *decl) {
6060
return cast<clang::ObjCPropertyDecl>(decl)->getType().getTypePtr();
6161
}
6262

63+
static Bridgeability getClangDeclBridgeability(const clang::Decl *decl) {
64+
// These declarations are always imported without bridging (for now).
65+
if (isa<clang::VarDecl>(decl) ||
66+
isa<clang::FieldDecl>(decl) ||
67+
isa<clang::IndirectFieldDecl>(decl))
68+
return Bridgeability::None;
69+
70+
// Functions and methods always use normal bridging.
71+
return Bridgeability::Full;
72+
}
73+
6374
AbstractionPattern
6475
TypeConverter::getAbstractionPattern(VarDecl *var, bool isNonObjC) {
6576
CanGenericSignature genericSig;
@@ -77,7 +88,7 @@ TypeConverter::getAbstractionPattern(VarDecl *var, bool isNonObjC) {
7788
auto contextType = var->getDeclContext()->mapTypeIntoContext(swiftType);
7889
swiftType = getLoweredBridgedType(
7990
AbstractionPattern(genericSig, swiftType, clangType),
80-
contextType,
91+
contextType, getClangDeclBridgeability(clangDecl),
8192
SILFunctionTypeRepresentation::CFunctionPointer,
8293
TypeConverter::ForMemory)->getCanonicalType();
8394
return AbstractionPattern(genericSig, swiftType, clangType);

lib/SIL/Bridging.cpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ SILType TypeConverter::getLoweredTypeOfGlobal(VarDecl *var) {
3838
AnyFunctionType::Param
3939
TypeConverter::getBridgedParam(SILFunctionTypeRepresentation rep,
4040
AbstractionPattern pattern,
41-
AnyFunctionType::Param param) {
41+
AnyFunctionType::Param param,
42+
Bridgeability bridging) {
4243
assert(!param.getParameterFlags().isInOut() &&
4344
!param.getParameterFlags().isVariadic());
4445

45-
auto bridged = getLoweredBridgedType(pattern, param.getPlainType(), rep,
46-
TypeConverter::ForArgument);
46+
auto bridged = getLoweredBridgedType(pattern, param.getPlainType(), bridging,
47+
rep, TypeConverter::ForArgument);
4748
if (!bridged) {
4849
Context.Diags.diagnose(SourceLoc(), diag::could_not_find_bridge_type,
4950
param.getPlainType());
@@ -59,20 +60,23 @@ void TypeConverter::
5960
getBridgedParams(SILFunctionTypeRepresentation rep,
6061
AbstractionPattern pattern,
6162
ArrayRef<AnyFunctionType::Param> params,
62-
SmallVectorImpl<AnyFunctionType::Param> &bridgedParams) {
63+
SmallVectorImpl<AnyFunctionType::Param> &bridgedParams,
64+
Bridgeability bridging) {
6365
for (unsigned i : indices(params)) {
6466
auto paramPattern = pattern.getFunctionParamType(i);
65-
bridgedParams.push_back(getBridgedParam(rep, paramPattern, params[i]));
67+
auto bridgedParam = getBridgedParam(rep, paramPattern, params[i], bridging);
68+
bridgedParams.push_back(bridgedParam);
6669
}
6770
}
6871

6972
/// Bridge a result type.
7073
CanType TypeConverter::getBridgedResultType(SILFunctionTypeRepresentation rep,
7174
AbstractionPattern pattern,
7275
CanType result,
76+
Bridgeability bridging,
7377
bool suppressOptional) {
7478
auto loweredType =
75-
getLoweredBridgedType(pattern, result, rep,
79+
getLoweredBridgedType(pattern, result, bridging, rep,
7680
suppressOptional
7781
? TypeConverter::ForNonOptionalResult
7882
: TypeConverter::ForResult);
@@ -89,6 +93,7 @@ CanType TypeConverter::getBridgedResultType(SILFunctionTypeRepresentation rep,
8993

9094
Type TypeConverter::getLoweredBridgedType(AbstractionPattern pattern,
9195
Type t,
96+
Bridgeability bridging,
9297
SILFunctionTypeRepresentation rep,
9398
BridgedTypePurpose purpose) {
9499
switch (rep) {
@@ -104,39 +109,46 @@ Type TypeConverter::getLoweredBridgedType(AbstractionPattern pattern,
104109
case SILFunctionTypeRepresentation::Block:
105110
// Map native types back to bridged types.
106111

107-
bool canBridgeBool = (rep == SILFunctionTypeRepresentation::ObjCMethod);
108-
109112
// Look through optional types.
110113
if (auto valueTy = t->getOptionalObjectType()) {
111114
pattern = pattern.getOptionalObjectType();
112-
auto ty = getLoweredCBridgedType(pattern, valueTy, canBridgeBool, false);
115+
auto ty = getLoweredCBridgedType(pattern, valueTy, bridging, rep,
116+
BridgedTypePurpose::ForNonOptionalResult);
113117
return ty ? OptionalType::get(ty) : ty;
114118
}
115-
return getLoweredCBridgedType(pattern, t, canBridgeBool,
116-
purpose == ForResult);
119+
return getLoweredCBridgedType(pattern, t, bridging, rep, purpose);
117120
}
118121

119122
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
120123
};
121124

122125
Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern,
123-
Type t,
124-
bool canBridgeBool,
125-
bool bridgedCollectionsAreOptional) {
126+
Type t, Bridgeability bridging,
127+
SILFunctionTypeRepresentation rep,
128+
BridgedTypePurpose purpose) {
126129
auto clangTy = pattern.isClangType() ? pattern.getClangType() : nullptr;
127130

128131
// Bridge Bool back to ObjC bool, unless the original Clang type was _Bool
129132
// or the Darwin Boolean type.
130133
auto nativeBoolTy = getBoolType();
131134
if (nativeBoolTy && t->isEqual(nativeBoolTy)) {
135+
// If we have a Clang type that was imported as Bool, it had better be
136+
// one of a small set of types.
132137
if (clangTy) {
133-
if (clangTy->isBooleanType())
138+
auto builtinTy = clangTy->castAs<clang::BuiltinType>();
139+
if (builtinTy->getKind() == clang::BuiltinType::Bool)
134140
return t;
135-
if (clangTy->isSpecificBuiltinType(clang::BuiltinType::UChar))
141+
if (builtinTy->getKind() == clang::BuiltinType::UChar)
136142
return getDarwinBooleanType();
143+
assert(builtinTy->getKind() == clang::BuiltinType::SChar);
144+
return getObjCBoolType();
137145
}
138-
if (clangTy || canBridgeBool)
146+
147+
// Otherwise, always assume ObjC methods should use ObjCBool.
148+
if (bridging != Bridgeability::None &&
149+
rep == SILFunctionTypeRepresentation::ObjCMethod)
139150
return getObjCBoolType();
151+
140152
return t;
141153
}
142154

@@ -180,12 +192,13 @@ Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern,
180192
// so we use the ObjCMethod representation.
181193
SmallVector<AnyFunctionType::Param, 8> newParams;
182194
getBridgedParams(SILFunctionType::Representation::ObjCMethod,
183-
pattern, funTy->getParams(), newParams);
195+
pattern, funTy->getParams(), newParams, bridging);
184196

185197
Type newResult =
186198
getBridgedResultType(SILFunctionType::Representation::ObjCMethod,
187199
pattern.getFunctionResultType(),
188200
funTy->getResult()->getCanonicalType(),
201+
bridging,
189202
/*non-optional*/false);
190203

191204
return FunctionType::get(newParams, newResult,
@@ -213,7 +226,7 @@ Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern,
213226
M.getASTContext().Id_ObjectiveCType,
214227
nullptr);
215228
assert(bridgedTy && "Missing _ObjectiveCType witness?");
216-
if (bridgedCollectionsAreOptional && clangTy)
229+
if (purpose == BridgedTypePurpose::ForResult && clangTy)
217230
bridgedTy = OptionalType::get(bridgedTy);
218231
return bridgedTy;
219232
}

lib/SIL/SILFunctionType.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,7 +2530,8 @@ SILFunctionType::substGenericArgs(SILModule &silModule,
25302530
CanAnyFunctionType
25312531
TypeConverter::getBridgedFunctionType(AbstractionPattern pattern,
25322532
CanAnyFunctionType t,
2533-
AnyFunctionType::ExtInfo extInfo) {
2533+
AnyFunctionType::ExtInfo extInfo,
2534+
Bridgeability bridging) {
25342535
// Pull out the generic signature.
25352536
CanGenericSignature genericSig = t.getOptGenericSignature();
25362537

@@ -2551,12 +2552,13 @@ TypeConverter::getBridgedFunctionType(AbstractionPattern pattern,
25512552
case SILFunctionTypeRepresentation::Block:
25522553
case SILFunctionTypeRepresentation::ObjCMethod: {
25532554
SmallVector<AnyFunctionType::Param, 8> params;
2554-
getBridgedParams(rep, pattern, t->getParams(), params);
2555+
getBridgedParams(rep, pattern, t->getParams(), params, bridging);
25552556

25562557
bool suppressOptional = pattern.hasForeignErrorStrippingResultOptionality();
25572558
auto result = getBridgedResultType(rep,
25582559
pattern.getFunctionResultType(),
25592560
t.getResult(),
2561+
bridging,
25602562
suppressOptional);
25612563

25622564
return CanAnyFunctionType::get(genericSig, llvm::makeArrayRef(params),
@@ -2627,6 +2629,10 @@ getAbstractionPatternForConstant(ASTContext &ctx, SILDeclRef constant,
26272629
TypeConverter::LoweredFormalTypes
26282630
TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
26292631
CanAnyFunctionType fnType) {
2632+
// We always use full bridging when importing a constant because we can
2633+
// directly bridge its arguments and results when calling it.
2634+
auto bridging = Bridgeability::Full;
2635+
26302636
unsigned numParameterLists = constant.getParameterListCount();
26312637
auto extInfo = fnType->getExtInfo();
26322638

@@ -2638,7 +2644,7 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
26382644
// Fast path: no uncurrying required.
26392645
if (numParameterLists == 1) {
26402646
auto bridgedFnType =
2641-
getBridgedFunctionType(bridgingFnPattern, fnType, extInfo);
2647+
getBridgedFunctionType(bridgingFnPattern, fnType, extInfo, bridging);
26422648
bridgingFnPattern.rewriteType(bridgingFnPattern.getGenericSignature(),
26432649
bridgedFnType);
26442650
return { bridgingFnPattern, bridgedFnType };
@@ -2685,17 +2691,18 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
26852691
// The "self" parameter should not get bridged unless it's a metatype.
26862692
if (selfParam.getPlainType()->is<AnyMetatypeType>()) {
26872693
auto selfPattern = bridgingFnPattern.getFunctionParamType(0);
2688-
selfParam = getBridgedParam(rep, selfPattern, selfParam);
2694+
selfParam = getBridgedParam(rep, selfPattern, selfParam, bridging);
26892695
}
26902696
}
26912697

26922698
auto partialFnPattern = bridgingFnPattern.getFunctionResultType();
2693-
getBridgedParams(rep, partialFnPattern, methodParams, bridgedParams);
2699+
getBridgedParams(rep, partialFnPattern, methodParams, bridgedParams,
2700+
bridging);
26942701

26952702
bridgedResultType =
26962703
getBridgedResultType(rep,
26972704
partialFnPattern.getFunctionResultType(),
2698-
resultType, suppressOptionalResult);
2705+
resultType, bridging, suppressOptionalResult);
26992706
break;
27002707
}
27012708

lib/SIL/TypeLowering.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1472,9 +1472,16 @@ CanType TypeConverter::getLoweredRValueType(AbstractionPattern origType,
14721472
auto extInfo = substFnType->getExtInfo();
14731473
if (getSILFunctionLanguage(extInfo.getSILRepresentation())
14741474
== SILFunctionLanguage::C) {
1475+
// The importer only applies fully-reversible bridging to the
1476+
// component types of C function pointers.
1477+
auto bridging = Bridgeability::Full;
1478+
if (extInfo.getSILRepresentation()
1479+
== SILFunctionTypeRepresentation::CFunctionPointer)
1480+
bridging = Bridgeability::None;
1481+
14751482
// Bridge the parameters and result of the function type.
14761483
auto bridgedFnType = getBridgedFunctionType(origType, substFnType,
1477-
extInfo);
1484+
extInfo, bridging);
14781485
substFnType = bridgedFnType;
14791486

14801487
// Also rewrite the type of the abstraction pattern.

lib/SILGen/SILGenApply.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ getIndirectApplyAbstractionPattern(SILGenFunction &SGF,
7676
// bridged to a foreign type.
7777
auto bridgedType =
7878
SGF.SGM.Types.getBridgedFunctionType(pattern, fnType,
79-
fnType->getExtInfo());
79+
fnType->getExtInfo(),
80+
Bridgeability::Full);
8081
pattern.rewriteType(CanGenericSignature(), bridgedType);
8182
return pattern;
8283
}

lib/SILGen/SILGenBridging.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ expandTupleTypes(AnyFunctionType::CanParamArrayRef params) {
358358
static CanAnyFunctionType getBridgedBlockType(SILGenModule &SGM,
359359
CanAnyFunctionType blockType) {
360360
return SGM.Types.getBridgedFunctionType(AbstractionPattern(blockType),
361-
blockType, blockType->getExtInfo());
361+
blockType, blockType->getExtInfo(),
362+
Bridgeability::Full);
362363
}
363364

364365
static void buildFuncToBlockInvokeBody(SILGenFunction &SGF,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
typedef unsigned long size_t;
2+
typedef _Bool (^predicate_t)(size_t);
3+
typedef struct {
4+
void (*takePredicate)(predicate_t);
5+
} Aggregate;

0 commit comments

Comments
 (0)