{"record":{"id":"537f907573b9329b","repo":"dotnet/runtime","slug":"stack-pointer-was-not-preserved-by-the-linker-or","errorCode":null,"errorMessage":"__stack_pointer was not preserved by the linker or optimizer","messagePattern":"__stack_pointer was not preserved by the linker or optimizer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/native/libs/Common/JavaScript/host/assets.ts","lineNumber":121,"sourceCode":"    }\n}\n\n// Builds the `webcil` import object. For R2R images (tableSize > 0) the module imports the runtime's\n// stack pointer, exception tag, indirect-call table and base globals; this also grows the table.\n// These import names and the webcilVersion/getWebcilPayload/fillWebcilTable handshake in\n// finishWebcilInstance are the R2R Webcil-in-Wasm host ABI defined by crossgen's WasmObjectWriter\n// (src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs, CreateDefaultGlobalImports/\n// WriteExports). Keep in sync with the corerun host\n// (src/coreclr/hosts/corerun/wasm/libCorerun.js, BrowserHost_ExternalAssemblyProbe). Unlike corerun,\n// which parses data segment 0 for payloadSize/tableSize, this loader receives them from boot config.\nfunction buildWebcilImports(memory: WebAssembly.Memory, payloadPtr: number, tableSize: number): Record<string, WebAssembly.ImportValue> {\n    const webcilImports: Record<string, WebAssembly.ImportValue> = { memory };\n    if (tableSize > 0) {\n        const stackPointer = _ems_.wasmExports?.__stack_pointer;\n        const rtlRestoreContextTag = _ems_.wasmExports?.__coreclr_wasm_rtlrestorecontext_tag;\n        const asyncContinuation = _ems_.wasmExports?.__async_continuation;\n        if (!stackPointer) {\n            throw new Error(\"__stack_pointer was not preserved by the linker or optimizer\");\n        }\n        if (!rtlRestoreContextTag) {\n            throw new Error(\"__coreclr_wasm_rtlrestorecontext_tag was not preserved by the linker or optimizer\");\n        }\n        if (!asyncContinuation) {\n            throw new Error(\"__async_continuation was not preserved by the linker or optimizer\");\n        }\n        const tableStartIndex = _ems_.wasmTable.length;\n        _ems_.wasmTable.grow(tableSize);\n        webcilImports.stackPointer = stackPointer;\n        webcilImports.rtlRestoreContextTag = rtlRestoreContextTag as unknown as WebAssembly.ImportValue;\n        webcilImports.asyncContinuation = asyncContinuation as unknown as WebAssembly.ImportValue;\n        webcilImports.table = _ems_.wasmTable;\n        webcilImports.tableBase = new WebAssembly.Global({ value: \"i32\", mutable: false }, tableStartIndex);\n        webcilImports.imageBase = new WebAssembly.Global({ value: \"i32\", mutable: false }, payloadPtr);\n    }\n    return webcilImports;\n}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/Common/JavaScript/host/assets.ts#L103-L139","documentation":"Thrown by buildWebcilImports() (src/native/libs/Common/JavaScript/host/assets.ts:114) for an R2R webcil asset (tableSize > 0). The host ABI requires the runtime to export __stack_pointer so the R2R image can share the runtime stack; if _ems_.wasmExports.__stack_pointer is falsy, the import cannot be satisfied and instantiation would fail with a confusing link error, so the host throws early.","triggerScenarios":"An R2R (ReadyToRun) webcil assembly is being instantiated, tableSize > 0, and the loaded runtime wasm module does not export __stack_pointer. This means the runtime was built/linked with an optimizer or linker that stripped or renamed the export.","commonSituations":"Building the runtime with a custom emscripten/linker config that drops --export __stack_pointer; using an R2R assembly produced by a newer toolchain against an older runtime that lacks the export; a misconfigured linker 'export-keep' list.","solutions":["Rebuild the runtime with the standard linker flags that preserve __stack_pointer (the default emscripten/runtime build does this).","Ensure the runtime .wasm version matches the toolchain that produced the R2R webcil assembly.","If customizing the build, add __stack_pointer (and the sibling exports) to the linker --export list."],"exampleFix":"# before: custom linker flags drop internal exports\nemcc ... -s EXPORTED_FUNCTIONS=[]\n\n# after: keep the host-ABI exports\nemcc ... \\\n  -s EXPORTED_FUNCTIONS=[__stack_pointer,__coreclr_wasm_rtlrestorecontext_tag,__async_continuation]","handlingStrategy":"validation","validationCode":"function runtimeExportsStackPointer(): boolean {\n  return !!((globalThis as any).Module?.wasmExports?.__stack_pointer);\n}","typeGuard":"function hasStackPointer(exp: any): exp is { __stack_pointer: WebAssembly.Global } {\n  return exp && !!exp.__stack_pointer;\n}","tryCatchPattern":null,"preventionTips":["Build the runtime with the default linker flags that preserve __stack_pointer.","Match the R2R assembly toolchain version to the runtime version.","Add the host-ABI exports to the linker --export list when customizing the build."],"tags":["webcil","r2r","linker","build"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}