mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #84948 from DougGregor/extern-c-asmname
[SILGen] Map the @_extern(c) C function name over to the asmname of a SIL function
This commit is contained in:
@@ -1428,11 +1428,6 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
|
||||
return NameA->Name.str();
|
||||
}
|
||||
|
||||
if (auto *ExternA = ExternAttr::find(getDecl()->getAttrs(), ExternKind::C)) {
|
||||
assert(isa<FuncDecl>(getDecl()) && "non-FuncDecl with @_extern should be rejected by typechecker");
|
||||
return ExternA->getCName(cast<FuncDecl>(getDecl())).str();
|
||||
}
|
||||
|
||||
// Use a given cdecl name for native-to-foreign thunks.
|
||||
if (getDecl()->getAttrs().hasAttribute<CDeclAttr>())
|
||||
if (isNativeToForeignThunk()) {
|
||||
|
||||
@@ -126,6 +126,12 @@ void SILFunctionBuilder::addFunctionAttributes(
|
||||
F->setEffectsKind(effectsAttr->getKind());
|
||||
}
|
||||
}
|
||||
|
||||
if (constant.isFunc() && constant.hasFuncDecl()) {
|
||||
auto func = constant.getFuncDecl();
|
||||
if (auto *EA = ExternAttr::find(Attrs, ExternKind::C))
|
||||
F->setAsmName(EA->getCName(func));
|
||||
}
|
||||
}
|
||||
|
||||
if (!customEffects.empty()) {
|
||||
|
||||
@@ -975,7 +975,7 @@ void Serializer::writeBlockInfoBlock() {
|
||||
BLOCK_RECORD(sil_block, SIL_SOURCE_LOC_REF);
|
||||
BLOCK_RECORD(sil_block, SIL_DEBUG_VALUE);
|
||||
BLOCK_RECORD(sil_block, SIL_DEBUG_VALUE_DELIMITER);
|
||||
|
||||
BLOCK_RECORD(sil_block, SIL_EXTRA_STRING);
|
||||
|
||||
BLOCK(SIL_INDEX_BLOCK);
|
||||
BLOCK_RECORD(sil_index_block, SIL_FUNC_NAMES);
|
||||
|
||||
8
test/SIL/Serialization/Inputs/extern_with_nonnull.swift
Normal file
8
test/SIL/Serialization/Inputs/extern_with_nonnull.swift
Normal file
@@ -0,0 +1,8 @@
|
||||
@_extern(c, "takes_a_void_pointer")
|
||||
public func takes_a_void_pointer(_ pointer: UnsafeRawPointer)
|
||||
|
||||
@_alwaysEmitIntoClient
|
||||
public func callWithNonNull() {
|
||||
let pointer = UnsafeMutablePointer<Int>.allocate(capacity: 1)
|
||||
takes_a_void_pointer(UnsafeRawPointer(pointer))
|
||||
}
|
||||
7
test/SIL/Serialization/Inputs/extern_with_nullable.swift
Normal file
7
test/SIL/Serialization/Inputs/extern_with_nullable.swift
Normal file
@@ -0,0 +1,7 @@
|
||||
@_extern(c, "takes_a_void_pointer")
|
||||
public func takes_a_void_pointer(_ pointer: UnsafeRawPointer?)
|
||||
|
||||
@_alwaysEmitIntoClient
|
||||
public func callWithNullable() {
|
||||
takes_a_void_pointer(nil)
|
||||
}
|
||||
18
test/SIL/Serialization/extern_collision.swift
Normal file
18
test/SIL/Serialization/extern_collision.swift
Normal file
@@ -0,0 +1,18 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -enable-experimental-feature Extern -o %t %S/Inputs/extern_with_nullable.swift
|
||||
// RUN: %target-swift-frontend -emit-module -enable-experimental-feature Extern -o %t %S/Inputs/extern_with_nonnull.swift
|
||||
// RUN: %target-swift-frontend -emit-sil -o %t -I %t -primary-file %s -module-name main -O
|
||||
|
||||
// REQUIRES: swift_feature_Extern
|
||||
|
||||
// Don't crash or otherwise fail when inlining multiple functions that reference
|
||||
// @_extern(c) declarations of the same name but different types at the SIL
|
||||
// level.
|
||||
|
||||
import extern_with_nullable
|
||||
import extern_with_nonnull
|
||||
|
||||
public func main() {
|
||||
callWithNullable()
|
||||
callWithNonNull()
|
||||
}
|
||||
@@ -2,48 +2,48 @@
|
||||
|
||||
// REQUIRES: swift_feature_Extern
|
||||
|
||||
// CHECK-DAG: sil hidden_external @my_c_name : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: sil hidden_external [asmname "my_c_name"] @$s8extern_c9withCNameyS2iFTo : $@convention(c) (Int) -> Int
|
||||
@_extern(c, "my_c_name")
|
||||
func withCName(_ x: Int) -> Int
|
||||
|
||||
// CHECK-DAG: sil hidden_external @take_c_func_ptr : $@convention(c) (@convention(c) (Int) -> Int) -> ()
|
||||
// CHECK-DAG: sil hidden_external [asmname "take_c_func_ptr"] @$s8extern_c12takeCFuncPtryyS2iXCF : $@convention(c) (@convention(c) (Int) -> Int) -> ()
|
||||
@_extern(c, "take_c_func_ptr")
|
||||
func takeCFuncPtr(_ f: @convention(c) (Int) -> Int)
|
||||
|
||||
// CHECK-DAG: sil @public_visible : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: sil [asmname "public_visible"] @$s8extern_c16publicVisibilityyS2iF : $@convention(c) (Int) -> Int
|
||||
@_extern(c, "public_visible")
|
||||
public func publicVisibility(_ x: Int) -> Int
|
||||
|
||||
// CHECK-DAG: sil @private_visible : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: sil [asmname "private_visible"] @$s8extern_c17privateVisibility{{.*}} : $@convention(c) (Int) -> Int
|
||||
@_extern(c, "private_visible")
|
||||
private func privateVisibility(_ x: Int) -> Int
|
||||
|
||||
// CHECK-DAG: sil hidden_external @withoutCName : $@convention(c) () -> Int
|
||||
// CHECK-DAG: sil hidden_external [asmname "withoutCName"] @$s8extern_c12withoutCNameSiyF : $@convention(c) () -> Int
|
||||
@_extern(c)
|
||||
func withoutCName() -> Int
|
||||
|
||||
// CHECK-DAG: sil hidden [ossa] @$s8extern_c10defaultArgyySiFfA_ : $@convention(thin) () -> Int {
|
||||
// CHECK-DAG: sil hidden_external @default_arg : $@convention(c) (Int) -> ()
|
||||
// CHECK-DAG: sil hidden_external [asmname "default_arg"] @$s8extern_c10defaultArgyySiF : $@convention(c) (Int) -> ()
|
||||
@_extern(c, "default_arg")
|
||||
func defaultArg(_ x: Int = 42)
|
||||
|
||||
func main() {
|
||||
// CHECK-DAG: [[F1:%.+]] = function_ref @my_c_name : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: [[F2:%.+]] = function_ref @take_c_func_ptr : $@convention(c) (@convention(c) (Int) -> Int) -> ()
|
||||
// CHECK-DAG: [[F1:%.+]] = function_ref @$s8extern_c9withCNameyS2iFTo : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: [[F2:%.+]] = function_ref @$s8extern_c12takeCFuncPtryyS2iXCF : $@convention(c) (@convention(c) (Int) -> Int) -> ()
|
||||
// CHECK-DAG: apply [[F2]]([[F1]]) : $@convention(c) (@convention(c) (Int) -> Int) -> ()
|
||||
takeCFuncPtr(withCName)
|
||||
// CHECK-DAG: [[F3:%.+]] = function_ref @public_visible : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: [[F3:%.+]] = function_ref @$s8extern_c16publicVisibilityyS2iF : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: apply [[F3]]({{.*}}) : $@convention(c) (Int) -> Int
|
||||
_ = publicVisibility(42)
|
||||
// CHECK-DAG: [[F4:%.+]] = function_ref @private_visible : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: [[F4:%.+]] = function_ref @$s8extern_c17privateVisibility{{.*}} : $@convention(c) (Int) -> Int
|
||||
// CHECK-DAG: apply [[F4]]({{.*}}) : $@convention(c) (Int) -> Int
|
||||
_ = privateVisibility(24)
|
||||
// CHECK-DAG: [[F5:%.+]] = function_ref @withoutCName : $@convention(c) () -> Int
|
||||
// CHECK-DAG: [[F5:%.+]] = function_ref @$s8extern_c12withoutCNameSiyF : $@convention(c) () -> Int
|
||||
// CHECK-DAG: apply [[F5]]() : $@convention(c) () -> Int
|
||||
_ = withoutCName()
|
||||
// CHECK-DAG: [[F6:%.+]] = function_ref @$s8extern_c10defaultArgyySiFfA_ : $@convention(thin) () -> Int
|
||||
// CHECK-DAG: [[DEFAULT_V:%.+]] = apply [[F6]]() : $@convention(thin) () -> Int
|
||||
// CHECK-DAG: [[F7:%.+]] = function_ref @default_arg : $@convention(c) (Int) -> ()
|
||||
// CHECK-DAG: [[F7:%.+]] = function_ref @$s8extern_c10defaultArgyySiF : $@convention(c) (Int) -> ()
|
||||
// CHECK-DAG: apply [[F7]]([[DEFAULT_V]]) : $@convention(c) (Int) -> ()
|
||||
defaultArg()
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ func my_extern_func1() // expected-note {{function declared here}}
|
||||
func my_extern_func2(x: Int)
|
||||
|
||||
@_extern(c, "my_other_extern_func")
|
||||
func my_other_extern_func1() // expected-note {{function declared here}}
|
||||
func my_other_extern_func1()
|
||||
|
||||
@_extern(c, "my_other_extern_func")
|
||||
func my_other_extern_func2(x: Int)
|
||||
@@ -18,6 +18,8 @@ public func foo() {
|
||||
my_extern_func1()
|
||||
my_extern_func2(x: 42) // expected-error {{function type mismatch, declared as '@convention(thin) () -> ()' but used as '@convention(thin) (Int) -> ()'}}
|
||||
|
||||
// @_extern(c, ...) keeps declarations separate at the SIL level, so we do
|
||||
// not detect a mismatch here.
|
||||
my_other_extern_func1()
|
||||
my_other_extern_func2(x: 42) // expected-error {{function type mismatch, declared as '@convention(c) () -> ()' but used as '@convention(c) (Int) -> ()'}}
|
||||
my_other_extern_func2(x: 42)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
@_cdecl("posix_memalign")
|
||||
func posix_memalign(_ resultPtr:UnsafeMutablePointer<UnsafeMutableRawPointer?>, _ :Int, _ :Int) -> Int32 { // expected-error {{function has wrong linkage to be called from}}
|
||||
func posix_memalign(_ resultPtr:UnsafeMutablePointer<UnsafeMutableRawPointer?>, _ :Int, _ :Int) -> Int32 { // okay: @_extern(c) declaration is separate
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user