Skip to content

Commit 79fc0f1

Browse files
committed
[extern] Give @_extern(c) functions @convention(c) type
This ensures that when we reference them, we get an appropriately-typed function value. SILGen can then thunk to whatever function type is needed.
1 parent 3445b86 commit 79fc0f1

File tree

3 files changed

+20
-0
lines changed

3 files changed

+20
-0
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,9 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
996996
// If the referenced decl isn't a VarDecl, it should be a constant of some
997997
// sort.
998998
SILDeclRef silDeclRef(decl);
999+
if (ExternAttr::find(decl->getAttrs(), ExternKind::C))
1000+
silDeclRef = silDeclRef.asForeign();
1001+
9991002
assert(silDeclRef.getParameterListCount() == 1);
10001003
auto substType = cast<AnyFunctionType>(refType);
10011004
auto typeContext = getFunctionTypeInfo(substType);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,6 +2565,11 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
25652565
infoBuilder = infoBuilder.withSendingResult();
25662566
}
25672567

2568+
if (ExternAttr::find(D->getAttrs(), ExternKind::C)) {
2569+
infoBuilder = infoBuilder.withRepresentation(
2570+
FunctionTypeRepresentation::CFunctionPointer);
2571+
}
2572+
25682573
// Lifetime dependencies only apply to the outer function type.
25692574
if (!hasSelf && lifetimeDependenceInfo.has_value()) {
25702575
infoBuilder =

test/SILGen/extern_c.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ func withoutCName() -> Int
2727
@_extern(c, "default_arg")
2828
func defaultArg(_ x: Int = 42)
2929

30+
func callMe(body: (Int) -> Int) -> Int {
31+
return body(17)
32+
}
33+
3034
func main() {
3135
// CHECK-DAG: [[F1:%.+]] = function_ref @$s8extern_c9withCNameyS2iFTo : $@convention(c) (Int) -> Int
3236
// CHECK-DAG: [[F2:%.+]] = function_ref @$s8extern_c12takeCFuncPtryyS2iXCFTo : $@convention(c) (@convention(c) (Int) -> Int) -> ()
@@ -46,6 +50,14 @@ func main() {
4650
// CHECK-DAG: [[F7:%.+]] = function_ref @$s8extern_c10defaultArgyySiFTo : $@convention(c) (Int) -> ()
4751
// CHECK-DAG: apply [[F7]]([[DEFAULT_V]]) : $@convention(c) (Int) -> ()
4852
defaultArg()
53+
54+
// CHECK-DAG: [[CREF:%[0-9]+]] = function_ref @$s8extern_c16publicVisibilityyS2iFTo : $@convention(c) (Int) -> Int
55+
// CHECK-DAG: [[THUNK:%[0-9]+]] = function_ref @$sS2iIetCyd_S2iIegyd_TR : $@convention(thin) (Int, @convention(c) (Int) -> Int) -> Int
56+
// CHECK-DAG: [[APPLIED:%[0-9]+]] = partial_apply [callee_guaranteed] [[THUNK]]([[CREF]]) : $@convention(thin) (Int, @convention(c) (Int) -> Int) -> Int
57+
// CHECK-DAG: [[NOESCAPE_APPLIED:%[0-9]+]] = convert_escape_to_noescape [not_guaranteed] [[APPLIED]] to $@noescape @callee_guaranteed (Int) -> Int
58+
// CHECK-DAG: [[CALL_ME:%[0-9]+]] = function_ref @$s8extern_c6callMe4bodyS3iXE_tF
59+
// CHECK-DAG: apply [[CALL_ME]]([[NOESCAPE_APPLIED]]) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed (Int) -> Int) -> Int
60+
_ = callMe(body: publicVisibility)
4961
}
5062

5163
main()

0 commit comments

Comments
 (0)