C and WASM via llvm
We are going to use the same llvm toolchain as in emcc:
$ brew install emscripten
$ emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.15
clang version 13.0.0 (https://github.com/llvm/llvm-project.git 1c5f08312874717caf5d94729d825c32845773ec)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /usr/local/opt/emscripten/libexec/llvm/bin
chapter_llvm/42/42.c
int answer() {
return 0b101010;
}
chapter_llvm/42/Makefile
CLANG=/usr/local/opt/emscripten/libexec/llvm/bin/clang
LLC=/usr/local/opt/emscripten/libexec/llvm/bin/llc
LD=/usr/local/opt/emscripten/libexec/llvm/bin/wasm-ld
WASM2WAT=wasm2wat
all:
$(CLANG) --target=wasm32 -emit-llvm -c -S 42.c
$(LLC) -march=wasm32 -filetype=obj 42.ll
$(LD) --no-entry --export=answer -o 42.wasm 42.o
$(WASM2WAT) -o 42.wat 42.wasm
clean:
rm 42.o 42.ll 42.wasm 42.wat
chapter_llvm/42/42.ll
; ModuleID = '42.c'
source_filename = "42.c"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32"
; Function Attrs: noinline nounwind optnone
define hidden i32 @answer() #0 {
ret i32 42
}
attributes #0 = { noinline nounwind optnone "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 1c5f08312874717caf5d94729d825c32845773ec)"}
chapter_llvm/42/42.wat
(module
(type (;0;) (func (result i32)))
(func $answer (type 0) (result i32)
i32.const 42)
(memory (;0;) 2)
(global (;0;) (mut i32) (i32.const 66560))
(export "memory" (memory 0))
(export "answer" (func $answer)))
chapter_llvm/42/42.js
(async () => {
var importObject = {};
const response = await fetch('chapter_llvm/42/42.wasm');
const bytes = await response.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, importObject);
const { exports } = instance;
console.log('Empty WASM Module', {response, bytes, instance, exports});
document.getElementById('llvm_output').innerHTML = `FROM WASM:
exports.answer() = ${exports.answer()}
`;
})();