diff --git a/Documentation/README.md b/Documentation/README.md
new file mode 100644
index 0000000..9926a2f
--- /dev/null
+++ b/Documentation/README.md
@@ -0,0 +1,6 @@
+Documentation for Embedded Swift
+================================
+
+Documentation for Embedded Swift can be found at these locations:
+- [in rendered form](https://swiftpackageindex.com/apple/swift-embedded-examples/documentation/embeddedswift)
+- [DocC source code](/Sources/EmbeddedSwift/Documentation.docc)
diff --git a/Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/ABI.md b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md
similarity index 84%
rename from Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/ABI.md
rename to Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md
index 7d5bea9..dfb2c89 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/ABI.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/ABI.md
@@ -1,10 +1,6 @@
-# ABI
+# ABI of Embedded Swift
-**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.**
-
-**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.**
-
-For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
+Understanding the different ABI (Application Binary Interface) for Embedded Swift
## ABI stability
@@ -14,7 +10,7 @@ Similarly, do not mix Embedded Swift code with full Swift code, as the ABIs are
## Symbol mangling under Embedded Swift
-Since Swift 5.0, the stable ABI mangling schema uses the `$s` prefix on all Swift symbols. Because Embedded Swift's ABI differs from the stable ABI, and furthermore because it's not expected to be stable, Embedded Swift uses a `$e` mangling prefix. The logic and structure of the mangling stays the same, the only difference is the prefix.
+Since Swift 5.0, the stable ABI mangling scheme uses the `$s` prefix on all Swift symbols. Because Embedded Swift's ABI differs from the stable ABI, and furthermore because it's not expected to be stable, Embedded Swift uses a `$e` mangling prefix. The logic and structure of the mangling stays the same, the only difference is the prefix.
## Calling convention of Embedded Swift
diff --git a/Sources/EmbeddedSwift/Documentation.docc/Development/Status.md b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md
similarity index 92%
rename from Sources/EmbeddedSwift/Documentation.docc/Development/Status.md
rename to Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md
index 5662f61..96f9286 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/Development/Status.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/CompilerDetails/Status.md
@@ -1,10 +1,6 @@
-# Status
+# Implementation Status
-**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.**
-
-**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.**
-
-For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
+Implementation status of compiler and language features in Embedded Swift, comparison to standard Swift
## Embedded Swift Language Features
diff --git a/Sources/EmbeddedSwift/Documentation.docc/Documentation.md b/Sources/EmbeddedSwift/Documentation.docc/Documentation.md
index 5afe875..cc0e349 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/Documentation.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/Documentation.md
@@ -1,187 +1,39 @@
# ``EmbeddedSwift``
+Embedded Swift is a compilation and language mode that enables development of baremetal, embedded and standalone software in Swift
+
@Metadata {
@DisplayName("Embedded Swift")
}
-## Overview
-
-Swift is a general purpose programming language suitable for both high-level application software and for low-level systems software. The existing major supported deployments of Swift are primarily targeting “large” operating systems (Linux, Windows, macOS, iOS), where storage and memory are relatively plentiful, multiple applications share code via dynamic linking, and the system can be expected to provide a number of common libraries (such as the C and C++ standard libraries). The typical size of the Swift runtime and standard library in these environments is around 5MB of binary size.
-
-However, lots of embedded platforms and low-level environments have constraints that make the standard Swift distribution impractical. These constraints have been described and discussed in existing prior work in this area, and there have been great past discussions in the Swift forums ([link](https://forums.swift.org/t/introduce-embedded-development-using-swift/56573)) and in last year’s video call ([link](https://forums.swift.org/t/call-for-interest-video-call-kickoff-using-swift-for-embedded-bare-metal-low-resources-programming/56911)), which shows there is a lot of interest and potential for Swift in this space. The motivation of “Embedded Swift” is to achieve a first class support for embedded platforms and unblock porting and using Swift in small environments. In particular the targets are:
-
-* (1) Platforms that have very limited memory
- * Microcontrollers and embedded systems with limited memory
- * Popular MCU board families and manufacturers (Arduino, STM32, ESP32, NXP, etc.) commonly offer boards that only have an order of 10’s or 100’s of kB of memory available.
- * Firmware, and especially firmware projects that are run from SRAM, or ROM
-* (2) Environments where runtime dependencies, implicit runtime calls, and heap allocations are restricted
- * Low-level environments without an underlying operating system, such as bootloaders, hypervisors, firmware
- * Operating system kernels, kernel extensions, and other non-userspace software components
- * Userspace components that are too low-level in terms of dependencies, namely anything that the Swift runtime depends on.
- * A special case here is the Swift runtime itself, which is today written in C++. The concepts described further in this document allow Swift to become the implementation language instead.
-
-A significant portion of the current Swift runtime and standard library supports Swift’s more dynamic features, particularly those that involve metadata. These features include:
-
-* Dynamic reflection facilities (such as mirrors, `as?` downcasts, and printing arbitrary values)
-* Existentials
-* ABI stability with support for library evolution
-* Separately-compiled generics
-* Dynamic code loading (plug-ins)
-
-On “smaller” operating systems, and in restricted environments with limited binary and memory size, the size of a full Swift standard library (with all public types and APIs present) and a Swift runtime, as well as the metadata required to support dynamic features, can be so large as to prevent the usage of Swift completely. In such environments, it may be reasonable to trade away some of the flexibility from the more dynamic features to achieve a significant reduction in code size, while still retaining the character of Swift.
-
-The following diagram summarizes the existing approaches to shrink down the size of the Swift runtime and standard library, and how “Embedded Swift” is tackling the problems with a new approach:
-
-
-
-This document presents a vision for “Embedded Swift”, a new compilation model of Swift that can produce extremely small binaries without external dependencies, suitable for restricted environments including embedded (microcontrollers) and baremetal setups (no operating system at all), and low-level environments (firmware, kernels, device drivers, low-level components of userspace OS runtimes).
-
-Embedded Swift limits the use of language and standard library features that would require a larger Swift runtime, while maintaining most of Swift’s feature set. It is important that Embedded Swift not become a separate dialect of Swift. Rather, it should remain an easy-to-explain subset of Swift that admits the same code and idioms as the full Swift language, where any restrictions on the language model are flagged by the Swift compiler. The subset itself should also be useful beyond low-level environments, for example, in high-performance runtimes and kernels embedded within a larger Swift application. The rest of this document describes exactly which language features are impacted, as well as the compilation model used for restricted environments.
-
-## Goals
-
-There are several goals of this new compilation mode:
-
-* **Eliminate the “large codesize cost of entry”** for Swift. Namely, the size of the supporting libraries (Swift runtime and standard library) must not dominate the binary size compared to application code.
-* **Simplify the code generated by the compiler** to make it easier to reason about it, and about its performance and runtime cost. In particular, complex runtime mechanisms such as runtime generic instantiation are undesirable.
-* **Allow effective and intuitive dead-code stripping** on application, library and standard library code.
-* **Support environments with and without a dynamic heap**. Effectively, there will be two bottom layers of Swift, and the lower one, “non-allocating” Embedded Swift, will necessarily be a more restricted compilation mode (e.g. classes will be disallowed as they fundamentally require heap allocations) and likely to be used only in very specialized use cases. “Allocating” Embedded Swift should allow classes and other language facilities that rely on the heap (e.g. indirect enums).
-* **Remove or reduce the amount of implicit runtime calls**. Specifically, runtime calls supporting heavyweight runtime facilities (type metadata lookups, generic instantiation) should not exist in Embedded Swift programs. Lightweight runtime calls (e.g. refcounting) are permissible but should only happen when the application uses a language feature that needs them (e.g. refcounted types).
-* **Introduce a way of producing minimal statically-linked binaries** without external dependencies, namely without the need to link with a non-dead-strippable large Swift runtime/stdlib library, and without the need to link full libc and libc++ libraries. The Swift standard library contains essential facilities for writing Swift code, and must be available to write code against, but it should “fold” into the application and/or be intuitively dead-strippable.
-* **Define a language subset, not a dialect.** Any code of Embedded Swift should always compile in regular Swift and behave the same.
- * **The Embedded Swift language subset should stay very close to “full” Swift**, even if it means adding alternative ABIs to the compiler to support some of them. Users should expect minimal porting effort to get code to work in Embedded Swift.
-
-## Embedded Swift Language Subset
-
-In order to achieve the goals listed above, Embedded **Swift** will impose limitations on certain language features:
-
-* Library Evolution will be limited in some way, and there’s no expectation of ABI stability or separate distribution of libraries in binary form.
-* Objective-C interoperability will not be available. C and C++ interoperability is not affected.
-* Reflection and Mirrors APIs will not be available.
-* The standard library’s print() function in its current form will not be available, and an alternative will be provided instead.
-* Metatypes will be restricted in some way, and code patterns where a metatype value is actually needed at runtime will be disallowed (but at a minimum using a metatype function argument as a type hint will be allowed, as well as calling class methods and initializers on concrete types).
- Examples:
- ```swift
- func foo(t: T.Type) { ... `t` used in a downcast ... } // not OK
- extension UnsafeRawPointer {
- func load(as type: T.Type) -> T { ... `type` unused ... } // OK
- }
- MyGenericClass.classFunc() // OK
- ```
-* Existentials and dynamic downcasting of existentials will be disallowed. For example:
- ```swift
- func foo(t: Any.Type) {} // not OK
- var e: any Comparable = 42 // not OK
- var a: [Any] = [1, "string", 3.5] // not OK
- ```
-* The types of thrown errors will be restricted in some manner, because thrown errors are of existential type `any Error` (which is disallowed by the prior item).
-* Classes will have restrictions, for example they cannot have non-final generic functions. For example:
- ```swift
- class MyClass {
- func member() { } // OK
- func genericMember { } // not OK
- }
- ```
- It’s an open question whether class metatypes are allowed to be used as runtime values and whether classes will allow dynamic downcasting.
-* KeyPaths will be restricted, but at a minimum it will be allowed to use keypath literals to form closures returning a field from a type, and it will be allowed to use keypaths that are compile-time references to inlined stored properties (so that `MemoryLayout.offset(of: ...)` will work on those).
-* String APIs requiring Unicode data tables will be unavailable by default (to avoid paying the associated codesize cost), and will require opting in. For example, string iteration, comparing two strings, hashing a string, string splitting are features needing Unicode data tables. These operations should become available on UTF8View instead with the proposal to add Equatable and Hashable conformances to String views ([link](https://forums.swift.org/t/pitch-add-equatable-and-hashable-conformance-to-string-views/60449)).
-
-**Non-allocating Embedded Swift** will add further restrictions on top of the ones listed above:
-
-* Classes cannot be instantiated, indirect enums cannot be constructed.
-* Escaping closures are not allowed.
-* Standard library features and API that rely on classes, indirect enums, escaping closures are not available. This includes for example dynamic containers (arrays, dictionaries, sets) and strings.
-
-The listed restrictions (for both “allocating” and “non-allocating” Embedded Swift) are not necessarily fundamental, and we might be able to (fully or partially) lift some of them in the future, by adding alternative compile-time implementations (as opposed to their current runtime implementations) of the language features.
-
-## Implementation of Embedded Compilation Mode
-
-The following describes the high-level points in the approach to implement Embedded Swift in the compiler:
-
-* **Specialization is required on all uses of generics and protocols** at compile-time, and libraries are compiled in a way that allows cross-module specialization (into clients of the libraries).
- * Required specialization (also known as monomorphization in other compilers/languages) needs type parameters of generic types and functions to always be compile-time known at the caller site, and then the compiler creates a specialized instantiation of the generic type/function that is no longer generic. The result is that the compiled code does not need access to any type metadata at runtime.
- * This compilation mode will not support separate compilation of generics, as that makes specialization not possible. Instead, library code providing generic types and functions will be required to provide function bodies as serialized SIL (effectively, “source code”) to clients via the mechanism described below.
-* **Library code is built as always inlinable and “emitIntoClient”** to support the specialization of generics/protocols in use sites that are outside of the library.
- * **This applies to the standard library, too**, and we shall distribute the standard library built this way with the toolchain.
- * This effectively provides the source code of libraries to application builds.
-* **The need for type metadata at runtime is completely eliminated**, by further ignoring ABI stability, disabling resilience, and disallowing reflection mirrors APIs. Classes with subclasses get a simple vtable (similar to C++ virtual classes). Classes without subclasses become final and don’t need a vtable. Witness tables (which describe a conformance of a type to a protocol) are only used at compile-time and not present at runtime.
- * **Type metadata is not emitted into binaries at all.** This causes code emitted by the compiler to become dead-strippable in the intuitive way given that metadata records (concretely type metadata, protocol conformance records, witness tables) are not present in compiler outputs.
- * **Runtime facilities to process metadata are removed** (runtime generic instantiation, runtime protocol conformance lookups) because there is no metadata present at runtime.
-
-## Enabling Embedded Swift Mode
-
-The exact mechanics of turning on Embedded Swift compilation mode are an open question and subject to further discussion and refinement. There are different use cases that should be covered:
-
-* the entire platform / system is using Embedded Swift as a platform level decision
-* a single component / library is built using Embedded Swift for an environment that otherwise has other code built with other compilation modes or compilers
-* for testing purposes, it’s highly desirable to be able to build a library using Embedded Swift and then exercise that library with a test harness that is built with regular Swift
-
-A possible solution here would be to have a top-level compiler flag, e.g. `-embedded`, but we could also make environments default to Embedded Swift mode where it makes sense to do so, based on the target triple that’s used for the compilation. Specifically, the existing “none” OS already has the meaning of “baremetal environment”, and e.g. `-target arm64-apple-none` could imply Embedded Swift mode.
-
-Building firmware using `-target arm64-apple-none` would highlight that we’re producing binaries that are “independent“ and not built for any specific OS. The standard library will be pre-built in the baremetal mode and available in the toolchain for common set of CPU architectures. (It does not need to be built “per OS”.)
-
-To support writing code that’s compiled under both regular Swift and also Embedded Swift, we should provide facilities to manage availability of APIs and conditional compilation of code. The concrete syntax for that is subject to discussion, the following snippet is presented only as a straw-man proposal:
-
-```swift
-@available(embedded, unavailable, "not available in Embedded Swift mode")
-public func notAvailableOnEmbedded()
-
-#if !mode(embedded)
-... code not compiled under Embedded Swift mode ...
-#endif
-
-@available(noAllocations, unavailable, "not available in no allocations mode")
-public func notAvailableInNonAllocatingMode()
-
-#if !mode(noAllocations)
-... code not compiled under no allocations mode ...
-#endif
-```
-
-## Dependencies of Embedded Swift Programs
-
-The expectation is that for “non-allocating” Embedded Swift, the user should only need a working Swift toolchain, and be able to pass a (set of) .swift file(s) to the compiler and receive a .o file that is just as simple to work with (e.g. to be linked into any library, app, firmware binary, etc.) as if it was produced by Clang on source code written in C:
-
-```
-$ swiftc *.swift -target arm64-apple-none -no-allocations -wmo -c -o a.o
-$ nm -gm a.o
-... shows no dependencies beyond memset/memcpy ...
-memset
-memcpy
-```
-
-A similar situation is expected even for "allocating" Embedded Swift, except that there will be a need for a small runtime library (significantly smaller compared to the existing Swift runtime written in C++) to support object instantiation and refcounting:
-
-```
-$ swiftc *.swift -target arm64-apple-none -wmo -c -o a.o
-$ nm -gm a.o
-... only very limited dependencies ...
-malloc
-calloc
-free
-swift_allocObject
-swift_initStackObject
-swift_initStaticObject
-swift_retain
-swift_release
-```
-
-The malloc/calloc/free APIs are expected to be provided by the platform. The Swift runtime APIs will be provided as an implementation that’s optimized for small codesize and will be available as a static library in the toolchain for common CPU architectures. Interestingly, it’s possible to write that implementation in “non-allocating” Baremetal Swift.
-
## Topics
### Getting Started
+-
+-
-
--
### Guided Examples
--
+-
+-
+-
+-
+
+### Using Embedded Swift
+
+-
+-
+-
+-
+-
+-
+-
### Build System Support
--
+-
-
-
-
@@ -189,22 +41,12 @@ The malloc/calloc/free APIs are expected to be provided by the platform. The Swi
### SDK Support
+-
+-
+-
-
-### Language Details
+### Compiler Development and Details
-
--
--
-
-### Development
-
-
-
-## See Also
-
-### Community Links
-
-- [Swift forums topic](https://forums.swift.org/)
-- [Slack channel](https://forums.swift.org/)
-- [Discord channel](https://forums.swift.org/)
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/InstallEmbeddedSwift.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/InstallEmbeddedSwift.md
index 0c918fe..18aaee2 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/InstallEmbeddedSwift.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/InstallEmbeddedSwift.md
@@ -1,10 +1,10 @@
# Install Embedded Swift
-Get the tools needed to use Embedded Swift.
+Get the tools needed to use Embedded Swift
## Overview
-Embedded Swift is an experimental and rapidly developing feature of the Swift language, as such it is only available in "Development Snapshot".
+> Warning: Embedded Swift is experimental. Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.
The best way to install Swift is using [`swiftly`](http://github.com/swiftlang/swiftly), the official Swift toolchain installer and manager. For instructions on how to install `swiftly`, check out the [Getting Started](https://www.swift.org/swiftly/documentation/swiftly/getting-started) guide.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md
new file mode 100644
index 0000000..981e0cf
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/Introduction.md
@@ -0,0 +1,59 @@
+# Introduction to Embedded Swift
+
+Write Swift code for microcontrollers, embedded systems, and bare-metal applications
+
+## Overview
+
+Embedded Swift is an experimental and rapidly developing feature of the Swift language that enables development of baremetal, embedded and standalone software. It's a subset of the Swift language designed for producing small, efficient binaries with minimal dependencies, making it suitable for resource-constrained environments.
+
+> Warning: Embedded Swift is experimental. Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.
+
+## How does Embedded Swift differ from regular Swift?
+
+Regular Swift is not a good fit for small constrained environments like microcontrollers, mainly due to codesize and memory footprint. Regular Swift typically requires at least a few megabytes of code and data to support dynamic language features like reflection, and separately compiled generics with ABI stability. Embedded Swift, on the other hand, can be deployed to environments with as little as kilobytes of available memory. This is achieved by:
+
+- Eliminating runtime type metadata where possible
+- Removing reflection capabilities
+- Using compile-time specialization (monomorphization) for generic code
+- Minimizing dependencies on external libraries
+
+This results in properties that are a great fit for embedded software development:
+
+- **Small binaries** that can be as tiny as a few hundred bytes for "Hello World"-like programs (fully self-contained).
+- **No hidden runtime costs** – Embedded Swift's runtime library does not manage any data structures behind your back, is itself less than a kilobyte in size, and it eligible to be removed if unused.
+- **Full C/C++ interoperability** to directly interact with existing C libraries and hardware-specific code, making it easy to integrate with vendor SDKs.
+- **Modern language features** like optionals, generics, and strong type safety are all available in Embedded Swift.
+- **Full safety of Swift** is retained in Embedded Swift.
+
+For a detailed introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches. Note that this is a historical document and does not capture latest development and further evolution. For an up-to-date in-depth breakdown of the language features of Embedded Swift, please see .
+
+## What Embedded Swift is and isn't
+
+- Embedded Swift **is** a way to produce small and freestanding binaries (with no, or trivial dependencies).
+- Embedded Swift **is not** a complete one-click solution to program all embedded boards and MCUs.
+- Embedded Swift **is** a compilation model that's analogous to a traditional C compiler in the sense that the compiler produces an object file (.o) that can be simply linked with your existing code, and it's not going to require you to port any libraries or runtimes.
+- Embedded Swift **is not** a HAL, it's not an SDK for development, it's not a set of libraries to program peripherals using high-level APIs. It's instead a compilation mode that's suitable for creating these components.
+
+## Platform support
+
+The Swift toolchain has the ability to produce code for almost any standard ARM and RISC-V platform, and that makes Embedded Swift versatile and not limited to specific platforms or hardware devices. This way, Embedded Swift can potentially target many different microcontroller families and embedded devices.
+
+Boards with active community support include the Raspberry Pi Pico, various STM32 development boards, and several ESP32 variants, with more platforms being regularly added as the community grows.
+
+## Interoperability with existing SDKs
+
+Software projects using Embedded Swift are typically developed in one of the following ways:
+
+1. Integrating with an existing SDK (typically in C, or C++) that provides either an embedded OS, or OS-like facilities, hardware drivers, and overall functionality that's needed for embedded software.
+
+2. Writing fully "bare-metal" code, without any pre-existing setup or SDK. This is typically done for extremely constrained environments and/or when full control of every piece of code is needed.
+
+Both the approaches are readily available in Embedded Swift, and the choice of which approach to use depends on your specific project requirements, hardware constraints, and development preferences. For integrating with existing SDKs, Swift's C/C++ interoperability makes it straightforward to call native SDK functions, while the bare-metal approach gives you complete control over every aspect of your code's execution environment.
+
+## Getting Started
+
+To start using Embedded Swift, please see the page for installation instructions.
+
+Once you've set up the toolchain, we recommend exploring the page which provides various paths for getting started, including the to try Embedded Swift on your development machine, and more advanced guides such as for programming an actual embedded device.
+
+For details about using Embedded Swift, consult the documentation, which explains how to build code with Embedded Swift and shows integration patterns with embedded SDKs and build systems.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md
new file mode 100644
index 0000000..9cd1bf7
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/LanguageSubset.md
@@ -0,0 +1,29 @@
+# Language subset
+
+Details of the Embedded Swift language subset compared to full Swift
+
+Embedded Swift is a subset of the Swift language, and some features are not available in Embedded Swift. This is necessary in order to achieve small binaries with effective dead-code elimination and minimized system dependencies.
+
+That said, *the vast majority* of the Swift language works exactly the same in Embedded Swift. This includes generics, protocols, enums with associated values, tuples, optionals, classes (instances are allocated on the heap and refcounted just like in regular Swift), inheritance, runtime polymorphism, arrays (heap-allocated copy-on-write just like in regular Swift) and much more.
+
+Note that there are no behavior changes in Embedded Swift compared to full Swift, and Embedded Swift is strictly a *subset* and not a *dialect*. Any code compatible with Embedded Swift will also compile and have the same semantics in full Swift.
+
+## Code-level features that are not available
+
+- **Not available**: Runtime reflection (`Mirror` APIs).
+- **Not available**: Values of protocol types ("existentials"), unless the protocol is restricted to be class-bound (derived from AnyObject). E.g. `let a: Hashable = ...` is not allowed. `Any` is also not allowed. See for details and alternatives of existentials.
+- **Not available**: Throwing errors or `any Error` type (in contrast with "typed throws", which *is* supported in Embedded Swift).
+- **Not available**: Metatypes, e.g. `let t = SomeClass.Type` or `type(of: value)` are not allowed.
+- **Not available**: Printing and stringification of arbitrary types (which is achieved via reflection in desktop Swift).
+- **Not available**: Using non-final generic class methods. See for details on this.
+- **Not available**: Weak and unowned references.
+
+## Compilation facilities that are not available
+
+- **Not available**: Library Evolution (stable ABI), and facilities that requires Library Evolution (e.g. internal module imports)
+- **Not available**: Objective-C interoperability
+- **Not available**: Builds without WMO (whole module optimization)
+
+## Further resources
+
+The above lists are describing features that are removed from Embedded Swift *by design*. Since Embedded Swift is currently an experimental preview, there might also be features that are not yet implemented. See the in-development status at [Embedded Swift -- Status](EmbeddedSwiftStatus.md).
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/UserManual.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/UserManual.md
deleted file mode 100644
index de931f0..0000000
--- a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/UserManual.md
+++ /dev/null
@@ -1,278 +0,0 @@
-# User Manual
-
-**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.**
-
-**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.**
-
-For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
-
-The following document explains how to use Embedded Swift's support in the Swift compiler and toolchain.
-
-## What Embedded Swift is, and what it isn't
-
-- Embedded Swift **is** a way to produce small and freestanding binaries (with no, or trivial dependencies).
-- Embedded Swift **is not** a complete one-click solution to program all embedded boards and MCUs.
-- Embedded Swift **is** a compilation model that's analogous to a traditional C compiler in the sense that the compiler produces an object file (.o) that can be simply linked with your existing code, and it's not going to require you to port any libraries or runtimes.
-- Embedded Swift **is not** a HAL, it's not an SDK for development, it's not a set of libraries to program peripherals using high-level APIs. It's instead a compilation mode that's suitable for creating these components.
-
-## Using Embedded Swift
-
-A typical setup and build + run cycle for an embedded development board involves:
-
-- (1) Getting an SDK with the C compilers, headers and libraries for the target
-- (2) Building the C source code, and Swift source code into object files.
-- (3) Linking all the libraries, C object files, and Swift object files.
-- (4) Post-processing the linked firmware into a flashable format (UF2, BIN, HEX, or bespoke formats)
-- (5) Uploading the flashable binary to the board over a USB cable using some vendor-provided JTAG/SWD tool, by copying it to a fake USB Mass Storage volume presented by the board or a custom platform bootloader.
-- (6) Restarting the board, observing physical effects of the firmware (LEDs light up) or UART output over USB, or presence on network, etc.
-
-Most of these steps are out of scope for this document, instead refer to the vendor provided documentation. This document only focuses on (2) from the list above, and it's important that you first get familiar with the details of firmware development for your board without Swift in the mix. Even if you want to build a completely pure Swift firmware, you are still going to need the vendor provided tooling for linking, post-processing, uploading, etc.
-
-## Building code using Embedded Swift
-
-A basic way to build a set of Swift source files in Embedded Swift mode, is to simply give the compiler (1) a target triple, (2) the `-enable-experimental-feature Embedded` flag, (3) the set of source files that form the input module:
-
-```bash
-$ swiftc -target -enable-experimental-feature Embedded -wmo \
- input1.swift input2.swift ... -c -o output.o
-```
-
-On macOS, it's common to have Xcode installed, which comes with a toolchain that does not support Embedded Swift yet. Unless you download, install, and activate a swift.org toolchain, you'll see this error:
-
-```bash
-$ swiftc input1.swift -enable-experimental-feature Embedded -wmo
-:0: error: unable to load standard library for target 'arm64-apple-macosx15.0'
-```
-
-To resolve it, download and install a nightly toolchain from swift.org. Then, don't forget to activate it in your terminal by setting the `TOOLCHAINS` environment variable, for example with this command (if you installed into the `/Library` path):
-
-```bash
-$ export TOOLCHAINS=$(plutil -extract CFBundleIdentifier raw /Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist)
-```
-
-## Examples
-
-### Building Swift firmware for an embedded target
-
-To build Swift firmware (for now ignoring integration with SDKs, libraries and other pre-existing C code), we can use the `-target` argument to specify the CPU architecture. The target triple also decides whether the output object file will be an ELF file, or a Mach-O. For example:
-
-```bash
-# To build an ARMv7 Mach-O object file:
-$ swiftc -target armv7-apple-none-macho -enable-experimental-feature Embedded -wmo \
- input1.swift input2.swift ... -c -o output.o
-
-# To build an ARMv7 ELF object file:
-$ swiftc -target armv7-none-none-eabi -enable-experimental-feature Embedded -wmo \
- input1.swift input2.swift ... -c -o output.o
-```
-
-Additionally, you probably want to specify additional Clang and/or LLVM flags to get the compiler to produce code for the exact ISA and ABI you need for your target.
-
-For example, a Raspberry Pi Pico / Pico W should target the ARMv6-M architecture via the `armv6m-*` target triple, but the `-mfloat-abi=soft` Clang option should also be used, and if you want to match ABI with libraries built with the GNU toolchain, you might also need `-fshort-enums`. To pass those to Swift, use the `-Xcc` prefix:
-
-```bash
-# To build an ELF object file for ARMv6-M with soft float ABI (floating-point arguments passed in integer registers) and "short enums":
-$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo \
- -Xcc -mfloat-abi=soft -Xcc -fshort-enums \
- input1.swift input2.swift ... -c -o output.o
-```
-
-This might not be obvious: `-Xcc` flags are typically only used to alter behavior of the Clang importer, but passing flags to Clang this way also works to specify LLVM target options like selecting a specific CPU architecture (`-march`, `-mcpu`, `-mmcu`), FPU unit availability (`-mfpu`), which registers are used to pass floating-point values (`-mfloat-abi`), and others.
-
-### Integrating with embedded SDKs and build systems
-
-For details and concrete examples of how to integrate with existing SDKs, see [Embedded Swift -- Integrating with embedded SDKs](IntegratingWithSDKs.md).
-
-### Building a macOS Embedded Swift program:
-
-It's also possible to build in Embedded Swift mode for regular non-embedded operating systems, like macOS. This is very useful for testing purposes, or if you just want to observe and experiment with Embedded Swift. A simple source code like this:
-
-```swift
-print("Hello, embedded world!")
-```
-
-...can be compiled using the `-enable-experimental-feature Embedded` flag (the implicit `-target` matches the host OS):
-
-```bash
-$ xcrun swiftc hello.swift -enable-experimental-feature Embedded -wmo
-$ ./hello
-Hello, embedded world!
-```
-
-Note that the resulting executable is still a *dynamically-linked executable*, so it's not fully standalone in the embedded sense. Namely is still uses `putchar` from Libsystem. But the singular object file that was used to build this executable was produced by the compiler in the same fashion that a real embedded build would. If we ask the compiler and linker to minimize the size of the outputs and to remove any unused code, we can observe that the binary has no other dependencies other than `putchar` and that the machine code section is very small (172 bytes in the `__text` section):
-
-```bash
-$ xcrun swiftc hello.swift -enable-experimental-feature Embedded -wmo -Osize -Xlinker -dead_strip
-$ nm -um ./hello
- (undefined) external _putchar (from libSystem)
-$ size -m ./hello
-Segment __TEXT: 16384
- Section __text: 172
-...
-```
-
-## Strings
-
-Both StaticString and String types are available in Embedded Swift. As is the case in desktop Swift, certain operations on strings require Unicode data tables for strict Unicode compliance. In Embedded Swift these data tables are provided as a separate static library (libUnicodeDataTables.a) that users need to link in manually – if they need to use these string operations. If the library is required, linking will fail due to missing on one or more of the following symbols:
-
-```
-_swift_stdlib_getAge
-_swift_stdlib_getBinaryProperties
-_swift_stdlib_getCaseMapping
-_swift_stdlib_getComposition
-_swift_stdlib_getDecompositionEntry
-_swift_stdlib_getGeneralCategory
-_swift_stdlib_getGraphemeBreakProperty
-_swift_stdlib_getMapping
-_swift_stdlib_getMphIdx
-_swift_stdlib_getNameAlias
-_swift_stdlib_getNormData
-_swift_stdlib_getNumericType
-_swift_stdlib_getNumericValue
-_swift_stdlib_getScalarBitArrayIdx
-_swift_stdlib_getScalarName
-_swift_stdlib_getScript
-_swift_stdlib_getScriptExtensions
-_swift_stdlib_getSpecialMapping
-_swift_stdlib_getWordBreakProperty
-_swift_stdlib_isLinkingConsonant
-_swift_stdlib_nfd_decompositions
-```
-
-To resolve this, link in the `libswiftUnicodeDataTables.a` that's in Swift toolchain's resource directory (`lib/swift/`) under the target triple that you're using:
-
-```bash
-$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo -c -o output.o
-$ ld ... -o binary output.o $(dirname `which swiftc`)/../lib/swift/embedded/armv6m-none-none-eabi/libswiftUnicodeDataTables.a
-```
-
-**Unicode data tables are required for (list not exhaustive):**
-
-- Comparing String objects for equality
-- Sorting Strings
-- Using String's hash values, and in particular using String as dictionary keys
-- Using String's `.count` property
-- Using Unicode-aware string processing APIs (`.split()`, iterating characters, indexing)
-- Using Unicode-aware conversion String APIs (`.uppercased()`, `.lowercased()`, etc.)
-
-**For contrast, unicode data tables are *not required for* (list not exhaustive):**
-
-- Using StaticString
-- Creating, concatenating, string interpolating, and printing String objects
-- Using `.utf8`, `.utf16`, and `.unicodeScalars` views of strings, including their .count property, using them as dictionary keys
-
-Manually linking `libswiftUnicodeDataTables.a` is required for several reasons, including acknowledging that the data tables are desirable: Since they have a non-negligible size, it's useful to be aware that you are using them.
-
-## Conditionalizing compilation for Embedded Swift
-
-It's often useful to have source code be compilable under both regular Swift and Embedded Swift. The following syntax is available for that (but note that as the rest of Embedded Swift, it's experimental, subject to change and not considered source stable):
-
-```swift
-func sayHello() {
- #if hasFeature(Embedded)
- print("I'm Embedded Swift")
- #else
- print("I'm regular Swift")
- #endif
-}
-```
-
-Additionally, you can also use an attribute (also experimental, and not source stable) to make entire functions, types and other declarations unavailable in Embedded Swift. This can be particularly useful to explicitly mark your own code (and also entire types and conformances) that relies on features unavailable in Embedded Swift, e.g. the Any type or Codable -- it is explicitly allowed to use those in unavailable contexts:
-
-```swift
-@_unavailableInEmbedded
-func useAny(_: Any) { ... }
-
-@_unavailableInEmbedded
-extension MyStruct: Codable {
- ...
-}
-```
-
-## Embedded Swift is a subset of Swift
-
-Embedded Swift is a subset of the Swift language, and some features are not available in Embedded Swift, however features are available, including: Generics, protocols, enums with associated values, tuples, optionals, classes (instances are allocated on the heap and refcounted just like in regular Swift), inheritance, runtime polymorphism, arrays (heap-allocated copy-on-write just like in regular Swift) and many more.
-
-Features that are not available:
-
-- **Not available**: Runtime reflection (`Mirror` APIs).
-- **Not available**: Values of protocol types ("existentials"), unless the protocol is restricted to be class-bound (derived from AnyObject). E.g. `let a: Hashable = ...` is not allowed. `Any` is also not allowed.
-- **Not available**: Metatypes, e.g. `let t = SomeClass.Type` or `type(of: value)` are not allowed.
-- **Not available**: Printing and stringification of arbitrary types (achieved via reflection in desktop Swift).
-- **Not available yet (under development)**: Swift Concurrency.
-
-For a more complete list of supported features in Embedded Swift, see [Embedded Swift -- Status](EmbeddedSwiftStatus.md).
-
-## Libraries and modules in Embedded Swift
-
-Traditional library build and use model of Swift is that library code is compiled into a .swiftmodule, containing the interfaces, and a compiled library with binary code, either a .a static library or a .dylib/.so dynamic library. A client's build then uses the .swiftmodule at compile-time, and the static/dynamic library at link-time.
-
-The library model in Embedded Swift works slightly differently: All Swift source code of a library is promoted into being inlineable and visible to client builds (this is necessary for generic code, and beneficial for optimizations for non-generic code), and ends up serialized into the .swiftmodule, the interface of the library. Therefore, the compiled code of a library is never needed, and doesn't even need to be produced. For example:
-
-```bash
-# Build the library, only as a .swiftmomodule. Notice that we never build the .o or .a for the library.
-$ swiftc -target -enable-experimental-feature Embedded -wmo \
- a.swift b.swift -module-name MyLibrary -emit-module -emit-module-path ./MyLibrary.swiftmodule
-
-# Build the client, "-I ." add the current directory to the module search path list
-$ swiftc -target -enable-experimental-feature Embedded -wmo \
- client.swift -I . -c -o client.o
-```
-
-The Embedded Swift standard library is distributed in the toolchain the same way: It's strictly a .swiftmodule without any compiled code present anywhere. All the compiling into machine code is performed as part of the client's build. This has the major benefit that the client's build can provide additional ABI and ISA defining flags, such as the above-mentioned `-mfloat-abi`, `-fshort-enums`, `-mcpu`, `-march` flags, and these flags in the client's build will apply to all the library code (including standard library code) as well.
-
-## Allocating and non-allocating Embedded Swift mode
-
-Embedded Swift does allow instantiating and using reference types (classes) which are refcounted objects allocated on the heap. A common case of needing those is for dynamic containers like arrays and sets (they use dynamically-sized heap-allocated class instances as their storage). There is only a handful of Swift language features that cause allocations:
-
-- creating class instances,
-- escaping a closure that captures local variables,
-- creating an indirect enum case with a payload referencing the enum itself
-- explicitly calling allocation APIs (e.g. `UnsafeMutablePointer.allocate()`).
-
-Outside of those cases, Embedded Swift does not perform allocations or cause heap usage.
-
-Some embedded platforms don't have and/or don't want *any heap allocations whatsoever* and don't provide a heap at all. The `-no-allocations` compiler flag can be used to match that, which will cause the compiler to produce an error at compile time when creating class instances or calling allocation APIs.
-
-```bash
-$ cat test.swift
-let p = UnsafeMutablePointer.allocate(capacity: 10)
-$ swiftc test.swift -enable-experimental-feature Embedded -wmo -no-allocations
-test.swift:1:37: error: cannot use allocating operation in -no-allocations mode
-```
-
-## External dependencies
-
-Embedded Swift minimizes external dependencies (i.e. functions that need to be available at link-time), but they still exist. There are generally two categories of dependencies: (1) functions that the Swift standard library or Embedded Swift runtime need to call, and (2) functions/symbols that are implicitly added by LLVM and the compiler pipeline.
-
-For (1), external dependencies are only used based on actual usage of the program under compilation:
-
-- instantiating a class, or using UnsafeMutablePointer.allocate()
- - dependency: `int posix_memalign(void **, size_t, size_t);`
- - dependency: `void free(void *);`
-- using print()
- - dependency: `int putchar(int);`
-- using Hashable, Set, Dictionary, or random-number generating APIs
- - dependency: `void arc4random_buf(void *, size_t);`
-
-For (2), external dependencies are also triggered by specific code needing them, but they are somewhat lower-level patterns where it might not be obvious that such patterns should cause external dependencies:
-
-- **basic memory copying and zeroing functions**
- - usage added for a variety of reasons (e.g. using structs on the stack)
- - dependency: `void *memset(void *, int, size_t);`
- - dependency: `void *memcpy(void *, const void *, size_t);`
-- **stack protectors** (aka stack cookies or stack canaries)
- - dependency: `void *__stack_chk_guard;`
- - dependency: `void __stack_chk_fail(void);`
- - stack protectors can be disabled with `-disable-stack-protector` swiftc flag
-- **atomics intrinsics**
- - 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 intrinsics**
- - on CPU architectures that don't have direct support for the math operations in the ISA
- - dependency (on Mach-O): `__divti3`
- - dependency (on Mach-O): `__modti3`
- - dependency (with EABI): `__aeabi_ldivmod`
-
-The user and/or the platform (via basic libraries like libc or compiler builtins) is expected to provide these well-known APIs.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/WaysToGetStarted.md b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/WaysToGetStarted.md
new file mode 100644
index 0000000..34fed8d
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/GettingStarted/WaysToGetStarted.md
@@ -0,0 +1,40 @@
+# Getting started with Embedded Swift
+
+Possible directions to explore to start using Embedded Swift
+
+## Introduction
+
+> Warning: Embedded Swift is experimental. Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.
+
+Embedded Swift is a way to write code for embedded systems using the Swift programming language. Depending on the use case, there are different ways of using it, different ways of integrating with existing ecosystems, and different setups for different hardware devices. This guide will help you explore various paths to get started with embedded development using Swift.
+
+Before diving into Embedded Swift development, you should have:
+
+- Basic knowledge of the Swift programming language
+- A Swift toolchain installed on your development host
+- A target embedded platform in mind (e.g. a Raspberry Pi Pico)
+ - this can also be a simulated hardware platform (e.g. in QEMU), or even a full desktop OS environment in case you're not interested in controlling low-level hardware or custom electronic peripherals
+
+## Guided Tutorials
+
+To help you get started with Embedded Swift, we've prepared several step-by-step guides that cover different platforms and use cases:
+
+- - Try out Embedded Swift on your development machine
+- - Build and run Swift code on a Raspberry Pi Pico
+- - Set up a baremetal Swift project for STM32 microcontrollers
+
+These guides provide a practical introduction to Embedded Swift development with specific hardware targets, showing you how to build, upload, and run your first Swift programs on embedded systems.
+
+## Other Resources
+
+For a deeper understanding of Embedded Swift concepts and philosophy, check out these resources:
+
+- - Learn about the core concepts and philosophy of Embedded Swift
+- - Understand which Swift language features are available in Embedded Swift
+- - Detailed instructions for installing the required toolchain
+
+For developers coming from embedded C/C++ backgrounds or those integrating Swift into existing projects:
+
+- - Essential knowledge for using Embedded Swift effectively
+- - How to share code between Embedded Swift and standard Swift
+- - Understanding how libraries work in Embedded Swift
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/rpi-pico-blink-sdk.md b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md
similarity index 73%
rename from Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/rpi-pico-blink-sdk.md
rename to Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md
index 2526ba4..45ccb62 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/rpi-pico-blink-sdk.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/PicoGuide.md
@@ -1,5 +1,7 @@
# Raspberry Pi Pico Blink (Pico SDK)
+Tutorial for targetting a Raspberry Pi Pico as an embedded device that runs a simple Swift program
+
In this guide we'll be targeting a Raspberry Pi Pico as the embedded device that our Swift application will run on. If you don't physically have one, don't worry! You can still run the application in an online emulator.
## Installing Swift
@@ -14,7 +16,7 @@ To test that you have Swift installed, run `swift --version` from your shell or
## Installing dependencies for embedded development
-Install the Raspberry Pi Pico SDK, and the Arm Embedded Toolchain by following the [Getting Started With Pico guide](https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf).
+Install the Raspberry Pi Pico SDK, and the Arm Embedded Toolchain by following the [Getting Started With Pico guide](https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf).
Export three environment variables to match your setup and hardware:
```shell
@@ -27,7 +29,7 @@ If you have the Wi-Fi enabled Pico W board instead of the regular Pico, note tha
Install [CMake 3.29](https://cmake.org/) or newer.
-To test that you have all the neccessary parts installed, you can run the following commands in a terminal:
+To test that you have all the necessary parts installed, you can run the following commands in a terminal:
```shell
$ swift --version
@@ -36,7 +38,7 @@ $ cmake --version
cmake version 3.29.2
$ echo $PICO_BOARD
pico
-$ ls $PICO_SDK_PATH
+$ ls $PICO_SDK_PATH
CMakeLists.txt README.md external/ pico_sdk_version.cmake tools/
CONTRIBUTING.md cmake/ lib/ src/
LICENSE.TXT docs/ pico_sdk_init.cmake test/
@@ -167,48 +169,3 @@ If you don't have a physical Pico, or if you want to iterate quickly, [Wokwi](ht
Open a [new Pico project in Wokwi](https://wokwi.com/projects/new/pi-pico). Instead of using the code editor to write C code, press F1 and choose "Upload Firmware and Start Simulation". Then select the UF2 file that our build process produced.
Once you upload the UF2 file to Wokwi, the simulation will start, and the LED should begin blinking repeatedly. Hooray! Our first Embedded Swift program is running in an emulator!
-
-## Bonus: Building a simple program for your host OS with Embedded Swift
-
-While desktop operating systems like macOS and Linux are not the typical targets for Embedded Swift, you **absolutely can** build code for them using the Embedded Swift mode. This is useful for experimentation, trying out Embedded Swift, or to be able to iterate fast on an idea for some code that doesn't really need the physical device to work.
-
-The simplest program in Embedded Swift can just be a regular "Hello, World":
-
-```swift
-// HelloEmbedded.swift
-print("Hello, Embedded Swift 😊")
-```
-
-And building it into an executable can be done by calling the `swiftc` compiler directly, but we'll want to add flags to enable Embedded Swift, and also Whole Module Optimization.
-
-```shell
-$ swiftc HelloEmbedded.swift -o HelloEmbedded -enable-experimental-feature Embedded -wmo
-```
-
-This will produce a regular executable binary, but notice that it's very small in size and that it also *does not actually depend on the Swift runtime in the OS* (all Embedded Swift binaries carry their runtime+stdlib dependencies within):
-
-```shell
-$ ls -al
--rwxr-xr-x 1 kuba staff 18K May 16 17:19 HelloEmbedded*
--rw-r--r-- 1 kuba staff 59B May 16 17:16 HelloEmbedded.swift
-$ otool -L HelloEmbedded
-HelloEmbedded:
- /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1000.0.0)
-```
-
-Let's run it:
-
-```shell
-$ ./HelloEmbedded
-Hello, Embedded Swift 😊
-```
-
-Hooray! Our first *host-side* Embedded Swift program is working!
-
-## Where to go next
-
-- The [Embedded Swift Vision Document](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md) will give you an overview of the approaches and goals of Embedded Swift, and also what exactly is in the Embedded Swift language subset.
-- The [collection of Embedded Swift example projects](https://github.com/apple/swift-embedded-examples) on GitHub shows on which embedded devices can Swift work today, and the examples can also be used as templates for your own projects.
-- The [Embedded Swift User Manual](https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md) describes how to use the Embedded Swift compilation mode and how to interact with the compiler.
-- The [Tools page](https://www.swift.org/tools/#editors) has guides for setting up Swift integration in your editor to enable features like indexing, autocomplete, jump-to-definition, and others.
-- The [Swift forums](https://forums.swift.org/) are the best place to ask questions, give feedback or share your cool projects.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md
new file mode 100644
index 0000000..95d7fd7
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/STM32BaremetalGuide.md
@@ -0,0 +1,489 @@
+# Baremetal Setup for STM32 with Embedded Swift
+
+Program a STM32 microcontroller directly with low-level Swift code
+
+This tutorial will guide you through setting up a baremetal STM32 project with Embedded Swift to create a simple LED blinking application with text output to UART, the "Hello World" of embedded systems. Concretely, we'll be using the STM32F746G-DISCO (discovery) development board, but the setup will work (with only small tweaks) on most other STM32 devices.
+
+We will be writing a full firmware from scratch including low-level boot code, direct hardware register configuration, a custom linker script and more. Besides educational purposes, this level of control is typically only needed in specialized setups because it involves more work and more complexity. If you want a simpler path to get started, you can integrate with an existing embedded SDK (like STCube or BSPs) instead, which offers higher-level APIs and hardware abstraction. Check out for guidance on common integration patterns.
+
+## Overall plan
+
+The entire baremetal project will consist of:
+- A Package.swift file describing the overall structure of the project
+- Register definitions for GPIO registers generated by Swift MMIO
+- A toolset.json file defining compilation and linking flags
+- A Makefile that will serve as a simple shortcut for building and flashing
+- A simple linker script
+- An interrupt vector and a reset function implementing basic startup code
+- Finally, the application logic in Embedded Swift that will set up UART and print "Hello World"
+
+Let's get started!
+
+## Prerequisites
+
+- Mac or Linux
+- STM32F746G-DISCO board connected over a USB cable
+- Swift toolchain installed using swiftly
+
+## Step 1: Create a New Swift Package
+
+Create a new directory for your project and initialize a Swift package:
+
+```bash
+mkdir STM32BlinkLED
+cd STM32BlinkLED
+swift package init --type executable
+```
+
+The initial Swift code that this generates will be in `Sources/STM32BlinkLED/STM32BlinkLED.swift` and we can keep its current content for now:
+
+```swift
+// The Swift Programming Language
+// https://docs.swift.org/swift-book
+
+@main
+struct STM32BlinkLED {
+ static func main() {
+ print("Hello, world!")
+ }
+}
+```
+
+Let's work on getting this print to actually work and produce text into UART.
+
+## Step 2: Download Arm Toolchain for Embedded
+
+We're going to use the [Arm Toolchain for Embedded](https://github.com/arm/arm-toolchain/tree/arm-software/arm-software/embedded) (formerly called "LLVM Toolchain for ARM") to provide us with basic C-level helper code, concretely memset, memcpy, and an allocator (malloc, free).
+
+Go to [https://github.com/arm/arm-toolchain/releases](https://github.com/arm/arm-toolchain/releases) and download the latest released version of "ATfe" for your host OS:
+- On macOS, download e.g. `ATfE-20.1.0-Darwin-universal.dmg`.
+- On x86_64 Linux, download e.g. `ATfE-20.1.0-Linux-x86_64.tar.xz`.
+
+Expand and copy out the contents of the toolchain into a subdirectory `llvm-toolchain` of our project. We should end up with a structure of:
+```shell
+STM32BlinkLED
+|- llvm-toolchain
+ |- bin/
+ |- CHANGELOG.md
+ |- docs/
+ |- include/
+ |- lib/
+ |- README.md
+ |- ...
+|- Sources
+|- Package.swift
+```
+
+## Step 3: Configure the Package
+
+Edit the `Package.swift` file to configure your project for embedded development, specifically let's use Swift MMIO as a dependency, and let's create two helper targets "Registers" and "Support":
+
+```swift
+// swift-tools-version: 5.10
+import PackageDescription
+
+let package = Package(
+ name: "STM32BlinkLED",
+ platforms: [.macOS(.v11)],
+ products: [
+ .executable(name: "STM32BlinkLED", targets: ["STM32BlinkLED"])
+ ],
+ dependencies: [
+ .package(url: "https://github.com/apple/swift-mmio", branch: "main"),
+ ],
+ targets: [
+ .executableTarget(
+ name: "STM32BlinkLED",
+ dependencies: ["Registers", "Support"]),
+ .target(
+ name: "Registers",
+ dependencies: [.product(name: "MMIO", package: "swift-mmio")]),
+ .target(
+ name: "Support"),
+ ])
+```
+
+Then let's create the respective source directories for the new targets (empty for now):
+
+```shell
+$ mkdir Sources/Registers
+$ mkdir Sources/Support
+$ mkdir Sources/Support/include
+```
+
+## Step 4: Generate MMIO register descriptions using SVD2Swift
+
+SVD2Swift is a tool provided by Swift MMIO that automatically generates Swift code from SVD (System View Description) files. SVD files contain detailed descriptions of all the memory-mapped registers in a microcontroller, making them invaluable for embedded development. Using this generated code gives us type-safe access to the hardware registers of the STM32F7 microcontroller.
+
+First, we'll build the SVD2Swift tool from the swift-mmio package we added as a dependency, then download an SVD file for our specific microcontroller, and finally generate the register definitions we need:
+
+```shell
+$ swift build --product SVD2Swift
+$ curl -L "https://github.com/apple/swift-embedded-examples/raw/refs/heads/main/Tools/SVDs/stm32f7x6.patched.svd" -O
+$ .build/debug/SVD2Swift --input stm32f7x6.patched.svd --output Sources/Registers --access-level public \
+ --peripherals RCC USART1 GPIOA GPIOB GPIOC GPIOD GPIOE GPIOF GPIOG GPIOH GPIOI GPIOJ GPIOK
+```
+
+Tip: If a build fails for any reason, it's often useful to add the `--verbose` flag to `swift build` to see a full list of commands the build system runs.
+
+## Step 5: Create a toolset.json file
+
+Create a `toolset.json` file in the project directory to configure the build with essential settings for ARMv7-based STM32 microcontrollers. This file defines options for the Swift compiler, C compiler, and linker:
+
+```json
+{
+ "schemaVersion": "1.0",
+ "swiftCompiler": {
+ "extraCLIOptions": [
+ "-enable-experimental-feature", "Embedded",
+ "-Xfrontend", "-mergeable-symbols"
+ ]
+ }
+}
+```
+
+After this is done, let's attempt a build using `swift build`. We have to specify the path to the toolset file, and also the right target triple:
+
+```shell
+$ swift build --configuration release --triple armv7em-none-none-eabi --toolset toolset.json
+```
+
+Currently, this should succeed during compilation, but fail to link (because we haven't yet defined a valid linker script for embedded usage):
+
+```shell
+$ swift build --configuration release --triple armv7em-none-none-eabi --toolset toolset.json
+...
+error: link command failed with exit code 1 (use -v to see invocation)
+ld.lld: error: unable to find library -lc
+ld.lld: error: unable to find library -lm
+ld.lld: error: libclang_rt.builtins.a: No such file or directory
+clang: error: ld.lld command failed with exit code 1 (use -v to see invocation)
+```
+
+## Step 6: Create a Linker Script and Startup Code
+
+Let's now create a linker script, an interrupt vector and startup code.
+
+Create a linker script file named `stm32f4.ld` in the project root directory:
+
+```
+MEMORY
+{
+ flash (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* end: 0x08100000 */
+ sram_stack (rw) : ORIGIN = 0x20000000, LENGTH = 32K /* end: 0x20008000 */
+ sram_data (rw) : ORIGIN = 0x20008000, LENGTH = 160K /* end: 0x20030000 */
+ sram_heap (rw) : ORIGIN = 0x20030000, LENGTH = 128K /* end: 0x20050000 */
+}
+
+SECTIONS
+{
+ .text : { *(.vectors*) ; *(.text*) } > flash
+ .rodata : { *(.rodata*) ; *(.got*) } > flash
+
+ __flash_data_start = (. + 3) & ~ 3; /* 4-byte aligned end of text is where data is going to be placed (by elf2hex) */
+
+ .bss : { *(.bss*) } > sram_data
+ .tbss : { *(.tbss*) } > sram_data
+ .data : { *(.data*) } > sram_data
+
+ __flash_data_len = . - ORIGIN(sram_data);
+
+ /DISCARD/ : { *(.swift_modhash*) }
+ /* ARM metadata sections */
+ /DISCARD/ : { *(.ARM.attributes*) *(.ARM.exidx) }
+ /* ELF metadata sections */
+ .symtab : { *(.symtab) }
+ .strtab : { *(.strtab) }
+ .shstrtab : { *(.shstrtab) }
+ .debug : { *(.debug*) }
+ .comment : { *(.comment) }
+}
+
+__stack_start = ORIGIN(sram_stack);
+__stack_end = ORIGIN(sram_stack) + LENGTH(sram_stack);
+
+__data_start = ORIGIN(sram_data);
+__data_end = ORIGIN(sram_data) + LENGTH(sram_data);
+
+__heap_start = ORIGIN(sram_heap);
+__heap_end = ORIGIN(sram_heap) + LENGTH(sram_heap);
+```
+
+Create startup code in C that defines the interrupt table and reset handler, in `Sources/Support/Startup.c`:
+
+```c
+#include
+#include
+
+void enable_fpu(void) {
+ *(volatile uint32_t *)0xE000ED88 |= (0xF << 20); // set CP10 and CP11 Full Access
+}
+
+// Reset entrypoint
+__attribute__((naked)) __attribute__((noreturn)) void ResetISR(void) {
+ asm volatile("bl enable_fpu");
+ asm volatile("ldr r0, =__data_start // dst");
+ asm volatile("ldr r1, =__flash_data_start // src");
+ asm volatile("ldr r2, =__flash_data_len // size");
+ asm volatile("bl memcpy"); // Relocate data section to RAM
+ asm volatile("bl main");
+
+ // If main returns, spin.
+ asm volatile("b .");
+}
+
+void IntDefaultHandlerISR() { __builtin_trap(); }
+
+// These are provided by the linker script
+extern void *__stack_start;
+extern void *__stack_end;
+
+// Primary interrupt vector table
+__attribute__((section(".vectors"))) const void *Vectors[120] = {
+ (void *)(((uintptr_t)&__stack_end) - 4), // initial SP
+ ResetISR, // 1 0x04 The reset handler
+ IntDefaultHandlerISR, // 2 0x08 The NMI handler
+ // All other interrupts are not handled
+};
+
+// ELF entrypoint, not actually called at runtime, but it's a GC root
+void *_start_elf(void) { return (void *)&Vectors; }
+```
+
+Finally, let's update `toolset.json` to configure the linker settings for our embedded target. We'll need to add several important options:
+1. The `-T` flag to specify our custom linker script
+2. Library paths to the ARM toolchain we downloaded
+3. Standard C library and runtime library linkage
+4. Disable standard library and stack protector features that aren't appropriate for baremetal code.
+
+```json
+{
+ "schemaVersion": "1.0",
+ "swiftCompiler": {
+ "extraCLIOptions": [
+ "-enable-experimental-feature", "Embedded",
+ "-Xfrontend", "-mergeable-symbols",
+ "-Xfrontend", "-disable-stack-protector",
+ "-Xclang-linker", "-nostdlib",
+ ]
+ },
+ "linker": {
+ "extraCLIOptions": [
+ "-T", "stm32f4.ld",
+ "-e", "_start_elf",
+ "-Lllvm-toolchain/lib/clang-runtimes/arm-none-eabi/armv7m_soft_fpv4_sp_d16_exn_rtti/lib",
+ "-lc",
+ "-lclang_rt.builtins",
+ ]
+ }
+}
+```
+
+At this point, linking will *almost* succeed, the only unresolved reference should be stdout/putchar:
+
+```shell
+$ swift build --configuration release --triple armv7em-none-none-eabi --toolset toolset.json
+ld.lld: error: undefined symbol: stdout
+>>> referenced by putchar.c
+>>> libc_tinystdio_putchar.c.o:(putchar) in archive llvm-toolchain/lib/clang-runtimes/arm-none-eabi/armv7m_soft_fpv4_sp_d16_exn_rtti/lib/libc.a
+```
+
+We're not going to actually try to provide the `stdout` symbol, instead let's provide our own custom `putchar` that will be routed to the UART.
+
+## Step 7: Add UART code
+
+Create a new file at `Sources/STM32BlinkLED/UART.swift`:
+
+```swift
+import Registers
+
+extension STM32BlinkLED {
+ static func initUartOutput() {
+ // A9 is UART1 TX, which is relayed by ST-LINK over USB
+
+ // Clock configuration
+ rcc.ahb1enr.modify { $0.raw.gpioaen = 1 } // Enable AHB clock to port A
+ rcc.apb2enr.modify { $0.raw.usart1en = 1 } // Enable APB clock to usart 1
+
+ // Configure A9 as UART1 TX
+ gpioa.moder.modify { $0.raw.moder9 = 0b10 } // Put Pin A9 into alternate function mode
+ gpioa.otyper.modify { $0.raw.ot9 = 0b0 } // Put Pin A9 into push pull
+ gpioa.ospeedr.modify { $0.raw.ospeedr9 = 0b00 } // Put Pin A9 into low speed
+ gpioa.pupdr.modify { $0.raw.pupdr9 = 0b00 } // Disable pull up/down on Pin A9
+ gpioa.afrh.modify { $0.raw.afrh9 = 0b0111 } // Set alternate function usart1 on Pin A9
+
+ // Configure UART1, set the baud rate to 115200 (we boot at 16 MHz)
+ usart1.brr.modify { $0.raw.storage = 16_000_000 / 115_200 }
+
+ usart1.cr1.modify {
+ $0.raw.ue = 1 // Enable USART 1
+ $0.raw.te = 1 // Enable TX
+ }
+ }
+}
+
+func waitTxBufferEmpty() {
+ // Spin while tx buffer not empty
+ while usart1.isr.read().raw.txe == 0 {}
+}
+
+func tx(value: UInt8) {
+ usart1.tdr.write { $0.raw.tdr_field = UInt32(value) }
+}
+
+@_cdecl("putchar")
+public func putchar(_ value: CInt) -> CInt {
+ waitTxBufferEmpty()
+ tx(value: UInt8(value))
+ waitTxBufferEmpty()
+ return 0
+}
+```
+
+## Step 8: Package up and Boot the Firmware
+
+The firmware should now build successfully, and we are finally ready to boot the firmware! We're going to use the `elf2hex` script to convert the ELF file that `swift build` produced into a format that's suitable for flashing, and then we'll use the `st-flash` tool from the opensource stlink package to actually run the firmware. We'll also use the `minicom` program to receive the text over UART, which will be presented on the host system as a serial port (also known as "COM port").
+
+First let's make sure we have st-link and minicom installed:
+```shell
+$ brew install stlink
+$ st-info --probe
+... TODO
+$ brew install minicom
+$ minicom
+... TODO
+```
+
+Then let's fetch the elf2hex tool:
+
+```shell
+$ curl -L "https://raw.githubusercontent.com/apple/swift-embedded-examples/refs/heads/main/Tools/elf2hex.py" -O
+$ chmod +x elf2hex.py
+```
+
+Next, let's build, package, and flash the firmware:
+
+```shell
+$ swift build --configuration release --triple armv7em-none-none-eabi --toolset toolset.json
+$ ./elf2hex.py .build/release/STM32BlinkLED .build/release/STM32BlinkLED.hex
+```
+
+```shell
+$ ls -al .build/release/STM32BlinkLED.hex
+-rw-r--r-- 1 kuba staff 13K May 18 10:12 .build/release/STM32BlinkLED.hex
+$ st-flash --connect-under-reset --format ihex write .build/release/STM32BlinkLED.hex
+... TODO
+```
+
+Flashing should succeed and the firmware will run, but at this point, you won't see any UART output yet, and that's expected. While we've created the functions to initialize UART and transmit data, we haven't actually called the initialization routine from our main application. The LED won't blink either since we haven't configured the GPIO pins for it. In the next step, we'll update our main application file to call our UART initialization function and configure the LED pin properly.
+
+## Step 9: Configuring pins for UART and LED
+
+Now let's update the main application file to actually use our UART setup and blink an LED. Open the `Sources/STM32BlinkLED/STM32BlinkLED.swift` file and replace its contents with:
+
+```swift
+import Registers
+
+@main
+struct STM32BlinkLED {
+ static func main() {
+ // Initialize UART for output
+ initUartOutput()
+
+ // Initialize LED (Pin I1 on STM32F746G-DISCO)
+ let ledPin: UInt32 = 1
+
+ // Enable clock for GPIO port I
+ rcc.ahb1enr.modify { $0.raw.gpioien = 1 }
+
+ // Configure I1 as output
+ gpioi.moder.modify { $0.raw.moder1 = 0b01 } // Output mode
+ gpioi.otyper.modify { $0.raw.ot1 = 0b0 } // Push-pull mode
+ gpioi.ospeedr.modify { $0.raw.ospeedr1 = 0b00 } // Low speed
+
+ print("Hello from Embedded Swift on STM32F7!")
+
+ // Main loop - toggle LED and print message
+ var count = 0
+ while true {
+ // Toggle the LED
+ let ledState = count % 2 == 0
+ gpioi.bsrr.write {
+ if ledState {
+ $0.raw.bs1 = 1 // Set pin (LED on)
+ } else {
+ $0.raw.br1 = 1 // Reset pin (LED off)
+ }
+ }
+
+ // Print status message every iteration
+ print("LED is now \(ledState ? "ON" : "OFF") - count: \(count)")
+
+ // Delay using a simple counter
+ for _ in 0..<500_000 {
+ // Empty loop to create delay
+ // This is not accurate timing, just a busy-wait
+ }
+
+ count += 1
+ }
+ }
+}
+```
+
+Now we need to create a Makefile to simplify the build and flash process. Create a file named `Makefile` in the project root:
+
+```makefile
+.PHONY: build flash clean
+
+# Serial port for UART output viewing (change to match your system)
+SERIAL_PORT ?= /dev/tty.usbmodem14203
+
+build:
+ swift build --configuration release --triple armv7em-none-none-eabi --toolset toolset.json
+ ./elf2hex.py .build/release/STM32BlinkLED .build/release/STM32BlinkLED.hex
+
+flash: build
+ st-flash --connect-under-reset --format ihex write .build/release/STM32BlinkLED.hex
+
+monitor:
+ minicom -D $(SERIAL_PORT) -b 115200
+
+clean:
+ swift package clean
+ rm -f .build/release/STM32BlinkLED.hex
+```
+
+Now you can build and flash your firmware with a single command:
+
+```shell
+$ make flash
+```
+
+To view the UART output, determine which serial port your STM32F7 board appears as on your system. The ST-Link on the discovery board presents itself as a USB-to-Serial device. Once you've identified the correct port (update the SERIAL_PORT variable in the Makefile if needed), run:
+
+```shell
+$ make monitor
+```
+
+You should now see "Hello from Embedded Swift on STM32F7!" followed by LED status messages in the minicom terminal, and the LED on your board should be blinking.
+
+## Conclusion
+
+Congratulations! You've successfully set up and programmed an STM32 microcontroller in baremetal mode using Embedded Swift. This simple LED blinking project demonstrates the fundamental concepts of embedded programming:
+
+1. Setting up hardware registers
+2. Configuring GPIO pins
+3. Creating delay functions
+4. Implementing a main loop
+
+From here, you can expand the project to include more complex functionality like interfacing with sensors, implementing communication protocols, or adding user input.
+
+## Next Steps
+
+- Add button input to control the LED patterns
+- Implement proper timer-based delays instead of the busy-wait approach
+- Add UART communication to send debug messages to your computer
+- Explore other peripherals like ADC, I2C, or SPI
+
+Happy embedded programming with Swift!
diff --git a/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/macOSGuide.md b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/macOSGuide.md
new file mode 100644
index 0000000..46b7c0b
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/GuidedExamples/macOSGuide.md
@@ -0,0 +1,48 @@
+# Try out Embedded Swift on macOS
+
+Tutorial for building a simple program for your host OS with Embedded Swift
+
+## Overview
+
+While desktop operating systems like macOS and Linux are not the typical targets for Embedded Swift, you **absolutely can** build code for them using the Embedded Swift mode. This is useful for experimentation, trying out Embedded Swift, or to be able to iterate fast on an idea for some code that doesn't really need the physical device to work.
+
+The simplest program in Embedded Swift can just be a regular "Hello, World":
+
+```swift
+// HelloEmbedded.swift
+print("Hello, Embedded Swift 😊")
+```
+
+And building it into an executable can be done by calling the `swiftc` compiler directly, but we'll want to add flags to enable Embedded Swift, and also Whole Module Optimization.
+
+```shell
+$ swiftc HelloEmbedded.swift -o HelloEmbedded -enable-experimental-feature Embedded -wmo
+```
+
+This will produce a regular executable binary, but notice that it's very small in size and that it also *does not actually depend on the Swift runtime in the OS* (all Embedded Swift binaries carry their runtime+stdlib dependencies within):
+
+```shell
+$ ls -al
+-rwxr-xr-x 1 kuba staff 18K May 16 17:19 HelloEmbedded*
+-rw-r--r-- 1 kuba staff 59B May 16 17:16 HelloEmbedded.swift
+$ otool -L HelloEmbedded
+HelloEmbedded:
+ /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1000.0.0)
+```
+
+Let's run it:
+
+```shell
+$ ./HelloEmbedded
+Hello, Embedded Swift 😊
+```
+
+Hooray! Our first *host-side* Embedded Swift program is working!
+
+## Where to go next
+
+- The [Embedded Swift Vision Document](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md) will give you an overview of the approaches and goals of Embedded Swift, and also what exactly is in the Embedded Swift language subset.
+- The [collection of Embedded Swift example projects](https://github.com/apple/swift-embedded-examples) on GitHub shows on which embedded devices can Swift work today, and the examples can also be used as templates for your own projects.
+- The [Embedded Swift User Manual](https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md) describes how to use the Embedded Swift compilation mode and how to interact with the compiler.
+- The [Tools page](https://www.swift.org/tools/#editors) has guides for setting up Swift integration in your editor to enable features like indexing, autocomplete, jump-to-definition, and others.
+- The [Swift forums](https://forums.swift.org/) are the best place to ask questions, give feedback or share your cool projects.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md
new file mode 100644
index 0000000..d5e9766
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/Baremetal.md
@@ -0,0 +1,3 @@
+# Baremetal use of Embedded Swift
+
+🚧 Under construction...
diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithESP.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithESP.md
new file mode 100644
index 0000000..e45c7af
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithESP.md
@@ -0,0 +1,3 @@
+# ESP IDF
+
+🚧 Under construction...
diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md
index 6ade648..3ff9065 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegrateWithPico.md
@@ -1,14 +1,8 @@
-# Integrating with Raspberry Pi Pico
+# Raspberry Pi Pico SDK
-**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.**
+Setting up a project that can seamlessly use C APIs from the Pico SDK.
-**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.**
-
-For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
-
-The following document sketches how to integrate Swift code into some popular embedded platforms' SDKs and build systems.
-
-## Integrating with Raspberry Pi Pico (W) build system:
+> Warning: Embedded Swift is experimental. Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.
Development for [Raspberry Pi Pico and Pico W](https://www.raspberrypi.com/products/raspberry-pi-pico/) normally uses the [Pico SDK](https://github.com/raspberrypi/pico-sdk) and the vendor provides several [sample projects in the pico-examples repository](https://github.com/raspberrypi/pico-examples). The SDK and sample project setup is described in:
diff --git a/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md
new file mode 100644
index 0000000..ac43e34
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/SDKSupport/IntegratingWithPlatforms.md
@@ -0,0 +1,97 @@
+# Integrating with embedded platforms
+
+Understand the common patterns and approaches for integrating Swift with existing embedded systems
+
+## Overview
+
+Most embedded platforms provide SDKs consisting of drivers, libraries, and HAL (Hardware Abstraction Layer) components, typically written in the C language. Embedded Swift's C interoperability makes it possible to seamlessly integrate with these existing SDKs.
+
+This will enable using the entire API surface of an SDK directly from Swift, and is usually the easiest way to get started — because all functionality from the SDK will simply be available in your Swift code. Additionally, you could build Swift wrappers around the C SDK to provide a more idiomatic Swift API. This approach requires a bit more work but can result in a more ergonomic and type-safe interface, leveraging Swift's strong type system and safety features to prevent common errors when interacting with low-level hardware.
+
+Alternatively, for the most constrained environments or when you need complete control over the hardware, you can develop baremetal Swift applications without relying on any SDK. This approach requires implementing your own hardware initialization code and peripheral drivers directly in Swift or in C with Swift wrappers. Baremetal development gives you the maximum flexibility but requires deeper understanding of the target hardware.
+
+## Common Integration Patterns
+
+### Using a Bridging Header
+
+The simplest method for integrating with an embedded platform SDK is using a bridging header that imports the necessary C headers:
+
+```c
+// BridgingHeader.h
+#include "platform_specific_header.h"
+#include "hardware_drivers.h"
+```
+
+When compiling Swift code, include this header:
+
+```bash
+swiftc -enable-experimental-feature Embedded -wmo \
+ -import-bridging-header BridgingHeader.h \
+ -target \
+ YourSwiftCode.swift -c -o output.o
+```
+
+Using a bridging header is discouraged when building an entire set of Swift libraries, but it's a very simple approach when the goal is to simply add a single Swift module into an existing software ecosystem.
+
+### Integrating with Build Systems
+
+Most embedded platforms use one of these build systems:
+
+1. **CMake** - See for details
+2. **Make** - See for more information
+3. **Platform-specific build tools** - These usually allow integration of custom build steps, and you can always manually invoke the Swift compiler (`swiftc`) with the right flags to produce a .o file that can be further used in the build. Follow the article for details.
+
+### Matching platform's ISA and ABI
+
+When integrating Swift code with embedded platforms, it's crucial to properly match the Instruction Set Architecture (ISA) and Application Binary Interface (ABI) of the target system. The Swift compiler needs specific arguments to generate code that's compatible with the target microcontroller's architecture and calling conventions. Mismatches in these settings can lead to hard-to-debug issues or even complete failure to execute.
+
+Different microcontrollers require specific target triples and compiler flags to generate appropriate machine code. Here are common configurations you'll need:
+
+- **ARM Cortex-M0/M0+**: `-target armv6m-none-none-eabi` - For low-power, minimal ARM cores
+- **ARM Cortex-M3/M4**: `-target armv7m-none-none-eabi` - For more capable 32-bit ARM cores
+- **ARM Cortex-M4F** (with FPU): `-target armv7em-none-none-eabi -Xcc -mfloat-abi=hard -Xcc -mfpu=fpv4-sp-d16` - For cores with hardware floating-point
+- **RISC-V**: `-target riscv32-none-none-elf` - For RISC-V based microcontrollers
+
+Additional important compiler flags to consider include:
+- `-Xcc -mfloat-abi=[soft|hard]` - Determines whether floating-point arguments are passed in integer registers (soft) or floating-point registers (hard)
+- `-Xcc -fshort-enums` - Makes enums use the smallest possible integer type, important for ABI compatibility with C code
+- `-Xcc -mcpu=specific-cpu` - Specifies the exact CPU model for more optimized code generation
+- `-Xfrontend -function-sections` - Places each function in its own section, enabling better dead code elimination during linking (this is a recommended setting for ELF targets)
+
+## Platform Examples
+
+### Raspberry Pi Pico
+
+For detailed instructions on integrating with the Raspberry Pi Pico SDK, see .
+
+### ESP32
+
+For ESP microcontrollers using the ESP-IDF framework, see . Note that only chips based on RISC-V architecture (e.g. ESP32-C3, ESP32-C6, ESP32-P4) are supported with Embedded Swift. The Xtensa ISA (used in e.g. ESP8266 or ESP32-S2 and ESP32-S3).
+
+### STM32
+
+STM32 microcontrollers can be programmed with Embedded Swift in two ways:
+
+1. Using the STM32Cube HAL/LL libraries - This requires proper integration with the STM32Cube build system
+2. Bare-metal approach - See for details
+
+### Bare-metal Development
+
+For completely bare-metal development without any SDK, see for guidance on implementing the necessary startup code and hardware initialization.
+
+## Tips & tricks
+
+- Using `print()` in your Swift code creates a dependency on `putchar`, which must be provided by your platform. Make sure your embedded environment has this C standard library function available if you plan to use Swift's printing functionality.
+
+- For debugging, consider implementing a custom print handler by implementing a C function called `putchar` that redirects output to your debug channel (UART, SWO, RTT, etc.). Many embedded platforms already do that by default.
+
+- Use the `-g` compiler flag during development to include debug information, making it easier to trace issues with a debugger like GDB or OpenOCD.
+
+- Use optimization flags to control code size and performance:
+ - Use `-Onone` during development for faster compilation and better debugging
+ - Use `-O` or `-Osize` for release builds to minimize code size and maximize performance
+ - Consider `-Osize` specifically for extremely constrained memory environments
+
+- When you cannot use `-Onone` (e.g. because the resulting binary size exceeds the platform limits), but you still want to maximize debuggability, use the `-assert-config=Debug` flag. This enables assertions, and also extra debug prints on failures.
+
+Remember that Embedded Swift is designed to have minimal impact on the overall system architecture, allowing you to start with small Swift components and gradually expand your Swift codebase as you become more comfortable with the language in embedded contexts.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Basics.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Basics.md
new file mode 100644
index 0000000..2a5f944
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Basics.md
@@ -0,0 +1,106 @@
+# Basics of using Embedded Swift
+
+Basic information for using Embedded Swift in typical embedded projects
+
+## Using Embedded Swift
+
+A typical setup and build and run cycle for an embedded development board involves:
+
+1. Getting an SDK with the C compilers, headers and libraries for the target
+2. Building the C source code, and Swift source code into object files.
+3. Linking all the libraries, C object files, and Swift object files.
+4. Post-processing the linked firmware into a flashable format (UF2, BIN, HEX, or bespoke formats)
+5. Uploading the flashable binary to the board over a USB cable using some vendor-provided JTAG/SWD tool, by copying it to a fake USB Mass Storage volume presented by the board or a custom platform bootloader.
+6. Restarting the board, observing physical effects of the firmware (LEDs light up) or UART output over USB, or presence on network, etc.
+
+Many of these steps are out of scope for this document, because they are unrelated to Swift, and need to be set up and achieved independently of using Embedded Swift. For that, refer to your hardware vendor provided documentation.
+
+This document only focuses on (2) from the list above, and it's important that you first get familiar with the details of firmware development for your board without Swift in the mix. Even if you want to build a completely pure Swift firmware, you are still going to need the vendor provided tooling for linking, post-processing, uploading, etc.
+
+## Building code using Embedded Swift
+
+A basic way to build a set of Swift source files in Embedded Swift mode, is to simply give the compiler the following:
+1. a target triple
+2. the `-enable-experimental-feature Embedded` flag
+3. the set of source files that form the input module:
+
+```shell
+$ swiftc -target -enable-experimental-feature Embedded -wmo \
+ input1.swift input2.swift ... -c -o output.o
+```
+
+On macOS, it's common to have Xcode installed, which comes with a toolchain that does not support Embedded Swift yet. Unless you download, install, and activate a swift.org toolchain, you'll see this error:
+
+```shell
+$ swiftc input1.swift -enable-experimental-feature Embedded -wmo
+:0: error: unable to load standard library for target 'arm64-apple-macosx15.0'
+```
+
+To resolve that, install a nightly Swift toolchain using Swiftly. You can follow the guide at for full instructions on that.
+
+## Building Swift firmware for a concrete embedded target
+
+To build Swift firmware (for now ignoring integration with SDKs, libraries and other pre-existing C code), we can use the `-target` argument to specify the CPU architecture. The target triple also decides whether the output object file will be an ELF file, or a Mach-O. For example:
+
+```bash
+# To build an ARMv7 Mach-O object file:
+$ swiftc -target armv7-apple-none-macho -enable-experimental-feature Embedded -wmo \
+ input1.swift input2.swift ... -c -o output.o
+
+# To build an ARMv7 ELF object file:
+$ swiftc -target armv7-none-none-eabi -enable-experimental-feature Embedded -wmo \
+ input1.swift input2.swift ... -c -o output.o
+```
+
+Additionally, you probably want to specify additional Clang and/or LLVM flags to get the compiler to produce code for the exact ISA and ABI you need for your target.
+
+For example, a Raspberry Pi Pico / Pico W should target the ARMv6-M architecture via the `armv6m-*` target triple, but the `-mfloat-abi=soft` Clang option should also be used, and if you want to match ABI with libraries built with the GNU toolchain, you might also need `-fshort-enums`. To pass those to Swift, use the `-Xcc` prefix:
+
+```bash
+# To build an ELF object file for ARMv6-M with soft float ABI (floating-point arguments passed in integer registers) and "short enums":
+$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo \
+ -Xcc -mfloat-abi=soft -Xcc -fshort-enums \
+ input1.swift input2.swift ... -c -o output.o
+```
+
+This might not be obvious: `-Xcc` flags are typically only used to alter behavior of the Clang importer, but passing flags to Clang this way also works to specify LLVM target options like selecting a specific CPU architecture (`-march`, `-mcpu`, `-mmcu`), FPU unit availability (`-mfpu`), which registers are used to pass floating-point values (`-mfloat-abi`), and others.
+
+## Integrating with existing embedded SDKs and build systems
+
+It's very common to integrate with existing SDKs in embedded development. This typically involves:
+
+1. **Setting up the build environment** with the right compiler flags, include paths, and linker settings to match the SDK's requirements.
+2. **Creating a bridging header** that exposes the C functions and types from the SDK to Swift.
+3. **Configuring the build system** to compile Swift code with the right flags and link it with the SDK's libraries.
+
+Most embedded SDKs provide a build system integration, commonly with CMake, Make, or their own custom build scripts. At the most basic level, it's always possible to manually call the compiler (`swiftc`) as described above from any build system. This will produce a .o file for the entire Swift module, and then a .o file can typically be directly used in the build system.
+
+For details and concrete examples of how to integrate with more common platforms, SDKs and build systems, see .
+
+### Building a macOS Embedded Swift program:
+
+It's also possible to build in Embedded Swift mode for regular non-embedded operating systems, like macOS. This is very useful for testing purposes, or if you just want to observe and experiment with Embedded Swift. A simple source code like this:
+
+```swift
+print("Hello, embedded world!")
+```
+
+...can be compiled using the `-enable-experimental-feature Embedded` flag (the implicit `-target` matches the host OS):
+
+```bash
+$ swiftc hello.swift -enable-experimental-feature Embedded -wmo
+$ ./hello
+Hello, embedded world!
+```
+
+Note that the resulting executable is still a *dynamically-linked executable*, so it's not fully standalone in the embedded sense. Namely is still uses `putchar` from Libsystem. But the singular object file that was used to build this executable was produced by the compiler in the same fashion that a real embedded build would. If we ask the compiler and linker to minimize the size of the outputs and to remove any unused code, we can observe that the binary has no other dependencies other than `putchar` and that the machine code section is very small (172 bytes in the `__text` section):
+
+```bash
+$ swiftc hello.swift -enable-experimental-feature Embedded -wmo -Osize -Xlinker -dead_strip
+$ nm -um ./hello
+ (undefined) external _putchar (from libSystem)
+$ size -m ./hello
+Segment __TEXT: 16384
+ Section __text: 172
+...
+```
diff --git a/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/ConditionalCompilation.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/ConditionalCompilation.md
new file mode 100644
index 0000000..d540718
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/ConditionalCompilation.md
@@ -0,0 +1,27 @@
+# Conditionalizing compilation for Embedded Swift
+
+How to share code between Embedded Swift and full Swift using conditional compilation
+
+It's often useful to have source code be compilable under both regular Swift and Embedded Swift. The following syntax is available for that (but note that as the rest of Embedded Swift, it's experimental, subject to change and not considered source stable):
+
+```swift
+func sayHello() {
+ #if hasFeature(Embedded)
+ print("I'm Embedded Swift")
+ #else
+ print("I'm regular Swift")
+ #endif
+}
+```
+
+Additionally, you can also use an attribute (also experimental, and not source stable) to make entire functions, types and other declarations unavailable in Embedded Swift. This can be particularly useful to explicitly mark your own code (and also entire types and conformances) that relies on features unavailable in Embedded Swift, e.g. the Any type or Codable -- it is explicitly allowed to use those in unavailable contexts:
+
+```swift
+@_unavailableInEmbedded
+func useAny(_: Any) { ... }
+
+@_unavailableInEmbedded
+extension MyStruct: Codable {
+ ...
+}
+```
diff --git a/Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/Existentials.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Existentials.md
similarity index 88%
rename from Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/Existentials.md
rename to Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Existentials.md
index d445d75..716e009 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/Existentials.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Existentials.md
@@ -1,10 +1,6 @@
# Existentials
-**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.**
-
-**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.**
-
-For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
+Restrictions on existentials ("any" types) that apply in Embedded Swift
## Background
@@ -21,7 +17,7 @@ Existentials are restricted in Embedded Swift in multiple ways, for multiple rea
Embedded Swift allows and supports class-bound existentials:
```swift
-procotol ClassBoundProtocol: AnyObject { // ✅, this means any type that wants to conform to ClassBoundProtocol must be a class type
+protocol ClassBoundProtocol: AnyObject { // ✅, this means any type that wants to conform to ClassBoundProtocol must be a class type
func foo()
}
diff --git a/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/ExternalDependencies.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/ExternalDependencies.md
new file mode 100644
index 0000000..cf07505
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/ExternalDependencies.md
@@ -0,0 +1,37 @@
+# External dependencies
+
+What external system dependencies should you expect from Embedded Swift compilations
+
+Embedded Swift minimizes external dependencies (i.e. functions that need to be available at link-time), but they still exist. There are generally two categories of dependencies: (1) functions that the Swift standard library or Embedded Swift runtime need to call, and (2) functions/symbols that are implicitly added by LLVM and the compiler pipeline.
+
+For (1), external dependencies are only used based on actual usage of the program under compilation:
+
+- instantiating a class, or using UnsafeMutablePointer.allocate()
+ - dependency: `int posix_memalign(void **, size_t, size_t);`
+ - dependency: `void free(void *);`
+- using print()
+ - dependency: `int putchar(int);`
+- using Hashable, Set, Dictionary, or random-number generating APIs
+ - dependency: `void arc4random_buf(void *, size_t);`
+
+For (2), external dependencies are also triggered by specific code needing them, but they are somewhat lower-level patterns where it might not be obvious that such patterns should cause external dependencies:
+
+- **basic memory copying and zeroing functions**
+ - usage added for a variety of reasons (e.g. using structs on the stack)
+ - dependency: `void *memset(void *, int, size_t);`
+ - dependency: `void *memcpy(void *, const void *, size_t);`
+- **stack protectors** (aka stack cookies or stack canaries)
+ - dependency: `void *__stack_chk_guard;`
+ - dependency: `void __stack_chk_fail(void);`
+ - stack protectors can be disabled with `-disable-stack-protector` swiftc flag
+- **atomics intrinsics**
+ - 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 intrinsics**
+ - on CPU architectures that don't have direct support for the math operations in the ISA
+ - dependency (on Mach-O): `__divti3`
+ - dependency (on Mach-O): `__modti3`
+ - dependency (with EABI): `__aeabi_ldivmod`
+
+The user and/or the platform (via basic libraries like libc or compiler builtins) is expected to provide these well-known APIs.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Libraries.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Libraries.md
new file mode 100644
index 0000000..22f5d2c
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Libraries.md
@@ -0,0 +1,19 @@
+# Libraries and modules in Embedded Swift
+
+Understand the library setup and linkage model of Embedded Swift
+
+Traditional library build and use model of Swift is that library code is compiled into a .swiftmodule, containing the interfaces, and a compiled library with binary code, either a .a static library or a .dylib/.so dynamic library. A client's build then uses the .swiftmodule at compile-time, and the static/dynamic library at link-time.
+
+The library model in Embedded Swift works slightly differently: All Swift source code of a library is promoted into being inlinable and visible to client builds (this is necessary for generic code, and beneficial for optimizations for non-generic code), and ends up serialized into the .swiftmodule, the interface of the library. Therefore, the compiled code of a library is never needed, and doesn't even need to be produced. For example:
+
+```bash
+# Build the library, only as a .swiftmodule. Notice that we never build the .o or .a for the library.
+$ swiftc -target -enable-experimental-feature Embedded -wmo \
+ a.swift b.swift -module-name MyLibrary -emit-module -emit-module-path ./MyLibrary.swiftmodule
+
+# Build the client, "-I ." add the current directory to the module search path list
+$ swiftc -target -enable-experimental-feature Embedded -wmo \
+ client.swift -I . -c -o client.o
+```
+
+The Embedded Swift standard library is distributed in the toolchain the same way: It's strictly a .swiftmodule without any compiled code present anywhere. All the compiling into machine code is performed as part of the client's build. This has the major benefit that the client's build can provide additional ABI and ISA defining flags, such as the above-mentioned `-mfloat-abi`, `-fshort-enums`, `-mcpu`, `-march` flags, and these flags in the client's build will apply to all the library code (including standard library code) as well.
diff --git a/Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/NonFinalGenericMethods.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/NonFinalGenericMethods.md
similarity index 87%
rename from Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/NonFinalGenericMethods.md
rename to Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/NonFinalGenericMethods.md
index d689c16..c1fe357 100644
--- a/Sources/EmbeddedSwift/Documentation.docc/LanguageDetails/NonFinalGenericMethods.md
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/NonFinalGenericMethods.md
@@ -1,10 +1,6 @@
# Non-final generic methods
-**⚠️ Embedded Swift is experimental. This document might be out of date with latest development.**
-
-**‼️ Use the latest downloadable 'Trunk Development' snapshot from swift.org to use Embedded Swift. Public releases of Swift do not yet support Embedded Swift.**
-
-For an introduction and motivation into Embedded Swift, please see "[A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md)", a Swift Evolution document highlighting the main goals and approaches.
+Restrictions on unbound generic methods that apply in Embedded Swift
## Background
@@ -127,4 +123,3 @@ func usingProtocolAsExistential(p: any MyProtocol) {
p.write(t: 42) // ✅
}
```
-
diff --git a/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Strings.md b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Strings.md
new file mode 100644
index 0000000..f1e23bd
--- /dev/null
+++ b/Sources/EmbeddedSwift/Documentation.docc/UsingEmbeddedSwift/Strings.md
@@ -0,0 +1,53 @@
+# Strings
+
+How to enable full Unicode-compliant string support in Embedded Swift
+
+Both StaticString and String types are available in Embedded Swift. As is the case in desktop Swift, certain operations on strings require Unicode data tables for strict Unicode compliance. In Embedded Swift these data tables are provided as a separate static library (libUnicodeDataTables.a) that users need to link in manually – if they need to use these string operations. If the library is required, linking will fail due to missing on one or more of the following symbols:
+
+```
+_swift_stdlib_getAge
+_swift_stdlib_getBinaryProperties
+_swift_stdlib_getCaseMapping
+_swift_stdlib_getComposition
+_swift_stdlib_getDecompositionEntry
+_swift_stdlib_getGeneralCategory
+_swift_stdlib_getGraphemeBreakProperty
+_swift_stdlib_getMapping
+_swift_stdlib_getMphIdx
+_swift_stdlib_getNameAlias
+_swift_stdlib_getNormData
+_swift_stdlib_getNumericType
+_swift_stdlib_getNumericValue
+_swift_stdlib_getScalarBitArrayIdx
+_swift_stdlib_getScalarName
+_swift_stdlib_getScript
+_swift_stdlib_getScriptExtensions
+_swift_stdlib_getSpecialMapping
+_swift_stdlib_getWordBreakProperty
+_swift_stdlib_isLinkingConsonant
+_swift_stdlib_nfd_decompositions
+```
+
+To resolve this, link in the `libswiftUnicodeDataTables.a` that's in Swift toolchain's resource directory (`lib/swift/`) under the target triple that you're using:
+
+```bash
+$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo -c -o output.o
+$ ld ... -o binary output.o $(dirname `which swiftc`)/../lib/swift/embedded/armv6m-none-none-eabi/libswiftUnicodeDataTables.a
+```
+
+**Unicode data tables are required for (list not exhaustive):**
+
+- Comparing String objects for equality
+- Sorting Strings
+- Using String's hash values, and in particular using String as dictionary keys
+- Using String's `.count` property
+- Using Unicode-aware string processing APIs (`.split()`, iterating characters, indexing)
+- Using Unicode-aware conversion String APIs (`.uppercased()`, `.lowercased()`, etc.)
+
+**For contrast, unicode data tables are *not required for* (list not exhaustive):**
+
+- Using StaticString
+- Creating, concatenating, string interpolating, and printing String objects
+- Using `.utf8`, `.utf16`, and `.unicodeScalars` views of strings, including their .count property, using them as dictionary keys
+
+Manually linking `libswiftUnicodeDataTables.a` is required for several reasons, including acknowledging that the data tables are desirable: Since they have a non-negligible size, it's useful to be aware that you are using them.