Building swift-mmio for STM32C011 with -no-allocations results in compilation error

Small question here. One thing I've been trying to do is ensure that I avoid using the heap on my tiny STM32C011 which only has 6KB of SRAM. For this, I've enabled the -no-allocations flag in my Swift SDK for the stm32c0xx. However, when I try to compile swift-mmio with -no-allocations passed, I get the following error:

/opt/swift-6.0.1/usr/bin/swift-frontend -frontend -c ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/BitField.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/BitFieldProjectable.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/MMIOInterposer.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/MMIOMacros.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/Register.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/RegisterArray.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/RegisterProtocol.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/RegisterStorage.swift ~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIO/RegisterValue.swift -supplementary-output-file-map /tmp/TemporaryDirectory.FHSkzt/supplementaryOutputs-1 -target armv6m-none-none-eabi -disable-objc-interop -sdk ~/swift-stm32c011-examples/swift-sdks/stm32c0xx.artifactbundle -I ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/Modules -color-diagnostics -g -debug-info-format=dwarf -dwarf-version=4 -module-cache-path ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/ModuleCache -suppress-warnings -swift-version 5 -Osize -D SWIFT_PACKAGE -disable-stack-protector -function-sections -load-plugin-executable ~/swift-stm32c011-examples/blink-mmio/.build/x86_64-unknown-linux-gnu/release/MMIOMacros-tool#MMIOMacros -no-allocations -enable-experimental-feature Embedded -enable-experimental-feature Embedded -empty-abi-descriptor -resource-dir /opt/swift-6.0.1/usr/lib/swift -file-compilation-dir ~/swift-stm32c011-examples/blink-mmio -Xcc -fmodule-map-file=~/swift-stm32c011-examples/blink-mmio/.build/checkouts/swift-mmio/Sources/MMIOVolatile/module.modulemap -Xcc --sysroot -Xcc ~/swift-stm32c011-examples/swift-sdks/stm32c0xx.artifactbundle -Xcc -mcpu=cortex-m0plus -Xcc -mthumb -Xcc -mfloat-abi=soft -Xcc -ffreestanding -Xcc -ffunction-sections -Xcc -fshort-enums -Xcc -g -module-name MMIO -package-name swift_mmio -plugin-path /opt/swift-6.0.1/usr/lib/swift/host/plugins -plugin-path /opt/swift-6.0.1/usr/local/lib/swift/host/plugins -enable-default-cmo -parse-as-library -num-threads 12 -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/BitField.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/BitFieldProjectable.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/MMIOInterposer.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/MMIOMacros.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/Register.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/RegisterArray.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/RegisterProtocol.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/RegisterStorage.swift.o -o ~/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/release/MMIO.build/RegisterValue.swift.o
<unknown>:0: error: cannot use allocating type '__SwiftNativeNSArrayWithContiguousStorage' in -no-allocations mode
in function __SwiftNativeNSArrayWithContiguousStorage.__allocating_init()
make: *** [Makefile:22: build] Error 1

Any ideas as to why this happens, and any way this can be fixed?

My test project code is up on GitHub here: swift-stm32c011-examples/blink-mmio at feature/no-allocations · xtremekforever/swift-stm32c011-examples · GitHub

I highly suggest not using the -no-allocations flag currently, it is aspirational and I don't expect it to work correctly.

I'm not sure why mmio is hitting this error, but I can guarantee that it does not use any dynamic allocations, and definitely does not use arrays. Instead to represent "arrays" of registers it uses RegisterArray<Value> which is a simple wrapper type which provides a subscript and does pointer math.

1 Like

Maybe @kubamracek has ideas about that error, but I suspect he will also say,
"don't use that flag yet".

That's right, but I'm also interested in identifying concrete problems with it. The error shown above is (in a very bad way) saying that there is a (heap using) Array being used. We should improve the error message, for sure, but if we're saying that it's a false error, then that's a separate problem. Can I get a Github issue raised for it?

1 Like

Okay, good to know. I figured it wasn't quite right because I would expect the library would not do anything allocating.

Sure, shall I open this ticket on the swiftlang/swift repo (is this the appropriate place)?

I'm using the Swift for Embedded preview for my real life project, so I'm interested in helping in any way I can.

1 Like

Yes.

Okay, working on that ticket now!!!

By the way @rauhul what is this error about when trying to build swift-mmio on the "main" branch?

Basics/Triple+Basics.swift:149: Fatal error: Cannot create dynamic libraries for os "noneOS".

I've been using the "swift-embedded-examples" branch, which works, but I am genuinely curious what causes this and what the fix is, since the swift-embedded-examples branch is still at Swift 5.9 across the board.

Ha serves me right for speaking too quickly, there is a place where an Array is used, but the hope was that it gets const folded away.

This currently happens if you use @ReadWrite(bits: <multiple ranges>) from here: swift-mmio/Sources/MMIO/BitField.swift at bb793358357b132b97384553429fe4f6adeb3d01 · apple/swift-mmio · GitHub

Kuba had a good suggestion of moving the check into the macro, which seems reasonable. I dont actually recall why I put this check in the runtime and hopped for constant folding.

:sigh: this issue is: Cannot cross compile when package contains dylib product · Issue #7893 · swiftlang/swift-package-manager · GitHub

cc @dschaefer2

we "just" need to decide on a file extension is in this case. I personally think we should derive it from the object file format if os == none, Doug has also suggested .so.

.so for the win :smile: . Most embedded platforms I've seen don't have dynamic loaders but the ones that do use .so (though QNX also used .dll but I think that was in regret).

Oops. Well, I filed the ticket here anyways: Bug compiling embedded Swift project with `-no-allocations` flag enabled with swift-mmio · Issue #76857 · swiftlang/swift · GitHub

Okay, this is helpful. Thanks for the info. I hope it can get solved soon! For now I am okay using what works but eagerly await anything new :smile:

Oops. Well, I filed the ticket here anyways: Bug compiling embedded Swift project with -no-allocations flag enabled with swift-mmio · Issue #76857 · swiftlang/swift · GitHub

Let's use that bugreport at least for the "the error from the compiler is not pointing to the location of the problem" part.

Sure, that's fine. I can even edit the description to clarify if needed.

I just rebased swift-embedded-examples on top of main!

Well I put up a patch with an alternate option here that we can discuss: Add a fallback extension none os dylibs by rauhul · Pull Request #8022 · swiftlang/swift-package-manager · GitHub

1 Like

Nice, it works! I upgraded my sample project to use it. I do like being able to use swift-syntax for 6.0 instead of the 509 version...

What's unclear to me is how this is not running into the none OS issue? Because on main that is still the case?