diff --git a/lib/SILOptimizer/UtilityPasses/Link.cpp b/lib/SILOptimizer/UtilityPasses/Link.cpp index bf080a33f8e6f..2cefc305f104b 100644 --- a/lib/SILOptimizer/UtilityPasses/Link.cpp +++ b/lib/SILOptimizer/UtilityPasses/Link.cpp @@ -13,6 +13,7 @@ #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SIL/SILModule.h" +#include "swift/Serialization/SerializedSILLoader.h" using namespace swift; @@ -35,8 +36,41 @@ class SILLinker : public SILModuleTransform { for (auto &Fn : M) if (M.linkFunction(&Fn, LinkMode)) invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::Everything); + + // In embedded Swift, the stdlib contains all the runtime functions needed + // (swift_retain, etc.). Link them in so they can be referenced in IRGen. + if (M.getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + linkEmbeddedRuntimeFromStdlib(); + } + } + + void linkEmbeddedRuntimeFromStdlib() { + #define FUNCTION(ID, NAME, CC, AVAILABILITY, RETURNS, ARGS, ATTRS, EFFECT) \ + linkEmbeddedRuntimeFunctionByName(#NAME); + + #define RETURNS(...) + #define ARGS(...) + #define NO_ARGS + #define ATTRS(...) + #define NO_ATTRS + #define EFFECT(...) + + #include "swift/Runtime/RuntimeFunctions.def" } + void linkEmbeddedRuntimeFunctionByName(StringRef name) { + SILModule &M = *getModule(); + + // Bail if runtime function is already loaded. + if (M.lookUpFunction(name)) return; + + SILFunction *Fn = + M.getSILLoader()->lookupSILFunction(name, SILLinkage::PublicExternal); + if (!Fn) return; + + if (M.linkFunction(Fn, LinkMode)) + invalidateAnalysis(Fn, SILAnalysis::InvalidationKind::Everything); + } }; } // end anonymous namespace diff --git a/stdlib/public/SwiftShims/swift/shims/CMakeLists.txt b/stdlib/public/SwiftShims/swift/shims/CMakeLists.txt index d56dcef16fbf4..2726660272435 100644 --- a/stdlib/public/SwiftShims/swift/shims/CMakeLists.txt +++ b/stdlib/public/SwiftShims/swift/shims/CMakeLists.txt @@ -1,6 +1,7 @@ set(sources AssertionReporting.h CoreFoundationShims.h + EmbeddedShims.h FoundationShims.h GlobalObjects.h HeapObject.h diff --git a/stdlib/public/SwiftShims/swift/shims/EmbeddedShims.h b/stdlib/public/SwiftShims/swift/shims/EmbeddedShims.h new file mode 100644 index 0000000000000..ce53f2a5a0420 --- /dev/null +++ b/stdlib/public/SwiftShims/swift/shims/EmbeddedShims.h @@ -0,0 +1,49 @@ +//===--- EmbeddedShims.h - shims for embedded Swift -------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Shims for embedded Swift. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H +#define SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H + +#include "SwiftStddef.h" +#include "Visibility.h" + +#if __has_feature(nullability) +#pragma clang assume_nonnull begin +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define SWIFT_CC __attribute__((swiftcall)) +#define SWIFT_CONTEXT __attribute__((swift_context)) + +typedef void SWIFT_CC (*HeapObjectDestroyer)(SWIFT_CONTEXT void *object); + +static inline void _swift_runtime_invoke_heap_object_destroy( + const void *destroy, void *self) { + ((HeapObjectDestroyer)destroy)(self); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#if __has_feature(nullability) +#pragma clang assume_nonnull end +#endif + +#endif // SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H diff --git a/stdlib/public/SwiftShims/swift/shims/LibcShims.h b/stdlib/public/SwiftShims/swift/shims/LibcShims.h index 1e4132f627900..672182ad23c29 100644 --- a/stdlib/public/SwiftShims/swift/shims/LibcShims.h +++ b/stdlib/public/SwiftShims/swift/shims/LibcShims.h @@ -40,6 +40,7 @@ __swift_size_t _swift_stdlib_fwrite_stdout(const void *ptr, __swift_size_t size, // General utilities // Memory management functions +extern int posix_memalign(void **memptr, __swift_size_t alignment, __swift_size_t size); static inline void _swift_stdlib_free(void *_Nullable ptr) { extern void free(void *_Nullable); free(ptr); diff --git a/stdlib/public/SwiftShims/swift/shims/module.modulemap b/stdlib/public/SwiftShims/swift/shims/module.modulemap index 36d7dd8be0d2d..d2c11e3215f78 100644 --- a/stdlib/public/SwiftShims/swift/shims/module.modulemap +++ b/stdlib/public/SwiftShims/swift/shims/module.modulemap @@ -1,6 +1,7 @@ module SwiftShims { header "AssertionReporting.h" header "CoreFoundationShims.h" + header "EmbeddedShims.h" header "FoundationShims.h" header "GlobalObjects.h" header "HeapObject.h" diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 2c271d31910a1..c06ed3505fad5 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -254,7 +254,10 @@ if(SWIFT_STDLIB_ENABLE_VECTOR_TYPES) list(APPEND SWIFTLIB_GYB_SOURCES SIMDConcreteOperations.swift.gyb SIMDVectorTypes.swift.gyb) endif() -list(APPEND SWIFTLIB_EMBEDDED_SOURCES EmbeddedStubs.swift) +list(APPEND SWIFTLIB_EMBEDDED_SOURCES + EmbeddedRuntime.swift + EmbeddedStubs.swift + ) set(GROUP_INFO_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/GroupInfo.json) set(swift_core_link_flags "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}") @@ -427,6 +430,7 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB) MODULE_DIR "${CMAKE_BINARY_DIR}/lib/swift/embedded" SDK "embedded" ARCHITECTURE "${arch}" + FILE_DEPENDS ${swiftCore_common_dependencies} INSTALL_IN_COMPONENT "never_install" ) add_dependencies(embedded-stdlib embedded-stdlib-${triple}) diff --git a/stdlib/public/core/EmbeddedRuntime.swift b/stdlib/public/core/EmbeddedRuntime.swift new file mode 100644 index 0000000000000..ee9b0c2a23005 --- /dev/null +++ b/stdlib/public/core/EmbeddedRuntime.swift @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftShims + +public struct ClassMetadata { + var superclassMetadata: UnsafeMutablePointer? + + // There is no way to express the actual calling convention on the heap desroy + // function (swiftcc with 'self') currently, so let's use UnsafeRawPointer + // and a helper function in C (_swift_runtime_invoke_heap_object_destroy). + var destroy: UnsafeRawPointer +} + +public struct HeapObject { + var metadata: UnsafeMutablePointer + + // TODO: This is just an initial support for strong refcounting only. We need + // to think about supporting (or banning) weak and/or unowned references. + var refcount: Int + + static let immortalRefCount = -1 +} + +func alignedAlloc(size: Int, alignment: Int) -> UnsafeMutableRawPointer? { + let alignment = max(alignment, MemoryLayout.size) + var r: UnsafeMutableRawPointer? = nil + _ = posix_memalign(&r, alignment, size) + return r +} + +@_cdecl("swift_slowAlloc") +public func swift_slowAlloc(_ size: Int, _ alignMask: Int) -> UnsafeMutableRawPointer? { + let alignment: Int + if alignMask == -1 { + alignment = _swift_MinAllocationAlignment + } else { + alignment = alignMask + 1 + } + return alignedAlloc(size: size, alignment: alignment) +} + +@_cdecl("swift_slowDealloc") +public func swift_slowDealloc(_ ptr: UnsafeMutableRawPointer?, _ size: Int, _ alignMask: Int) { + free(ptr) +} + +@_silgen_name("swift_allocObject") +public func swift_allocObject(metadata: UnsafeMutablePointer, requiredSize: Int, requiredAlignmentMask: Int) -> UnsafeMutablePointer { + let p = swift_slowAlloc(requiredSize, requiredAlignmentMask)! + let object = p.assumingMemoryBound(to: HeapObject.self) + object.pointee.metadata = metadata + object.pointee.refcount = 1 + return object +} + +@_silgen_name("swift_deallocClassInstance") +public func swift_deallocClassInstance(object: UnsafeMutablePointer, allocatedSize: Int, allocatedAlignMask: Int) { + free(object) +} + +@_silgen_name("swift_initStackObject") +public func swift_initStackObject(metadata: UnsafeMutablePointer, object: UnsafeMutablePointer) -> UnsafeMutablePointer { + object.pointee.metadata = metadata + + // TODO/FIXME: Making all stack promoted objects immortal is not correct. + object.pointee.refcount = HeapObject.immortalRefCount + return object +} + +// TODO/FIXME: Refcounting and swift_once is not thread-safe, the following only works in single-threaded environments. + +@_silgen_name("swift_isUniquelyReferenced_nonNull_native") +public func swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer) -> Bool { + // TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments. + return object.pointee.refcount == 1 +} + +@_silgen_name("swift_retain") +public func swift_retain(object: Builtin.RawPointer) -> Builtin.RawPointer { + if Int(Builtin.ptrtoint_Word(object)) == 0 { return object } + let o = UnsafeMutablePointer(object) + // TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments. + if o.pointee.refcount == HeapObject.immortalRefCount { return o._rawValue } + o.pointee.refcount += 1 + return o._rawValue +} + +@_silgen_name("swift_release") +public func swift_release(object: Builtin.RawPointer) { + if Int(Builtin.ptrtoint_Word(object)) == 0 { return } + let o = UnsafeMutablePointer(object) + // TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments. + if o.pointee.refcount == HeapObject.immortalRefCount { return } + o.pointee.refcount -= 1 + if o.pointee.refcount == 0 { + _swift_runtime_invoke_heap_object_destroy(o.pointee.metadata.pointee.destroy, o) + } +} + +@_silgen_name("swift_beginAccess") +public func swift_beginAccess(pointer: UnsafeMutableRawPointer, buffer: UnsafeMutableRawPointer, flags: UInt, pc: UnsafeMutableRawPointer) { + // TODO: Add actual exclusivity checking. +} + +@_silgen_name("swift_endAccess") +public func swift_endAccess(buffer: UnsafeMutableRawPointer) { + // TODO: Add actual exclusivity checking. +} + +@_silgen_name("swift_once") +public func swift_once(predicate: UnsafeMutablePointer, fn: (@convention(c) (UnsafeMutableRawPointer)->()), context: UnsafeMutableRawPointer) { + // TODO/FIXME: The following only works in single-threaded environments. + if predicate.pointee == 0 { + predicate.pointee = 1 + fn(context) + } +} + +@_silgen_name("swift_deletedMethodError") +public func swift_deletedMethodError() -> Never { + Builtin.int_trap() +} diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json index d61673baa343a..2ec15e28a8669 100644 --- a/stdlib/public/core/GroupInfo.json +++ b/stdlib/public/core/GroupInfo.json @@ -244,6 +244,7 @@ "Duration.swift", "DurationProtocol.swift", "Instant.swift", + "EmbeddedRuntime.swift", "EmbeddedStubs.swift" ], "Result": [ diff --git a/test/embedded/Inputs/tiny-runtime-dummy-refcounting.c b/test/embedded/Inputs/tiny-runtime-dummy-refcounting.c deleted file mode 100644 index 43f405d3d69e5..0000000000000 --- a/test/embedded/Inputs/tiny-runtime-dummy-refcounting.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include -#include - -typedef struct ClassMetadata ClassMetadata; -typedef struct HeapObject HeapObject; - -#if !__has_attribute(swiftcall) -#error "The runtime must be built with a compiler that supports swiftcall." -#endif - -typedef struct ClassMetadata { - ClassMetadata *superclassMetadata; - void __attribute__((swiftcall)) (* destroy)(__attribute__((swift_context)) HeapObject *object); -} ClassMetadata; - -typedef struct HeapObject { - ClassMetadata *metadata; - size_t refcount; -} HeapObject; - -void *swift_slowAlloc(size_t bytes, size_t alignMask) { - void *r = NULL; - posix_memalign(&r, (alignMask == (size_t)-1) ? 16 : (alignMask + 1), bytes); - bzero(r, bytes); - return r; -} - -void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask) { - free(ptr); -} - -void *swift_allocObject(ClassMetadata *metadata, size_t requiredSize, size_t requiredAlignmentMask) { - HeapObject *object = swift_slowAlloc(requiredSize, requiredAlignmentMask); - object->metadata = metadata; - object->refcount = 1; - return object; -} - -void swift_deallocClassInstance(HeapObject *object, size_t allocatedSize, size_t allocatedAlignMask) { - free(object); -} - -HeapObject *swift_initStackObject(ClassMetadata *metadata, HeapObject *object) { - object->metadata = metadata; - object->refcount = -1; - return object; -} - -bool swift_isUniquelyReferenced_nonNull_native(HeapObject *object) { - return object->refcount == 1; -} - -void swift_release(HeapObject *object) { - if (object == NULL) return; - if (object->refcount == -1) return; - - object->refcount -= 1; - if (object->refcount == 0) { - object->metadata->destroy(object); - } -} - -HeapObject *swift_retain(HeapObject *object) { - if (object->refcount == -1) return object; - - object->refcount += 1; - return object; -} - -void swift_beginAccess(void *pointer, void *buffer, uintptr_t flags, void *pc) { } -void swift_endAccess(void *buffer) { } - -void swift_once(uintptr_t *predicate, void (*fn)(void *), void *context) { - if (!*predicate) { - *predicate = 1; - fn(context); - } -} diff --git a/test/embedded/Inputs/tiny-runtime-dummy-refcounting.swift b/test/embedded/Inputs/tiny-runtime-dummy-refcounting.swift deleted file mode 100644 index a12e4c67de83c..0000000000000 --- a/test/embedded/Inputs/tiny-runtime-dummy-refcounting.swift +++ /dev/null @@ -1,80 +0,0 @@ -let _swift_MinAllocationAlignment: UInt = 16 - -@_silgen_name("posix_memalign") -func posix_memalign(_: UnsafeMutablePointer, _: UInt, _: UInt) -> CInt - -@_silgen_name("free") -func free(_: UnsafeMutableRawPointer?) - -func alignedAlloc(size: UInt, alignment: UInt) -> UnsafeMutableRawPointer? { - let alignment = max(alignment, UInt(MemoryLayout.size)) - var r: UnsafeMutableRawPointer? = nil - _ = posix_memalign(&r, alignment, size) - return r -} - -/// Public APIs -// void *swift_slowAlloc(size_t size, size_t alignMask); -@_cdecl("swift_slowAlloc") -public func swift_slowAlloc(_ size: UInt, _ alignMask: UInt) -> UnsafeMutableRawPointer? { - let alignment: UInt - if alignMask == UInt.max { - alignment = _swift_MinAllocationAlignment - } else { - alignment = alignMask + 1 - } - return alignedAlloc(size: size, alignment: alignment) -} - -// void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask); -@_cdecl("swift_slowDealloc") -public func swift_slowDealloc(_ ptr: UnsafeMutableRawPointer?, _ size: UInt, _ alignMask: UInt) { - free(ptr) -} - -@_silgen_name("swift_allocObject") -public func swift_allocObject(metadata: UnsafeMutableRawPointer, requiredSize: UInt, requiredAlignmentMask: UInt) -> UnsafeMutablePointer { - let p = swift_slowAlloc(requiredSize, requiredAlignmentMask)! - let object = p.assumingMemoryBound(to: HeapObject.self) - object.pointee.metadata = metadata - object.pointee.refcount = 1 - return object -} - -@_silgen_name("swift_deallocClassInstance") -public func swift_deallocClassInstance(object: UnsafeMutablePointer, allocatedSize: UInt, allocatedAlignMask: UInt) { - free(object) -} - -@_silgen_name("swift_initStackObject") -public func swift_initStackObject(metadata: UnsafeMutableRawPointer, object: UnsafeMutablePointer) -> UnsafeMutablePointer { - object.pointee.metadata = metadata - object.pointee.refcount = -1 - return object -} - -@_silgen_name("swift_isUniquelyReferenced_nonNull_native") -public func swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer) -> Bool { - return object.pointee.refcount == 1 -} - -public struct HeapObject { - var metadata: UnsafeMutableRawPointer - var refcount: Int -} - -@_silgen_name("swift_retain") -public func swift_retain(object: UnsafeMutablePointer) -> UnsafeMutablePointer { - if object.pointee.refcount == -1 { return object } - object.pointee.refcount += 1 - return object -} - -@_silgen_name("swift_release") -public func swift_release(object: UnsafeMutablePointer) { - if object.pointee.refcount == -1 { return } - object.pointee.refcount -= 1 - if object.pointee.refcount == 0 { - free(object) - } -} diff --git a/test/embedded/array-builtins-exec.swift b/test/embedded/array-builtins-exec.swift index 57629351236ad..779236a29bb23 100644 --- a/test/embedded/array-builtins-exec.swift +++ b/test/embedded/array-builtins-exec.swift @@ -1,7 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s %S/Inputs/print.swift -enable-experimental-feature Embedded -enable-builtin-module -c -o %t/main.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o -// RUN: %target-clang %t/main.o %t/runtime.o -o %t/a.out -dead_strip +// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/array-to-pointer.swift b/test/embedded/array-to-pointer.swift index e04583511a31d..9eb8c52465789 100644 --- a/test/embedded/array-to-pointer.swift +++ b/test/embedded/array-to-pointer.swift @@ -1,8 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -c -o %t/main.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o // RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o -// RUN: %target-clang %t/main.o %t/runtime.o %t/print.o -o %t/a.out -dead_strip +// RUN: %target-clang %t/main.o %t/print.o -o %t/a.out -dead_strip // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/arrays-swift-runtime.swift b/test/embedded/arrays-swift-runtime.swift deleted file mode 100644 index 51d1620db4352..0000000000000 --- a/test/embedded/arrays-swift-runtime.swift +++ /dev/null @@ -1,60 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s %S/Inputs/tiny-runtime-dummy-refcounting.swift -enable-experimental-feature Embedded -c -o %t/main.o -// RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o -// RUN: %target-clang %t/main.o %t/print.o -o %t/a.out -dead_strip -// RUN: %target-run %t/a.out | %FileCheck %s - -// REQUIRES: executable_test -// REQUIRES: optimized_stdlib -// REQUIRES: VENDOR=apple -// REQUIRES: OS=macosx - -@_silgen_name("putchar") -func putchar(_: UInt8) - -public func print(_ s: StaticString, terminator: StaticString = "\n") { - var p = s.utf8Start - while p.pointee != 0 { - putchar(p.pointee) - p += 1 - } - p = terminator.utf8Start - while p.pointee != 0 { - putchar(p.pointee) - p += 1 - } -} - -@_silgen_name("print_long") -func print_long(_: Int) - -public func print(_ n: Int, terminator: StaticString = "\n") { - print_long(n) - print("", terminator: terminator) -} - -func print(_ array: [Int]) { - print("[", terminator: "") - for i in 0 ..< array.count { - print_long(array[i]) - if i != array.count - 1 { print(", ", terminator: "") } - } - print("]") -} - -func test() { - var a = [1, 2, 3] - a.append(8) - a.append(contentsOf: [5, 4]) - let b = a.sorted() - var c = b - c = c.reversed().filter { $0 % 2 == 0 } - print(c) // CHECK: [8, 4, 2] -} - -@main -struct Main { - static func main() { - test() - } -} diff --git a/test/embedded/arrays.swift b/test/embedded/arrays.swift index d08bf5a4e6761..8adb1c9fe4568 100644 --- a/test/embedded/arrays.swift +++ b/test/embedded/arrays.swift @@ -1,8 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -c -o %t/main.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o // RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o -// RUN: %target-clang %t/main.o %t/runtime.o %t/print.o -o %t/a.out -dead_strip +// RUN: %target-clang %t/main.o %t/print.o -o %t/a.out -dead_strip // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/classes-arrays.swift b/test/embedded/classes-arrays.swift index 5cb515357c7e6..1ca9b1f7a37e8 100644 --- a/test/embedded/classes-arrays.swift +++ b/test/embedded/classes-arrays.swift @@ -1,7 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s %S/Inputs/print.swift -enable-experimental-feature Embedded -c -o %t/main.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o -// RUN: %target-clang %t/main.o %t/runtime.o -o %t/a.out -dead_strip +// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/classes.swift b/test/embedded/classes.swift index 2f9276d87ee32..9b8e0cc55ba7e 100644 --- a/test/embedded/classes.swift +++ b/test/embedded/classes.swift @@ -1,7 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s %S/Inputs/print.swift -enable-experimental-feature Embedded -c -o %t/main.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o -// RUN: %target-clang %t/main.o %t/runtime.o -o %t/a.out -dead_strip +// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/modules-globals-exec.swift b/test/embedded/modules-globals-exec.swift index 4c7a65ffb0b22..7ff9328e6c0fb 100644 --- a/test/embedded/modules-globals-exec.swift +++ b/test/embedded/modules-globals-exec.swift @@ -3,9 +3,8 @@ // RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library // RUN: %target-swift-frontend -c -I %t %t/Main.swift -enable-experimental-feature Embedded -o %t/a.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o // RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o -// RUN: %target-clang %t/a.o %t/print.o %t/runtime.o -o %t/a.out +// RUN: %target-clang %t/a.o %t/print.o -o %t/a.out // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/modules-print-exec.swift b/test/embedded/modules-print-exec.swift index ed05cae7031e9..a8ed0db72eae0 100644 --- a/test/embedded/modules-print-exec.swift +++ b/test/embedded/modules-print-exec.swift @@ -3,9 +3,8 @@ // RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library // RUN: %target-swift-frontend -c -I %t %t/Main.swift -enable-experimental-feature Embedded -o %t/a.o -// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o // RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o -// RUN: %target-clang %t/a.o %t/print.o %t/runtime.o -o %t/a.out +// RUN: %target-clang %t/a.o %t/print.o -o %t/a.out // RUN: %target-run %t/a.out | %FileCheck %s // REQUIRES: executable_test diff --git a/test/embedded/runtime.swift b/test/embedded/runtime.swift new file mode 100644 index 0000000000000..31e1a0ba7f95d --- /dev/null +++ b/test/embedded/runtime.swift @@ -0,0 +1,85 @@ +// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s +// RUN: %target-run-simple-swift(-O -enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s +// RUN: %target-run-simple-swift(-Osize -enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s + +// REQUIRES: executable_test +// REQUIRES: optimized_stdlib +// REQUIRES: VENDOR=apple +// REQUIRES: OS=macosx + +@_silgen_name("putchar") +func putchar(_: UInt8) + +public func print(_ s: StaticString, terminator: StaticString = "\n") { + var p = s.utf8Start + while p.pointee != 0 { + putchar(p.pointee) + p += 1 + } + p = terminator.utf8Start + while p.pointee != 0 { + putchar(p.pointee) + p += 1 + } +} + +class MyClass { + init() { print("MyClass.init") } + deinit { print("MyClass.deinit") } + func foo() { print("MyClass.foo") } +} + +class MySubClass: MyClass { + override init() { print("MySubClass.init") } + deinit { print("MySubClass.deinit") } + override func foo() { print("MySubClass.foo") } +} + +class MySubSubClass: MySubClass { + override init() { print("MySubSubClass.init") } + deinit { print("MySubSubClass.deinit") } + override func foo() { print("MySubSubClass.foo") } +} + +@main +struct Main { + static var objects: [MyClass] = [] + static func main() { + print("1") // CHECK: 1 + objects.append(MyClass()) + // CHECK: MyClass.init + print("") + + print("2") // CHECK: 2 + objects.append(MySubClass()) + // CHECK: MySubClass.init + // CHECK: MyClass.init + print("") + + print("3") // CHECK: 3 + objects.append(MySubSubClass()) + // CHECK: MySubSubClass.init + // CHECK: MySubClass.init + // CHECK: MyClass.init + print("") + + print("4") // CHECK: 4 + for o in objects { + o.foo() + // CHECK: MyClass.foo + // CHECK: MySubClass.foo + // CHECK: MySubSubClass.foo + } + print("") + + print("5") // CHECK: 5 + objects = [] + // CHECK: MyClass.deinit + // CHECK: MySubClass.deinit + // CHECK: MyClass.deinit + // CHECK: MySubSubClass.deinit + // CHECK: MySubClass.deinit + // CHECK: MyClass.deinit + print("") + } +}