diff --git a/test/Interop/Cxx/extern-var/Inputs/extern-var.cc b/test/Interop/Cxx/extern-var/Inputs/extern-var.cc new file mode 100644 index 0000000000000..cdad2ba856f0f --- /dev/null +++ b/test/Interop/Cxx/extern-var/Inputs/extern-var.cc @@ -0,0 +1,21 @@ +int counter = 12; + +int getCounterFromCxx() { + return counter; +} + +void setCounterFromCxx(int c) { + counter = c; +} + +namespace Namespaced { + int counter = 12; + + int getCounterFromCxx() { + return counter; + } + + void setCounterFromCxx(int c) { + counter = c; + } +} diff --git a/test/Interop/Cxx/extern-var/Inputs/extern-var.h b/test/Interop/Cxx/extern-var/Inputs/extern-var.h new file mode 100644 index 0000000000000..c20a0d7586580 --- /dev/null +++ b/test/Interop/Cxx/extern-var/Inputs/extern-var.h @@ -0,0 +1,11 @@ +extern int counter; + +int getCounterFromCxx(); +void setCounterFromCxx(int); + +namespace Namespaced { + extern int counter; + + int getCounterFromCxx(); + void setCounterFromCxx(int); +} diff --git a/test/Interop/Cxx/extern-var/Inputs/module.modulemap b/test/Interop/Cxx/extern-var/Inputs/module.modulemap new file mode 100644 index 0000000000000..0f0ea6448047a --- /dev/null +++ b/test/Interop/Cxx/extern-var/Inputs/module.modulemap @@ -0,0 +1,3 @@ +module ExternVar { + header "extern-var.h" +} diff --git a/test/Interop/Cxx/extern-var/extern-var-irgen.swift b/test/Interop/Cxx/extern-var/extern-var-irgen.swift new file mode 100644 index 0000000000000..10cc415118d02 --- /dev/null +++ b/test/Interop/Cxx/extern-var/extern-var-irgen.swift @@ -0,0 +1,49 @@ +// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import ExternVar + +public func getCounter() -> CInt { + return counter +} + +// CHECK: @{{counter|"\?counter@@3HA"}} = external {{(dso_local )?}}global i32, align 4 + +// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main10getCounters5Int32VyF"() #0 +// CHECK: [[LOAD:%.*]] = load i32, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @{{counter|"\?counter@@3HA"}} to %Ts5Int32V*), i32 0, i32 0), align 4 +// CHECK: ret i32 [[LOAD]] + +public func setCounter(_ c: CInt) { + counter = c +} + +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main10setCounteryys5Int32VF"(i32 %0) #0 +// CHECK: store i32 %0, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @{{counter|"\?counter@@3HA"}} to %Ts5Int32V*), i32 0, i32 0), align 4 + +public func getNamespacedCounter() -> CInt { + return Namespaced.counter +} + +// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main20getNamespacedCounters5Int32VyF"() #0 +//FIXME mangle non-top-level var names to prevent name collisions and check: +// load i32, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @Namespaced.counter to %Ts5Int32V*), i32 0, i32 0), align 4 +// CHECK: ret i32 %1 + +public func setNamespacedCounter(_ c: CInt) { + Namespaced.counter = c +} + +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main20setNamespacedCounteryys5Int32VF"(i32 %0) #0 +//FIXME mangle non-top-level var names to prevent name collisions and check: +// store i32 %0, i32* getelementptr inbounds (%Ts5Int32V, %Ts5Int32V* bitcast (i32* @Namespaced.counter to %Ts5Int32V*), i32 0, i32 0), align 4 + +func modifyInout(_ c: inout CInt) { + c = 42 +} + +public func passingVarAsInout() { + modifyInout(&counter) +} + +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main17passingVarAsInoutyyF"() #0 +// CHECK: call swiftcc void @"$s4main11modifyInoutyys5Int32VzF"(%Ts5Int32V* nocapture dereferenceable(4) bitcast (i32* @{{counter|"\?counter@@3HA"}} to %Ts5Int32V*)) + diff --git a/test/Interop/Cxx/extern-var/extern-var-silgen.swift b/test/Interop/Cxx/extern-var/extern-var-silgen.swift new file mode 100644 index 0000000000000..8f0a306ac5a96 --- /dev/null +++ b/test/Interop/Cxx/extern-var/extern-var-silgen.swift @@ -0,0 +1,59 @@ +// RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import ExternVar + +func getCounter() -> CInt { + return counter +} + +// CHECK: sil_global @counter : $Int32 + +// CHECK: sil hidden @$s4main10getCounters5Int32VyF : $@convention(thin) () -> Int32 +// CHECK: [[COUNTER:%.*]] = global_addr @counter : $*Int32 +// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[COUNTER]] : $*Int32 +// CHECK: [[LOAD:%.*]] = load [[ACCESS]] : $*Int32 +// CHECK: return [[LOAD]] : $Int32 + +func setCounter(_ c: CInt) { + counter = c +} + +// CHECK: sil hidden @$s4main10setCounteryys5Int32VF : $@convention(thin) (Int32) -> () +// CHECK: [[COUNTER:%.*]] = global_addr @counter : $*Int32 +// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[COUNTER]] : $*Int32 +// CHECK: store %0 to [[ACCESS]] : $*Int32 + +func getNamespacedCounter() -> CInt { + return Namespaced.counter +} + +// sil hidden @$s4main20getNamespacedCounters5Int32VyF : $@convention(thin) () -> Int32 +//FIXME mangle non-top-level var names to prevent name collisions +// %0 = global_addr @Namespaced.counter : $*Int32 +// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] %0 : $*Int32 +// CHECK: [[LOAD:%.*]] = load [[ACCESS]] : $*Int32 +// CHECK: return [[LOAD]] : $Int32 + +func setNamespacedCounter(_ c: CInt) { + Namespaced.counter = c +} + +// CHECK: sil hidden @$s4main20setNamespacedCounteryys5Int32VF : $@convention(thin) (Int32) -> () +//FIXME mangle non-top-level var names to prevent name collisions +// %1 = global_addr @Namespaced.counter : $*Int32 +// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] %1 : $*Int32 +// CHECK: store %0 to [[ACCESS]] : $*Int32 + +func modifyInout(_ c: inout CInt) { + c = 42 +} + +func passingVarAsInout() { + modifyInout(&counter) +} + +// CHECK: sil hidden @$s4main17passingVarAsInoutyyF : $@convention(thin) () -> () +// CHECK: [[COUNTER:%.*]] = global_addr @counter : $*Int32 +// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[COUNTER]] : $*Int32 +// CHECK: [[FUNCTION:%.*]] = function_ref @$s4main11modifyInoutyys5Int32VzF : $@convention(thin) (@inout Int32) -> () +// CHECK: apply [[FUNCTION]]([[ACCESS]]) : $@convention(thin) (@inout Int32) -> () diff --git a/test/Interop/Cxx/extern-var/extern-var.swift b/test/Interop/Cxx/extern-var/extern-var.swift new file mode 100644 index 0000000000000..5e66075f755a7 --- /dev/null +++ b/test/Interop/Cxx/extern-var/extern-var.swift @@ -0,0 +1,48 @@ +// RUN: %empty-directory(%t) +// RUN: %target-clang -c %S/Inputs/extern-var.cc -I %S/Inputs -o %t/extern-var.o +// RUN: %target-build-swift %s -I %S/Inputs -o %t/extern-var %t/extern-var.o -Xfrontend -enable-cxx-interop +// RUN: %target-codesign %t/extern-var +// RUN: %target-run %t/extern-var +// +// REQUIRES: executable_test + +import ExternVar +import StdlibUnittest + +var ExternVarTestSuite = TestSuite("ExternVarTestSuite") + +ExternVarTestSuite.test("write-from-swift") { + counter = 42 + expectEqual(42, counter) + expectEqual(42, getCounterFromCxx()) +} + +ExternVarTestSuite.test("write-from-cxx") { + setCounterFromCxx(84) + expectEqual(84, counter) + expectEqual(84, getCounterFromCxx()) +} + +//FIXME mangle non-top-level var names to prevent name collisions +// ExternVarTestSuite.test("namespaced-write-from-swift") { +// Namespaced.counter = 42 +// expectEqual(42, Namespaced.counter) +// expectEqual(42, amespaced.getCounterFromCxx()) +// } + +//FIXME mangle non-top-level var names to prevent name collisions +// ExternVarTestSuite.test("namespaced-write-from-cxx") { +// Namespaced.setCounterFromCxx(84) +// expectEqual(84, Namespaced.counter) +// expectEqual(84, Namespaced.getCounterFromCxx()) +// } + +//FIXME mangle non-top-level var names to prevent name collisions +// ExternVarTestSuite.test("no-collisions") { +// counter = 12 +// Namespaced.counter = 42 +// expectEqual(12, counter) +// expectEqual(42, Namespaced.counter) +// } + +runAllTests() diff --git a/test/lit.cfg b/test/lit.cfg index 84e5935283384..f45780f8c35f2 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -1028,6 +1028,7 @@ elif run_os in ['windows-msvc']: config.target_shared_library_suffix = '.dll' config.target_sdk_name = 'windows' config.target_runtime = 'native' + config.target_cc_options = "" config.target_build_swift = \ ('%r -target %s %s %s %s %s -libc %s' % \ @@ -1055,7 +1056,8 @@ elif run_os in ['windows-msvc']: config.target_add_rpath = r'' config.target_clang = \ - ('clang++ -target %s %s -fobjc-runtime=ios-5.0' % (config.variant_triple, clang_mcp_opt)) + ('clang++ -target %s %s %s -fobjc-runtime=ios-5.0' % \ + (config.variant_triple, clang_mcp_opt, config.target_cc_options)) config.target_ld = \ ('%r -libpath:%s' % (config.link, os.path.join(test_resource_dir, \ config.target_sdk_name))) @@ -1095,24 +1097,28 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows- config.target_shared_library_prefix = 'lib' config.target_shared_library_suffix = ".dll" config.target_sdk_name = "cygwin" + config.target_cc_options = "" elif run_os == 'windows-gnu': lit_config.note("Testing MinGW " + config.variant_triple) config.target_object_format = "coff" config.target_shared_library_prefix = 'lib' config.target_shared_library_suffix = ".dll" config.target_sdk_name = "mingw" + config.target_cc_options = "" elif run_os == 'freebsd': lit_config.note("Testing FreeBSD " + config.variant_triple) config.target_object_format = "elf" config.target_shared_library_prefix = 'lib' config.target_shared_library_suffix = ".so" config.target_sdk_name = "freebsd" + config.target_cc_options = "-fPIE" elif run_os == 'openbsd': lit_config.note("Testing OpenBSD " + config.variant_triple) config.target_object_format = "elf" config.target_shared_library_prefix = 'lib' config.target_shared_library_suffix = ".so" config.target_sdk_name = "openbsd" + config.target_cc_options = "-fPIE" elif kIsAndroid: lit_config.note("Testing Android " + config.variant_triple) config.target_object_format = "elf" @@ -1122,12 +1128,14 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows- # Needed by several ParseableInterface/swift_build_sdk_interfaces tests on # Android config.environment['ANDROID_DATA'] = os.environ['ANDROID_DATA'] + config.target_cc_options = "-fPIE" else: lit_config.note("Testing Linux " + config.variant_triple) config.target_object_format = "elf" config.target_shared_library_prefix = 'lib' config.target_shared_library_suffix = ".so" config.target_sdk_name = "linux" + config.target_cc_options = "-fPIE" config.target_runtime = "native" config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract") @@ -1185,8 +1193,8 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows- '%s -emit-pcm -target %s' % (config.swiftc, config.variant_triple)) config.target_clang = ( - "clang++ -target %s %s -fobjc-runtime=ios-5.0" % - (config.variant_triple, clang_mcp_opt)) + "clang++ -target %s %s %s -fobjc-runtime=ios-5.0" % + (config.variant_triple, clang_mcp_opt, config.target_cc_options)) config.target_ld = "ld -L%r" % (make_path(test_resource_dir, config.target_sdk_name)) elif run_os == 'linux-androideabi' or run_os == 'linux-android': # The module triple for Android ARMv7 seems to be canonicalized in LLVM @@ -1195,6 +1203,7 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android': target_specific_module_triple = re.sub(r'androideabi', 'android', target_specific_module_triple) config.variant_triple = re.sub(r'androideabi', 'android', config.variant_triple) + config.target_cc_options = "-fPIE" def get_architecture_value(**kwargs): result = kwargs[run_cpu] if result is None: @@ -1315,7 +1324,7 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android': 'clang++', '-target', config.variant_triple, clang_mcp_opt, android_include_system_paths_opt, - '-fobjc-runtime=ios-5.0']) + config.target_cc_options, '-fobjc-runtime=ios-5.0']) config.target_ld = ' '.join([ tools_directory, '-L%s' % make_path(test_resource_dir, config.target_sdk_name)])