Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try LLVM tailcall without ghccc #39

Open
dfordivam opened this issue Dec 9, 2019 · 2 comments
Open

Try LLVM tailcall without ghccc #39

dfordivam opened this issue Dec 9, 2019 · 2 comments

Comments

@dfordivam
Copy link
Member

dfordivam commented Dec 9, 2019

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.

@dfordivam
Copy link
Member Author

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

@dfordivam
Copy link
Member Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant