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()}
`;
})();