Skip to content

[embedded] Start building Synchronization in embedded Swift mode #72293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/EmbeddedSwift/EmbeddedSwiftStatus.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ This status table describes which of the following Swift features can be used in

| **Swift Feature** | **Currently Supported In Embedded Swift?** |
|------------------------------------------------------------|-----------------------------------------------------|
| Synchronization module | Yes |
| Swift Concurrency | Partial, experimental (basics of actors and tasks work in single-threaded concurrency mode) |
| C interop | Yes |
| C++ interop | Yes |
Expand Down
1 change: 1 addition & 0 deletions docs/EmbeddedSwift/UserManual.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ For (2), external dependencies are also triggered by specific code needing them,
- **atomics instrinsics**
- on CPU architectures that don't have direct load-acquire/store-release support in the ISA, LLVM calls helper functions for atomic operations
- needed by refcounting in the Embedded Swift runtime (so any class usage will trigger this dependency)
- also needed when using atomics from the Synchronization module
- **multiplication/division/modulo instrinsics**
- on CPU architectures that don't have direct support for the math operations in the ISA
- dependency (on Mach-O): `__divti3`
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB)
"x86_64 x86_64-unknown-none-elf x86_64-unknown-none-elf"
# Without specifying the `windows` component LLVM refuses to
# generate valid COFF object files.
"i686 i686-unknown-windows-coff i686-unknown-windows-coff"
"x86_64 x86_64-unknown-windows-coff x86_64-unknown-windows-coff"
"i686 i686-unknown-windows-msvc i686-unknown-windows-msvc"
"x86_64 x86_64-unknown-windows-msvc x86_64-unknown-windows-msvc"
)
endif()

Expand Down
3 changes: 3 additions & 0 deletions stdlib/public/Synchronization/AtomicMemoryOrderings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ extension AtomicLoadOrdering: Hashable {
}

@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension AtomicLoadOrdering: CustomStringConvertible {
@available(SwiftStdlib 6.0, *)
public var description: String {
Expand Down Expand Up @@ -191,6 +192,7 @@ extension AtomicStoreOrdering: Hashable {
}

@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension AtomicStoreOrdering: CustomStringConvertible {
@available(SwiftStdlib 6.0, *)
public var description: String {
Expand Down Expand Up @@ -315,6 +317,7 @@ extension AtomicUpdateOrdering: Hashable {
}

@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension AtomicUpdateOrdering: CustomStringConvertible {
@available(SwiftStdlib 6.0, *)
public var description: String {
Expand Down
71 changes: 57 additions & 14 deletions stdlib/public/Synchronization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
#
#===----------------------------------------------------------------------===#

add_swift_target_library(swiftSynchronization ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
# List of files here:
set(swift_synchronization_sources
Atomic.swift
AtomicBool.swift
AtomicFloats.swift
Expand All @@ -21,23 +20,67 @@ add_swift_target_library(swiftSynchronization ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES
AtomicPointers.swift
AtomicRepresentable.swift
WordPair.swift
)
set(swift_synchronization_gyb_sources
AtomicIntegers.swift.gyb
AtomicStorage.swift.gyb
)
set(swift_synchronization_swift_compile_flags
${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
"-enable-builtin-module"
"-enable-experimental-feature" "RawLayout"
"-enable-experimental-feature" "StaticExclusiveOnly"
)

GYB_SOURCES
AtomicIntegers.swift.gyb
AtomicStorage.swift.gyb

SWIFT_COMPILE_FLAGS
${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
"-enable-builtin-module"
"-enable-experimental-feature" "RawLayout"
"-enable-experimental-feature" "StaticExclusiveOnly"

add_swift_target_library(swiftSynchronization ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
${swift_synchronization_sources}
GYB_SOURCES ${swift_synchronization_gyb_sources}
SWIFT_COMPILE_FLAGS ${swift_synchronization_swift_compile_flags}
LINK_FLAGS
"${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"

INSTALL_IN_COMPONENT
stdlib

MACCATALYST_BUILD_FLAVOR
"zippered"
)

# Embedded Synchronization - embedded libraries are built as .swiftmodule only,
# i.e. there is no .o or .a file produced (no binary code is actually produced)
# and only users of a library are going to actually compile any needed code.
if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB)
add_custom_target(embedded-synchronization ALL)

foreach(entry ${EMBEDDED_STDLIB_TARGET_TRIPLES})
string(REGEX REPLACE "[ \t]+" ";" list "${entry}")
list(GET list 0 arch)
list(GET list 1 mod)
list(GET list 2 triple)

set(SWIFT_SDK_embedded_ARCH_${arch}_MODULE "${mod}")
set(SWIFT_SDK_embedded_LIB_SUBDIR "embedded")
set(SWIFT_SDK_embedded_ARCH_${arch}_TRIPLE "${triple}")
set(SWIFT_SDK_embedded_PATH ${SWIFT_SDK_OSX_PATH})
set(SWIFT_SDK_embedded_ARCH_${arch}_PATH ${SWIFT_SDK_OSX_PATH})
set(SWIFT_SDK_embedded_USE_ISYSROOT TRUE)
add_swift_target_library_single(
embedded-synchronization-${mod}
swiftSynchronization
ONLY_SWIFTMODULE
IS_FRAGILE

${swift_synchronization_sources}
GYB_SOURCES ${swift_synchronization_gyb_sources}

SWIFT_COMPILE_FLAGS
${swift_synchronization_swift_compile_flags}
-Xcc -D__MACH__ -Xcc -D__APPLE__ -Xcc -ffreestanding -enable-experimental-feature Embedded

MODULE_DIR "${CMAKE_BINARY_DIR}/lib/swift/embedded"
SDK "embedded"
ARCHITECTURE "${arch}"
DEPENDS embedded-stdlib-${mod}
INSTALL_IN_COMPONENT stdlib
)
add_dependencies(embedded-synchronization embedded-synchronization-${mod})
endforeach()
endif()
2 changes: 2 additions & 0 deletions stdlib/public/Synchronization/WordPair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ extension WordPair: Hashable {
}

@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension WordPair: CustomStringConvertible {
/// A string that represents the contents of the word pair.
@available(SwiftStdlib 6.0, *)
Expand All @@ -193,6 +194,7 @@ extension WordPair: CustomStringConvertible {
}

@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension WordPair: CustomDebugStringConvertible {
/// A string that represents the contents of the word pair, suitable for
/// debugging.
Expand Down
3 changes: 0 additions & 3 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,6 @@ add_swift_target_library(swiftCore
# Embedded standard library - embedded libraries are built as .swiftmodule only,
# i.e. there is no .o or .a file produced (no binary code is actually produced)
# and only users of a library are going to actually compile any needed code.
#
# For now, we build a hardcoded list of target triples of the embedded stdlib,
# and only when building Swift on macOS.
if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB)
add_custom_target(embedded-stdlib ALL)

Expand Down
32 changes: 32 additions & 0 deletions test/embedded/synchronization.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -parse-as-library -enable-experimental-feature Embedded -disable-availability-checking -c -o %t/main.o
// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip
// RUN: %target-run %t/a.out | %FileCheck %s

// REQUIRES: swift_in_compiler
// REQUIRES: executable_test
// REQUIRES: optimized_stdlib
// REQUIRES: OS=macosx || OS=linux-gnu

import Synchronization

@main
struct Main {
static let x = Atomic(128)

static func main() {
let old = x.load(ordering: .relaxed)
x.store(42, ordering: .relaxed)
let new = x.load(ordering: .relaxed)
print(old) // CHECK: 128
print(new) // CHECK: 42
let old2 = x.exchange(12, ordering: .acquiring)
print(old2) // CHECK: 42
let (exchanged, original) = x.compareExchange(expected: 128, desired: 316, ordering: .sequentiallyConsistent)
print(exchanged) // CHECK: false
print(original) // CHECK: 12
let (exchanged2, original2) = x.compareExchange(expected: 12, desired: 316, ordering: .sequentiallyConsistent)
print(exchanged2) // CHECK: true
print(original2) // CHECK: 12
}
}