Progress
Background
LLGO already successfully compiles Go code to LLVM IR (.ll files). Unlike the official Go compiler, LLGO heavily relies on C libraries for implementation, making its dependency handling needs more similar to C/C++ projects targeting WebAssembly.
Problem Statement
Extending LLGO to support WebAssembly requires addressing how to compile LLVM IR (.ll files) to WebAssembly and handle the various C library dependencies.
Compilation Path Challenge
The existing path from .ll to WebAssembly requires:
- Compiling LLVM IR to WebAssembly object files
- Linking WebAssembly object files with required libraries
- Resolving external function calls
Library Dependencies
A minimal executable dependencies:
ldd ~/go/bin/test
linux-vdso.so.1 (0x0000edf5b7cf6000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000edf5b7c10000)
libatomic.so.1 => /lib/aarch64-linux-gnu/libatomic.so.1 (0x0000edf5b77d0000)
libgc.so.1 => /lib/aarch64-linux-gnu/libgc.so.1 (0x0000edf5b7750000)
libunwind.so.8 => /lib/aarch64-linux-gnu/libunwind.so.8 (0x0000edf5b7700000)
libffi.so.8 => /lib/aarch64-linux-gnu/libffi.so.8 (0x0000edf5b76d0000)
libuv.so.1 => /lib/aarch64-linux-gnu/libuv.so.1 (0x0000edf5b7670000)
libssl.so.3 => /lib/aarch64-linux-gnu/libssl.so.3 (0x0000edf5b75a0000)
libcrypto.so.3 => /lib/aarch64-linux-gnu/libcrypto.so.3 (0x0000edf5b7000000)
libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000edf5b7560000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000edf5b6e40000)
/lib/ld-linux-aarch64.so.1 (0x0000edf5b7cb9000)
liblzma.so.5 => /lib/aarch64-linux-gnu/liblzma.so.5 (0x0000edf5b7510000)
otool -L ~/go/bin/test
/Users/lijie/go/bin/test.test:
/opt/homebrew/opt/bdw-gc/lib/libgc.1.dylib (compatibility version 1.0.0, current version 1.5.4)
/opt/homebrew/opt/llvm@18/lib/libLLVM.dylib (compatibility version 1.0.0, current version 18.1.8)
/opt/homebrew/opt/libuv/lib/libuv.1.dylib (compatibility version 2.0.0, current version 2.0.0)
/usr/lib/libffi.dylib (compatibility version 1.0.0, current version 39.0.0)
/opt/homebrew/opt/openssl@3/lib/libssl.3.dylib (compatibility version 3.0.0, current version 3.0.0)
/opt/homebrew/opt/openssl@3/lib/libcrypto.3.dylib (compatibility version 3.0.0, current version 3.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.12)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)
LLGO runtime depends on several external libraries that need WebAssembly support:
libgc.so.1 / libgc.1.dylib (Boehm Garbage Collector)
libunwind.so.8 (stack unwinding)
libuv.so.1 / libuv.1.dylib (async I/O)
libatomic.so.1 (atomic operations)
libssl.so.3 / libssl.3.dylib (OpenSSL)
libcrypto.so.3 / libcrypto.3.dylib (OpenSSL crypto)
libz.so.1 (compression)
libLLVM.dylib (LLVM libraries)
Existing Solutions Comparison
WASI-SDK vs Emscripten
| Library |
WASI-SDK |
Emscripten |
Notes |
| libm.so.6 |
✅ |
✅ |
Math library |
| libc.so.6 |
✅ |
✅ |
Standard C library |
| libatomic.so.1 |
Partial ✓ |
✅ |
Atomic operations |
| libgc.so.1 |
❌ |
Portable ✓ |
Garbage Collector |
| libunwind.so.8 |
❌ |
Partial ✓ |
Stack unwinding |
| libffi.so.8 |
❌ |
Portable ✓ |
Foreign Function Interface |
| libuv.so.1 |
❌ |
Portable ✓ |
Async I/O |
| libssl.so.3 |
❌ |
✅ (ports) |
OpenSSL |
| libcrypto.so.3 |
❌ |
✅ (ports) |
OpenSSL crypto |
| libz.so.1 |
❌ |
✅ (ports) |
zlib compression |
| libLLVM.dylib |
❌ |
❌ |
LLVM library (Removed via #1032) |
Implementation Approaches
-
WASI-SDK Approach
# Compile LLVM IR to object file
llc -march=wasm32 -filetype=obj -o file.o file.ll
# Link with WASI SDK
wasm-ld --export-all -o output.wasm file.o
- Handles standard C libraries
- Most external dependencies require manual porting
- Simpler, cleaner WebAssembly output
-
Emscripten Approach
# Compile LLVM IR to object file compatible with Emscripten
llc -march=wasm32 -filetype=obj -o file.o file.ll
# Link with Emscripten
emcc file.o -s USE_ZLIB=1 -s USE_SSL=1 -o output.js
- Better support for complex libraries
- Built-in handling for many dependencies
- More complex output with JavaScript dependencies
Platform-Specific libLLVM Runtime Dependency
The dependency on libLLVM.dylib is primarily a macOS-specific issue:
-
Platform-specific nature:
- On macOS: LLGO depends on
libLLVM.dylib mainly for its libunwind functionality
- On Linux: No direct runtime dependency on libLLVM exists
-
WebAssembly adaptation approach:
- For macOS-derived builds: Replace libunwind functionality with WebAssembly-compatible alternatives
- Use platform-agnostic stack unwinding approach for WebAssembly target
- Ensure any indirect LLVM runtime dependencies are identified and addressed
Third-party Library C Dependencies Challenge
Beyond LLGO's own dependencies, C dependencies in third-party libraries present a significant challenge:
- Many popular Go third-party libraries wrap C libraries via CGO for core functionality
- These C dependencies must also be compiled to WebAssembly
- Some C libraries may use features that are challenging in WebAssembly environments (file system, networking, threading)
This means that even with WebAssembly support in LLGO itself, the complete compilation of user projects may be limited by whether the C dependencies used in third-party libraries can be successfully converted to WebAssembly format.
Compatibility with Source Mapping and ABI Optimization Proposal
This proposal is theoretically compatible with the "Implementing Source Mapping and ABI Optimization Using Custom LLVM Passes" proposal:
- LLVM's WebAssembly backend supports DILocation and DWARF debug information
- Custom LLVM passes for source mapping should work with WebAssembly target
- Will need early validation to confirm DILocation preservation in WebAssembly output
Progress
llgoandruntimeto LLGoFiles because it is not compatible with GOOS=js or GOOS=wasip1import "C"unsafe.Sizeof(C.jmpbuf{})incompilerfmt.PrintlnBackground
LLGO already successfully compiles Go code to LLVM IR (.ll files). Unlike the official Go compiler, LLGO heavily relies on C libraries for implementation, making its dependency handling needs more similar to C/C++ projects targeting WebAssembly.
Problem Statement
Extending LLGO to support WebAssembly requires addressing how to compile LLVM IR (.ll files) to WebAssembly and handle the various C library dependencies.
Compilation Path Challenge
The existing path from
.llto WebAssembly requires:Library Dependencies
A minimal executable dependencies:
LLGO runtime depends on several external libraries that need WebAssembly support:
libgc.so.1/libgc.1.dylib(Boehm Garbage Collector)libunwind.so.8(stack unwinding)libuv.so.1/libuv.1.dylib(async I/O)libatomic.so.1(atomic operations)libssl.so.3/libssl.3.dylib(OpenSSL)libcrypto.so.3/libcrypto.3.dylib(OpenSSL crypto)libz.so.1(compression)libLLVM.dylib(LLVM libraries)Existing Solutions Comparison
WASI-SDK vs Emscripten
Implementation Approaches
WASI-SDK Approach
Emscripten Approach
Platform-Specific libLLVM Runtime Dependency
The dependency on
libLLVM.dylibis primarily a macOS-specific issue:Platform-specific nature:
libLLVM.dylibmainly for its libunwind functionalityWebAssembly adaptation approach:
Third-party Library C Dependencies Challenge
Beyond LLGO's own dependencies, C dependencies in third-party libraries present a significant challenge:
This means that even with WebAssembly support in LLGO itself, the complete compilation of user projects may be limited by whether the C dependencies used in third-party libraries can be successfully converted to WebAssembly format.
Compatibility with Source Mapping and ABI Optimization Proposal
This proposal is theoretically compatible with the "Implementing Source Mapping and ABI Optimization Using Custom LLVM Passes" proposal: