@@ -1121,29 +1121,46 @@ RValue RValueEmitter::visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E,
1121
1121
1122
1122
static ManagedValue convertCFunctionSignature (SILGenFunction &SGF,
1123
1123
FunctionConversionExpr *e,
1124
- ManagedValue result) {
1124
+ SILType loweredResultTy,
1125
+ llvm::function_ref<ManagedValue ()> fnEmitter) {
1125
1126
SILType loweredDestTy = SGF.getLoweredType (e->getType ());
1126
-
1127
- if (result.getType () == loweredDestTy)
1128
- return result;
1127
+ ManagedValue result;
1129
1128
1130
1129
// We're converting between C function pointer types. They better be
1131
1130
// ABI-compatible, since we can't emit a thunk.
1132
- if (SGF.SGM .Types .checkForABIDifferences (result.getSwiftType (),
1133
- loweredDestTy.getSwiftRValueType ())
1134
- == TypeConverter::ABIDifference::NeedsThunk) {
1131
+ switch (SGF.SGM .Types .checkForABIDifferences (
1132
+ loweredResultTy.getSwiftRValueType (),
1133
+ loweredDestTy.getSwiftRValueType ())) {
1134
+ case TypeConverter::ABIDifference::Trivial:
1135
+ result = fnEmitter ();
1136
+ assert (result.getType () == loweredResultTy);
1137
+
1138
+ if (loweredResultTy != loweredDestTy) {
1139
+ result = ManagedValue::forUnmanaged (
1140
+ SGF.B .createConvertFunction (e, result.getUnmanagedValue (),
1141
+ loweredDestTy));
1142
+ }
1143
+
1144
+ break ;
1145
+
1146
+ case TypeConverter::ABIDifference::NeedsThunk:
1147
+ // Note: in this case, we don't call the emitter at all -- doing so
1148
+ // just runs the risk of tripping up asserts in SILGenBridging.cpp
1135
1149
SGF.SGM .diagnose (e, diag::unsupported_c_function_pointer_conversion,
1136
1150
e->getSubExpr ()->getType (), e->getType ());
1137
- return SGF.emitUndef (e, loweredDestTy);
1151
+ result = SGF.emitUndef (e, loweredDestTy);
1152
+ break ;
1153
+
1154
+ case TypeConverter::ABIDifference::ThinToThick:
1155
+ llvm_unreachable (" Cannot have thin to thick conversion here" );
1138
1156
}
1139
1157
1140
- return ManagedValue::forUnmanaged (
1141
- SGF.B .createConvertFunction (e, result.getUnmanagedValue (),
1142
- loweredDestTy));
1158
+ return result;
1143
1159
}
1144
1160
1145
- static RValue emitCFunctionPointer (SILGenFunction &gen,
1146
- FunctionConversionExpr *conversionExpr) {
1161
+ static
1162
+ ManagedValue emitCFunctionPointer (SILGenFunction &gen,
1163
+ FunctionConversionExpr *conversionExpr) {
1147
1164
auto expr = conversionExpr->getSubExpr ();
1148
1165
1149
1166
// Look through base-ignored exprs to get to the function ref.
@@ -1180,13 +1197,18 @@ static RValue emitCFunctionPointer(SILGenFunction &gen,
1180
1197
}
1181
1198
1182
1199
// Produce a reference to the C-compatible entry point for the function.
1183
- SILDeclRef cEntryPoint (loc, ResilienceExpansion::Minimal,
1184
- /* uncurryLevel*/ 0 ,
1185
- /* foreign*/ true );
1186
- SILValue cRef = gen.emitGlobalFunctionRef (expr, cEntryPoint);
1187
- ManagedValue result = convertCFunctionSignature (gen, conversionExpr,
1188
- ManagedValue::forUnmanaged (cRef));
1189
- return RValue (gen, conversionExpr, result);
1200
+ SILDeclRef constant (loc, ResilienceExpansion::Minimal,
1201
+ /* uncurryLevel*/ 0 ,
1202
+ /* foreign*/ true );
1203
+ SILConstantInfo constantInfo = gen.getConstantInfo (constant);
1204
+
1205
+ return convertCFunctionSignature (
1206
+ gen, conversionExpr,
1207
+ constantInfo.getSILType (),
1208
+ [&]() -> ManagedValue {
1209
+ SILValue cRef = gen.emitGlobalFunctionRef (expr, constant);
1210
+ return ManagedValue::forUnmanaged (cRef);
1211
+ });
1190
1212
}
1191
1213
1192
1214
// Change the representation without changing the signature or
@@ -1271,15 +1293,27 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
1271
1293
cast<FunctionType>(e->getType ()->getCanonicalType ());
1272
1294
1273
1295
if (destRepTy->getRepresentation () == FunctionTypeRepresentation::CFunctionPointer) {
1274
- // A "conversion" of a DeclRef a C function pointer is done by referencing
1275
- // the thunk (or original C function) with the C calling convention.
1276
- if (srcRepTy->getRepresentation () != FunctionTypeRepresentation::CFunctionPointer)
1277
- return emitCFunctionPointer (SGF, e);
1278
-
1279
- // Ok, we're converting a C function pointer value to another C function
1280
- // pointer.
1281
- auto result = SGF.emitRValueAsSingleValue (e->getSubExpr ());
1282
- return RValue (SGF, e, convertCFunctionSignature (SGF, e, result));
1296
+ ManagedValue result;
1297
+
1298
+ if (srcRepTy->getRepresentation () != FunctionTypeRepresentation::CFunctionPointer) {
1299
+ // A "conversion" of a DeclRef a C function pointer is done by referencing
1300
+ // the thunk (or original C function) with the C calling convention.
1301
+ result = emitCFunctionPointer (SGF, e);
1302
+ } else {
1303
+ // Ok, we're converting a C function pointer value to another C function
1304
+ // pointer.
1305
+
1306
+ // Emit the C function pointer
1307
+ result = SGF.emitRValueAsSingleValue (e->getSubExpr ());
1308
+
1309
+ // Possibly bitcast the C function pointer to account for ABI-compatible
1310
+ // parameter and result type conversions
1311
+ result = convertCFunctionSignature (SGF, e, result.getType (),
1312
+ [&]() -> ManagedValue {
1313
+ return result;
1314
+ });
1315
+ }
1316
+ return RValue (SGF, e, result);
1283
1317
}
1284
1318
1285
1319
// Break the conversion into three stages:
0 commit comments