16 bit support in swift compiler


I'm using swiftc to output LLVM IR then compiling this to AVR machine code using a custom built LLC.exe. This is all working well in most cases but there's an issue with the pointers.

Can anyone give me pointers in the swift code how I can change the datalayout that's output to specify 16 bit pointers please?

To be specific, I'm trying to get the LLVM datalayout to support 16 bit pointers.

Here's an example program and how it compiles to SIL and then to LLVM IR.

import AVR
typealias IntegerLiteralType = UInt8
pinMode(pin: 4, mode: INPUT)
setupTimerIntervalInterruptCallback(tenthsOfAMillisecond: 1000) {
while(true) {

sil_stage raw

import Builtin
import Swift
import SwiftShims

sil_global [let] @INPUT : $Bool

sil_scope 1 {  parent @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 }
sil_scope 2 { loc "main.swift":22:1 parent 1 }

// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  %2 = global_addr @INPUT : $*Bool, scope 1       // user: %8
  // function_ref pinMode(pin : UInt8, mode : Bool) -> ()
  %3 = function_ref @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_ : $@convention(thin) (UInt8, Bool) -> (), loc "main.swift":5:1, scope 1 // user: %9
  // function_ref UInt8.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt8
  %4 = function_ref @_TFVs5UInt8CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt8.Type) -> UInt8, loc "main.swift":5:14, scope 1 // user: %7
  %5 = metatype $@thin UInt8.Type, loc "main.swift":5:14, scope 1 // user: %7
  %6 = integer_literal $Builtin.Int2048, 4, loc "main.swift":5:14, scope 1 // user: %7
  %7 = apply %4(%6, %5) : $@convention(method) (Builtin.Int2048, @thin UInt8.Type) -> UInt8, loc "main.swift":5:14, scope 1 // user: %9
  %8 = load_borrow %2 : $*Bool, loc "main.swift":5:23, scope 1 // user: %9
  %9 = apply %3(%7, %8) : $@convention(thin) (UInt8, Bool) -> (), loc "main.swift":5:28, scope 1
  // function_ref setupTimerIntervalInterruptCallback(tenthsOfAMillisecond : UInt16, callback : @convention(c) () -> ()) -> ()
  %10 = function_ref @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_ : $@convention(thin) (UInt16, @convention(c) () -> ()) -> (), loc "main.swift":7:1, scope 1 // user: %16
  // function_ref UInt16.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt16
  %11 = function_ref @_TFVs6UInt16CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt16.Type) -> UInt16, loc "main.swift":7:59, scope 1 // user: %14
  %12 = metatype $@thin UInt16.Type, loc "main.swift":7:59, scope 1 // user: %14
  %13 = integer_literal $Builtin.Int2048, 1000, loc "main.swift":7:59, scope 1 // user: %14
  %14 = apply %11(%13, %12) : $@convention(method) (Builtin.Int2048, @thin UInt16.Type) -> UInt16, loc "main.swift":7:59, scope 1 // user: %16
  // function_ref @objc (closure #1)
  %15 = function_ref @_TToF4mainU_FT_T_ : $@convention(c) () -> (), loc "main.swift":7:65, scope 1 // user: %16
  %16 = apply %10(%14, %15) : $@convention(thin) (UInt16, @convention(c) () -> ()) -> (), loc "main.swift":19:1, scope 1
  br bb1, loc "main.swift":21:1, scope 2          // id: %17

bb1:                                              // Preds: bb2 bb0
  // function_ref Bool._getBuiltinLogicValue() -> Builtin.Int1
  %18 = function_ref @_TFSb21_getBuiltinLogicValuefT_Bi1_ : $@convention(method) (Bool) -> Builtin.Int1, loc "main.swift":21:7, scope 2 // user: %23
  // function_ref Bool.init(_builtinBooleanLiteral : Builtin.Int1) -> Bool
  %19 = function_ref @_TFSbCfT22_builtinBooleanLiteralBi1__Sb : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool, loc "main.swift":21:7, scope 2 // user: %22
  %20 = metatype $@thin Bool.Type, loc "main.swift":21:7, scope 2 // user: %22
  %21 = integer_literal $Builtin.Int1, -1, loc "main.swift":21:7, scope 2 // user: %22
  %22 = apply %19(%21, %20) : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool, loc "main.swift":21:7, scope 2 // user: %23
  %23 = apply %18(%22) : $@convention(method) (Bool) -> Builtin.Int1, loc "main.swift":21:11, scope 2 // user: %24
  cond_br %23, bb2, bb3, loc "main.swift":21:11, scope 2 // id: %24

bb2:                                              // Preds: bb1
  br bb1, loc "main.swift":22:1, scope 2          // id: %25

bb3:                                              // Preds: bb1
  %26 = integer_literal $Builtin.Int32, 0, scope 2 // user: %27
  %27 = struct $Int32 (%26 : $Builtin.Int32), scope 2 // user: %28
  return %27 : $Int32, scope 2                    // id: %28
} // end sil function 'main'

// pinMode(pin : UInt8, mode : Bool) -> ()
sil @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_ : $@convention(thin) (UInt8, Bool) -> ()

// UInt8.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt8
sil [transparent] [fragile] @_TFVs5UInt8CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt8.Type) -> UInt8

// setupTimerIntervalInterruptCallback(tenthsOfAMillisecond : UInt16, callback : @convention(c) () -> ()) -> ()
sil @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_ : $@convention(thin) (UInt16, @convention(c) () -> ()) -> ()

// UInt16.init(_builtinIntegerLiteral : Builtin.Int2048) -> UInt16
sil [transparent] [fragile] @_TFVs6UInt16CfT22_builtinIntegerLiteralBi2048__S_ : $@convention(method) (Builtin.Int2048, @thin UInt16.Type) -> UInt16

sil_scope 3 { loc "main.swift":7:65 parent @_TF4mainU_FT_T_ : $@convention(thin) () -> () }
sil_scope 4 { loc "main.swift":19:1 parent 3 }

// (closure #1)
sil shared @_TF4mainU_FT_T_ : $@convention(thin) () -> () {
  %0 = tuple (), loc "main.swift":19:1, scope 4   // user: %1
  return %0 : $(), loc "main.swift":19:1, scope 4 // id: %1
} // end sil function '_TF4mainU_FT_T_'

sil_scope 5 { loc "main.swift":7:65 parent @_TToF4mainU_FT_T_ : $@convention(c) () -> () }

// @objc (closure #1)
sil shared [thunk] @_TToF4mainU_FT_T_ : $@convention(c) () -> () {
  // function_ref (closure #1)
  %0 = function_ref @_TF4mainU_FT_T_ : $@convention(thin) () -> (), scope 5 // user: %1
  %1 = apply %0() : $@convention(thin) () -> (), scope 5 // user: %2
  return %1 : $(), scope 5                        // id: %2
} // end sil function '_TToF4mainU_FT_T_'

// Bool._getBuiltinLogicValue() -> Builtin.Int1
sil [transparent] [fragile] @_TFSb21_getBuiltinLogicValuefT_Bi1_ : $@convention(method) (Bool) -> Builtin.Int1

// Bool.init(_builtinBooleanLiteral : Builtin.Int1) -> Bool
sil [transparent] [fragile] @_TFSbCfT22_builtinBooleanLiteralBi1__Sb : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool

And the final, resulting LLVM IR:

; ModuleID = 'main.ll'
source_filename = "main.ll"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9"

@INPUT = external local_unnamed_addr constant i8, align 1
@__swift_reflection_version = linkonce_odr hidden constant i16 1
@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata"

; Function Attrs: noreturn
define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
  %2 = load i1, i1* bitcast (i8* @INPUT to i1*), align 1
  tail call void @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_(i8 4, i1 %2)
  tail call void @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_(i16 1000, i8* bitcast (void ()* @_TToF4mainU_FT_T_ to i8*))
  br label %3

; <label>:3:                                      ; preds = %3, %entry
  br label %3

declare void @_TF3AVR7pinModeFT3pinVs5UInt84modeSb_T_(i8, i1) local_unnamed_addr #1

declare void @_TF3AVR35setupTimerIntervalInterruptCallbackFT20tenthsOfAMillisecondVs6UInt168callbackcT_T__T_(i16, i8*) local_unnamed_addr #1

; Function Attrs: norecurse nounwind
define linkonce_odr hidden void @_TToF4mainU_FT_T_() #2 {
  ret void

attributes #0 = { noreturn "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+fxsr,+mmx,+x87,+sse,+sse2,+sse3" }
attributes #1 = { "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+fxsr,+mmx,+x87,+sse,+sse2,+sse3" }
attributes #2 = { norecurse nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+fxsr,+mmx,+x87,+sse,+sse2,+sse3" }

!0 = !{i32 1, !"Objective-C Version", i32 2}
!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!2 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
!3 = !{i32 4, !"Objective-C Garbage Collection", i32 1024}
!4 = !{i32 1, !"Objective-C Class Properties", i32 64}
!5 = !{i32 6, !"Linker Options", !6}
!6 = !{!7, !8}
!7 = !{!"-lswiftCore"}
!8 = !{!"-lobjc"}
!9 = !{i32 1, !"PIC Level", i32 2}
!10 = !{i32 1, !"Swift Version", i32 4}

The problem is ultimately the LLVM back end for the AVR processor cannot handle 64 bit pointers. The Apple developers who studied the problem at WWDC said I'll need to recompile the swift compiler source with a patch to make it 16 bit.

Any help would be greatly appreciated!



To start with, you'll want to pass an appropriate -target triple to the Swift compiler when targeting AVR. As you can see in the target triple = line of the LLVM output, your IR is being generated to target x86-64 macOS. You will likely have to edit many target-specific parts of Swift throughout the compiler and standard library to add support for a 16-bit platform, but by setting the correct target triple, those places will hopefully begin to reveal themselves through errors or assertion failures in a debug compiler.



If I attempt to pass any other target to the built compiler it just errors:


<unknown>:0: error: **unknown target 'avr-atmel-none-none'

OK, slight progress... after a bit of grepping through source for that error, realised it needs an OS, otherwise will always bork. Changed to -target avr-atmel-linux-gnueabihf.

Now it gives the error:

<unknown>:0: error: unsupported target architecture: 'avr'

From another source code search, it looks like, at the very least, I'll need to add AVR as a supported architecture inside...


std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {

(It is supported by LLVM.)

Unfortunately, after that it's a bit of a dead end. It's unclear how the architecture will affect the datalayout or where the datalayout is set. Annoyingly, searching through the code doesn't give much clue.

Anyone any ideas?

Swift largely reuses Clang's LLVM target setup, so by setting the target triple you should get reasonable defaults for data layout and other target options. I'd start with those before tweaking.

Cool. That sounds like sense. Bear with me, thanks for all your advice. I guess what i'm trying is a bit ambitious.

So, I made a small swift source change to accept avr as an architecture and recompiled then tested it again with my simple swift program:

import AVR
typealias IntegerLiteralType = UInt8
pinMode(pin: 4, mode: INPUT)

while(true) {

When compiled with the new swift compiler:

"/Users/carlpeto/avr/swift/build/Ninja+cmark-ReleaseAssert+llvm-DebugAssert+swift-DebugAssert+stdlib-ReleaseAssert/swift-macosx-x86_64/bin/swiftc" -Xfrontend -emit-ir -S -no-link-objc-runtime -import-objc-header buildr.h -I AVR -I CAVR -target avr-atmel-linux-gnueabihf -O -module-name main main.swift -o main.ll

...it comes out with a different error:
<unknown>:0: error: unknown target triple 'avr-atmel-linux-gnueabihf', please use -triple or -arch

<unknown>:0: error: clang importer creation failed

make: *** [main.ll] Error 1

I'm assuming this is because I need to look through the clang source code and find somewhere to patch to allow the avr architecture?

Or is this a different cause?

It's a bit surprising if it's clang because avr is an architecture in llvm but when I've built for avr in other llvm source trees, I've had to enable experimental targets.


cc @jrose. You may need to modify the Clang target setup to pass the right target info down to Clang then. In the meantime, you can also use -Xcc to pass command-line arguments through to the Clang driver, e.g. -Xcc -triple -Xcc <triple-clang-understands> to experiment with what settings Clang needs to support AVR.

"Enable experimental targets" sounds like the problem here too. Swift doesn't explicitly have an option for that, but you'll need to get that option to the CMake invocation for LLVM too. You can use build-script's --extra-cmake-options to accomplish this (it shouldn't matter if the extra options are passed to Swift's CMake as well):

  --extra-cmake-options EXTRA_CMAKE_OPTIONS
                        Pass through extra options to CMake in the form of
                        comma separated options
                        "-DCMAKE_VAR1=YES,-DCMAKE_VAR2=/tmp". Can be called
                        multiple times to add multiple such options.

OK, good options... I'll try that build. Takes ages to run each build. Slowing the process down.

Thanks for the advice @jrose and @Joe_Groff

Looks like the AVR target code of the LLVM source tagged for swift 3.1.1 is a bit too old (Dylan only started to maintain it a few years ago and upstreamed a lot of bugfixes in the last year)...

+ /usr/local/bin/cmake --build /Users/carlpeto/avr/swift/build/Ninja+cmark-ReleaseAssert+llvm-DebugAssert+swift-DebugAssert+stdlib-ReleaseAssert/llvm-macosx-x86_64 -- -j8 all
[1096/2276] Building CXX object lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetObjectFile.cpp.o
FAILED: lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetObjectFile.cpp.o 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++   -DGTEST_HAS_RTTI=0 -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Ilib/Target/AVR -I/Users/carlpeto/avr/swift/llvm/lib/Target/AVR -Iinclude -I/Users/carlpeto/avr/swift/llvm/include -g -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Werror=date-time -std=c++11 -fcolor-diagnostics -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -mmacosx-version-min=10.9    -fno-exceptions -fno-rtti -MD -MT lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetObjectFile.cpp.o -MF lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetObjectFile.cpp.o.d -o lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetObjectFile.cpp.o -c /Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
In file included from /Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp:10:
/Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetObjectFile.h:26:68: error: non-virtual member function marked 'override' hides virtual member function
                                    const TargetMachine &TM) const override;
/Users/carlpeto/avr/swift/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h:59:14: note: hidden overloaded virtual function 'llvm::TargetLoweringObjectFileELF::SelectSectionForGlobal' declared here: different number of parameters (3 vs 4)
  MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
/Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp:38:55: error: too many arguments to function call, expected 3, have 4
  return Base::SelectSectionForGlobal(GV, Kind, Mang, TM);
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~                 ^~
/Users/carlpeto/avr/swift/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h:59:3: note: 'SelectSectionForGlobal' declared here
  MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
2 errors generated.
[1098/2276] Building CXX object lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetMachine.cpp.o
FAILED: lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetMachine.cpp.o 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++   -DGTEST_HAS_RTTI=0 -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Ilib/Target/AVR -I/Users/carlpeto/avr/swift/llvm/lib/Target/AVR -Iinclude -I/Users/carlpeto/avr/swift/llvm/include -g -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Werror=date-time -std=c++11 -fcolor-diagnostics -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -mmacosx-version-min=10.9    -fno-exceptions -fno-rtti -MD -MT lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetMachine.cpp.o -MF lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetMachine.cpp.o.d -o lib/Target/AVR/CMakeFiles/LLVMAVRCodeGen.dir/AVRTargetMachine.cpp.o -c /Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetMachine.cpp
In file included from /Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetMachine.cpp:22:
/Users/carlpeto/avr/swift/llvm/lib/Target/AVR/AVRTargetObjectFile.h:26:68: error: non-virtual member function marked 'override' hides virtual member function
                                    const TargetMachine &TM) const override;
/Users/carlpeto/avr/swift/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h:59:14: note: hidden overloaded virtual function 'llvm::TargetLoweringObjectFileELF::SelectSectionForGlobal' declared here: different number of parameters (3 vs 4)
  MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
1 error generated.
[1103/2276] Building CXX object lib/CodeGen/CMakeFiles/LLVMCodeGen.dir/StackColoring.cpp.o
ninja: build stopped: subcommand failed.
utils/build-script: fatal error: command terminated with a non-zero exit status 1, aborting

I'll need to either use more up to date Swift to try to get nearer to the modern LLVM 6 of the AVR target code or use the hack Joe suggested to pass a different triple to clang...

(I'll post back here with the results when I try these approaches.)

OK, next issue...

"/Users/carlpeto/avr/swift/build/Ninja+cmark-ReleaseAssert+llvm-DebugAssert+swift-DebugAssert+stdlib-ReleaseAssert/swift-macosx-x86_64/bin/swiftc" -Xfrontend -emit-ir -S -no-link-objc-runtime -import-objc-header buildr.h -Xcc -target -Xcc -arm-linux-gnueabihf -I AVR -I CAVR -target avr-atmel-linux-gnueabihf -O -module-name main main.swift -o main.ll

<unknown>:0: error: unable to load standard library for target 'avr-atmel-linux-gnueabihf'

make: *** [main.ll] Error 1

For my purposes, i'm not actually using anything from the stdlib. Daft question... is there a way to 'disable' the stdlib for this invocation of compiling swift -> LLVM IR??

-parse-stdlib disables the import of the standard library. You're eventually going to need some kind of library that defines the basic integer and pointer types, though, especially if you want to use Swift's interop with C.

Yes, I came to exactly the same conclusions myself. :slight_smile:

My code mostly just calls through to an underlying C module, but all of that is exposed to swift as standard integer/pointer types, which are defined in stdlib.

That means when I try to include swift that calls through to my underlying C libs I get things like...

utils.swift:142:47: error: use of undeclared type 'UInt16'
public func writeEEPROMWithoutVerify(address: UInt16, value: UInt8) {

I have considered trying to copy in just the bits of the stdlib I need, just as a bare minimum.

But this is starting to become a major project when really all i'm trying to do is get the compiler to output pointers of a different size in the LLVM IR. Before that, my hacked together compilation was working in many cases even from LLVM IR that was made to target x86_64, provided I wrote my Swift code explicitly to show byte sizes, as above.

So I think I'll have to find another approach. It feels like there must be a simpler way to hack this than rewriting/porting stdlib (even if I may go there in the very long run to add support for structs, classes, enums, etc.)

A lot of compiler functionality relies on parts of the standard library existing. You're going to deal with a lot of pain trying to get code compiled for another platform to work on AVR. "Just outputting pointers of a different size" affects code generation in a lot of nontrivial ways. I would recommend continuing on with trying to build a minimal standard library, either from scratch or by selectively compiling out parts of the existing standard library that don't make sense on AVR.

1 Like

Yes, that makes sense. I'm going to need at least a basic stdlib most likely. I guess the question is really then, how do I create a stdlib for avr? My patch at least allows swift to accept avr as a target and enables the avr backend for llvm but i'm not clear how to configure the build for another architecture like this. Currently compiling on OSX.

I've stumbled upon a similar problem trying to compile stdlib for WebAssembly. I had to disable all code that depends on import Glibc and import Darwin. Very interesting how multiple stdlib implementations would fit into Swift compiler build infrastructure, because we can potentially have these platforms where significant parts need to be reimplemented from scratch.

It might be nice to extract out a "core" subset of the standard library that doesn't rely on large dependencies like ICU or heavyweight runtime functionality that doesn't make sense on embedded platforms. In the case of libc dependencies, though, you should be hopefully be able to modularize and use your platform libc to some degree instead of glibc/darwin.

1 Like

What would be the best way to proceed with this extraction? Creating a separate core barebones module, call it say Prelude, which is then reexported by Swift? Or some other way that changes the way stdlib is built?

To me it seems like it could be an alternative build of the existing standard library, #if-ing out the parts that don't belong in the "embedded" build, so that the implementation of that subset follows the standard implementation. Someone like @Ben_Cohen who works on the standard library might have stronger opinions, though, since I could also see that approach being an annoying maintenance burden.

Gosh... interesting discussion! I'm tempted to say for my case I want so very little of the standard library for now (really just Ints and Pointers) that I'm going to be much better doing one of two things...

  1. most simple - copy out the bits I need into my current "component" library (perhaps as a simple Stdlib.swift file), include that with my existing code and build everything with -parse-stdlib and somehow find a way to stop the swift compile from attempting to build stdlib in my case, just building swift/c.

  2. harder/better - find a way to modify the swift build process to include an out of tree version of stdlib then put my micro-stdlib in there.

Either way, I'd slowly add one or two bits as required. Like I say for now my code currently only ever uses Ints and Pointers.