Skip to content

Commit

Permalink
Fixed and optimized linking with newer clang
Browse files Browse the repository at this point in the history
  • Loading branch information
yglukhov committed Mar 19, 2024
1 parent 0e1b6df commit 2754d22
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
5 changes: 2 additions & 3 deletions tests/config.nims
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
--d:release
--nomain
--opt:size
--listCmd
# --listCmd
--d:wasm
--stackTrace:off
--d:noSignalHandler
--exceptions:goto
--app:lib
--d:nimPreviewFloatRoundtrip # Avoid using sprintf as it's not available in wasm

let llTarget = "wasm32-unknown-unknown-wasm"
Expand All @@ -24,7 +23,7 @@ switch("passC", "-I/usr/include") # Wouldn't compile without this :(
switch("passC", "-flto") # Important for code size!

# gc-sections seems to not have any effect
var linkerOptions = "-nostdlib -Wl,--no-entry,--allow-undefined,--export-dynamic,--gc-sections,--strip-all"
var linkerOptions = "-nostdlib -Wl,--no-entry,--allow-undefined,--gc-sections,--strip-all"

switch("clang.options.linker", linkerOptions)
switch("clang.cpp.options.linker", linkerOptions)
24 changes: 13 additions & 11 deletions wasmrt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ const wasmExportCodegenDecl = when defined(cpp):
macro exportwasm*(p: untyped): untyped =
expectKind(p, nnkProcDef)
result = p
result.addPragma(ident"exportc")
result.addPragma(newColonExpr(ident"codegenDecl", newLit(wasmExportCodegenDecl)))
let name = $p.name
let codegenPragma = "__attribute__ ((export_name (\"" & name & "\"))) $# $#$#"
result.addPragma(newColonExpr(ident"codegenDecl", newLit(codegenPragma)))

proc stripSinkFromArgType(t: NimNode): NimNode =
result = t
Expand Down Expand Up @@ -365,21 +366,22 @@ g._nimwd = (v, a) => new Float64Array(q.buffer, a).set(v);
W.instantiate(m, {env: o}).then(m => {
g._nimm = m;
g._nime = m.exports;
q = _nime.memory;
n = g._nime = m.exports;
q = n.memory;
_nimmu();
_nime.NimMain();
for(i in n) if (i[0]==';') n[i]()
})
""").minifyJs().escapeJs()

{.emit: ["""
#define NIM_WASM_EXPORT N_LIB_EXPORT __attribute__((visibility ("default")))
int stdout = 0;
int stderr = 1;
static int dummyErrno = 0;
NIM_WASM_EXPORT const char __nimWasmInit __asm__(""" & '"' & initCode & """") = 0;
void __nimWasmInit() __attribute__((export_name(""" & '"' & initCode & """"))) {
void NimMain();
NimMain();
}
N_LIB_PRIVATE void* memcpy(void* a, const void* b, size_t s) {
char* aa = (char*)a;
Expand Down Expand Up @@ -572,8 +574,8 @@ macro defDyncall(sig: static[string]): untyped =

let wrappedCall = newCall(bindSym"dyncallWrap", callbackCall)
result = newProc(ident("dyncall"), params, wrappedCall)
result.addPragma(newColonExpr(ident"exportc", newLit("_d" & sig)))
result.addPragma(ident"dynlib")
let codegenPragma = "__attribute__ ((export_name (\"" & "_d" & sig & "\"))) $# $#$#"
result.addPragma(newColonExpr(ident"codegenDecl", newLit(codegenPragma)))
# echo repr result

proc defineDyncall*(sig: static[string]) =
Expand Down Expand Up @@ -687,7 +689,7 @@ proc free(p: pointer) {.exportc.} = dealloc(p)

# Suppress __wasm_call_ctors
# https://stackoverflow.com/questions/72568387/why-is-an-objects-constructor-being-called-in-every-exported-wasm-function
proc initialize() {.stackTrace: off, exportc: "_initialize", codegenDecl: wasmExportCodegenDecl.} =
proc initialize() {.stackTrace: off, exportc: "_initialize".} =
proc ctors() {.importc: "__wasm_call_ctors".}
ctors()

Expand Down

0 comments on commit 2754d22

Please sign in to comment.