Skip to content

Commit bc147ae

Browse files
authored
Merge pull request #73944 from kubamracek/embedded-docs5
[embedded] Add a section on Strings into the User Manual
2 parents 1407980 + 772e066 commit bc147ae

File tree

2 files changed

+70
-12
lines changed

2 files changed

+70
-12
lines changed

docs/EmbeddedSwift/EmbeddedSwiftStatus.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ This status table describes which of the following standard library features can
3434
| Codable, Encodable, Decodable | No |
3535
| Collection + related protocols | Yes |
3636
| Collection algorithms (sort, reverse) | Yes |
37-
| CustomStringConvertible, CustomDebugStringConvertible | No |
37+
| CustomStringConvertible, CustomDebugStringConvertible | Yes, except those that require reflection (e.g. Array's .description) |
3838
| Dictionary (dynamic heap-allocated container) | Yes |
3939
| FixedWidthInteger + related protocols | Yes |
4040
| Hashable, Equatable, Comparable protocols | Yes |
@@ -45,15 +45,15 @@ This status table describes which of the following standard library features can
4545
| Mirror (runtime reflection) | No, intentionally unsupported long-term |
4646
| Objective-C bridging | No, intentionally unsupported long-term |
4747
| Optional | Yes |
48-
| print / debugPrint | Partial (only StaticStrings and integers) |
48+
| print / debugPrint | Partial (only String, string interpolation, StaticStrings, integers, pointers and booleans) |
4949
| Range, ClosedRange, Stride | Yes |
5050
| Result | Yes |
5151
| Set (dynamic heap-allocated container) | Yes |
5252
| SIMD types | Yes |
5353
| StaticString | Yes |
54-
| String (dynamic) | No (work in progress) |
55-
| String Interpolations | No (work in progress) |
56-
| Unicode | No |
54+
| String (dynamic) | Yes |
55+
| String Interpolations | Yes |
56+
| Unicode | Yes |
5757
| Unsafe\[Mutable\]\[Raw\]\[Buffer\]Pointer | Yes |
5858
| VarArgs | No |
5959

docs/EmbeddedSwift/UserManual.md

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ The following document explains how to use Embedded Swift's support in the Swift
2020
A typical setup and build + run cycle for an embedded development board involves:
2121

2222
- (1) Getting an SDK with the C compilers, headers and libraries for the target
23-
- (2) Building the C source code, and Swift source code
23+
- (2) Building the C source code, and Swift source code into object files.
2424
- (3) Linking all the libraries, C object files, and Swift object files.
2525
- (4) Post-processing the linked firmware into a flashable format (UD2, BIN, or bespoke formats)
2626
- (5) Uploading the flashable binary to the board over a USB cable using some vendor-provided JTAG/SWD tool or by copying it to a fake USB Mass Storage volume presented by the board.
2727
- (6) Restarting the board, observing physical effects of the firmware (LEDs light up) or UART output over USB, or presence on network, etc.
2828

29-
Most of these steps are out of scope for this document, instead refer to the vendor provided documentation and get familiar with the details of firmware development for your board without Swift in the mix first. Even if you want to build a completely pure Swift firmware, you are still very likely going to need the vendor provided tooling for linking, post-processing, uploading, etc.
29+
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.
3030

3131
## Building code using Embedded Swift
3232

@@ -49,7 +49,7 @@ $ swiftc -target armv7-apple-none-macho -enable-experimental-feature Embedded -w
4949
input1.swift input2.swift ... -c -o output.o
5050

5151
# To build an ARMv7 ELF object file:
52-
$ swiftc -target armv7-unknown-none-eabi -enable-experimental-feature Embedded -wmo \
52+
$ swiftc -target armv7-none-none-eabi -enable-experimental-feature Embedded -wmo \
5353
input1.swift input2.swift ... -c -o output.o
5454
```
5555

@@ -59,7 +59,7 @@ For example, a Raspberry Pi Pico / Pico W should target the ARMv6-M architecture
5959

6060
```bash
6161
# To build an ELF object file for ARMv6-M with soft float ABI (floating-point arguments passed in integer registers) and "short enums":
62-
$ swiftc -target armv6m-unknown-none-eabi -enable-experimental-feature Embedded -wmo \
62+
$ swiftc -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo \
6363
-Xcc -mfloat-abi=soft -Xcc -fshort-enums \
6464
input1.swift input2.swift ... -c -o output.o
6565
```
@@ -98,6 +98,58 @@ Segment __TEXT: 16384
9898
...
9999
```
100100

101+
## Strings
102+
103+
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:
104+
105+
```
106+
_swift_stdlib_getAge
107+
_swift_stdlib_getBinaryProperties
108+
_swift_stdlib_getCaseMapping
109+
_swift_stdlib_getComposition
110+
_swift_stdlib_getDecompositionEntry
111+
_swift_stdlib_getGeneralCategory
112+
_swift_stdlib_getGraphemeBreakProperty
113+
_swift_stdlib_getMapping
114+
_swift_stdlib_getMphIdx
115+
_swift_stdlib_getNameAlias
116+
_swift_stdlib_getNormData
117+
_swift_stdlib_getNumericType
118+
_swift_stdlib_getNumericValue
119+
_swift_stdlib_getScalarBitArrayIdx
120+
_swift_stdlib_getScalarName
121+
_swift_stdlib_getScript
122+
_swift_stdlib_getScriptExtensions
123+
_swift_stdlib_getSpecialMapping
124+
_swift_stdlib_getWordBreakProperty
125+
_swift_stdlib_isLinkingConsonant
126+
_swift_stdlib_nfd_decompositions
127+
```
128+
129+
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:
130+
131+
```bash
132+
$ swiftc <inputs> -target armv6m-none-none-eabi -enable-experimental-feature Embedded -wmo -c -o output.o
133+
$ ld ... -o binary output.o $(dirname `which swiftc`)/../lib/swift/embedded/armv6m-none-none-eabi/libswiftUnicodeDataTables.a
134+
```
135+
136+
**Unicode data tables are required for (list not exhaustive):**
137+
138+
- Comparing String objects for equality
139+
- Sorting Strings
140+
- Using String's hash values, and in particular using String as dictionary keys
141+
- Using String's .count property
142+
- Using Unicode-aware string processing APIs (.split(), iterating characters, indexing)
143+
- Using Unicode-aware conversion String APIs (.uppercased(), .lowercased(), etc.)
144+
145+
**For contrast, unicode data tables are *not required for* (list not exhaustive):**
146+
147+
- Using StaticString
148+
- Creating, concatenating, string interpolating, and printing String objects
149+
- Using .utf8, .utf16, and .unicodeScalars views of strings, including their .count property, using them as dictionary keys
150+
151+
Manually linking libUnicodeDataTables.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.
152+
101153
## Conditionalizing compilation for Embedded Swift
102154

103155
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):
@@ -133,8 +185,7 @@ Features that are not available:
133185
- **Not available**: Runtime reflection (`Mirror` APIs).
134186
- **Not available**: Values of protocol types ("existentials"), e.g. `let a: Hashable = ...`, are not allowed. `Any` and `AnyObject` are also not allowed.
135187
- **Not available**: Metatypes, e.g. `let t = SomeClass.Type` or `type(of: value)` are not allowed.
136-
- **Not available yet (under development)**: The print() function for types other than StaticString and integers.
137-
- **Not available yet (under development)**: String. (StaticString **is** available).
188+
- **Not available**: Printing and stringifation of arbitrary types (archieved via reflection in desktop Swift).
138189
- **Not available yet (under development)**: Swift Concurrency.
139190

140191
For a more complete list of supported features in Embedded Swift, see [Embedded Swift -- Status](EmbeddedSwiftStatus.md).
@@ -159,7 +210,14 @@ The Embedded Swift standard library is distributed in the toolchain the same way
159210

160211
## Allocating and non-allocating Embedded Swift mode
161212

162-
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). Outside of creating class instances and explicitly calling allocation APIs (e.g. `UnsafeMutablePointer.allocate()`), Embedded Swift does not perform allocations or cause heap usage.
213+
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:
214+
215+
- creating class instances,
216+
- escaping a closure that captures local variables,
217+
- creating an indirect enum case with a payload referencing the enum itself
218+
- explicitly calling allocation APIs (e.g. `UnsafeMutablePointer.allocate()`).
219+
220+
Outside of those cases, Embedded Swift does not perform allocations or cause heap usage.
163221

164222
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.
165223

0 commit comments

Comments
 (0)