Open dfordivam opened 4 years ago
For the simple "hello-world" haskell code, the following works fine
wasm32-unknown-unknown-wasm-llc -mattr=+tail-call main.ll
It generates the
return_call_indirect (i32, i32, i32, i64, i64, i64, i64, i64, i64, i64) -> ()
But in the machine code generation step it fails
wasm32-unknown-unknown-wasm-llvm-mc --triple wasm32-unknown-unknown-wasm --mc-relax-all --mcpu=generic --mattr=+tail-call --filetype=obj -o main.o main.s
main.s:6:9: error: data directive must occur in a data segment: 0
.int64 0 # @"s1gf_info$def"
^
main.s:8:9: error: data directive must occur in a data segment: 21
.int32 21 # 0x15
Files here -> https://gist.github.com/dfordivam/1a4551dc3ea8a084541586c138c70fac
The wip branch is https://github.com/WebGHC/wasm-cross/tree/llvm-tailcall-1
The binaries generated via llvm backend are huge (10mb for hello-world, 115 mb reflex-todomvc) as the linker --gc-sections
is not removing most of the unused code. And this is not working because all the closure symbols being marked as NoStrip
. I tried various things to stop this but nothing worked.
On doing a hack in linker to ignore NoStrip
the sizes of the binaries reduced to 2mb for hello-world and 8mb for reflex-todomvc (after strip of debug symbols). These sizes are comparable / slightly bigger than the unregistered build (C based).
On further analysis of the closure of the binaries I found that they contain roughly the same number of symbols as the native binaries (indicating that the linker is indeed removing most of the dead code). And comparing the sizes of some of the APIs revealed that the size of wasm code is significantly bigger than the native.
API | native size | wasm size |
---|---|---|
base_GHCziConcziSignal_signalzuhandlers_entry | 104 | 178 |
base_GHCziForeignPtr_mallocForeignPtrBytes2_entry | 88 | 199 |
base_GHCziIOziBuffer_Buffer_con_entry | 16 | 45 |
base_GHCziIOziEncoding_getFileSystemEncoding6_entry | 88 | 250 |
I also tried the x86 llvm binary with NO_REGS and TABLES_NEXT_TO_CODE disabled. With this size of the binary (hello-world) increased by about 25%
So a combination of these two factors are behind the 2~3 times size difference between native x86 and wasm binaries.
If we are able to use llvm using the already supported tailcall (musttail call, without the ghccc), then we will have better idea of the size of binary andd potential issues further in the compilation. Also we could test the runtime in the chromium (by enabling the tail-call), and get to know if there are any issues in our approach, etc.