diff --git a/lld/test/wasm/data-layout.ll b/lld/test/wasm/data-layout.ll --- a/lld/test/wasm/data-layout.ll +++ b/lld/test/wasm/data-layout.ll @@ -32,12 +32,18 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1080 +; CHECK-NEXT: Value: 1088 ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1080 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66624 ; CHECK: - Type: DATA diff --git a/lld/test/wasm/gc-sections.ll b/lld/test/wasm/gc-sections.ll --- a/lld/test/wasm/gc-sections.ll +++ b/lld/test/wasm/gc-sections.ll @@ -117,12 +117,18 @@ ; NO-GC-NEXT: Opcode: I32_CONST ; NO-GC-NEXT: Value: 66576 ; NO-GC-NEXT: - Index: 1 +; NO-GC-NEXT: Type: I32 +; NO-GC-NEXT: Mutable: false +; NO-GC-NEXT: InitExpr: +; NO-GC-NEXT: Opcode: I32_CONST +; NO-GC-NEXT: Value: 1040 +; NO-GC-NEXT: - Index: 2 ; NO-GC-NEXT: Type: I64 ; NO-GC-NEXT: Mutable: true ; NO-GC-NEXT: InitExpr: ; NO-GC-NEXT: Opcode: I64_CONST ; NO-GC-NEXT: Value: 123 -; NO-GC-NEXT: - Index: 2 +; NO-GC-NEXT: - Index: 3 ; NO-GC-NEXT: Type: I64 ; NO-GC-NEXT: Mutable: true ; NO-GC-NEXT: InitExpr: diff --git a/lld/test/wasm/no-tls.test b/lld/test/wasm/no-tls.test --- a/lld/test/wasm/no-tls.test +++ b/lld/test/wasm/no-tls.test @@ -16,16 +16,24 @@ CHECK-NEXT: Opcode: I32_CONST CHECK-NEXT: Value: 66576 -; __tls_base +; __stack_limit CHECK-NEXT: - Index: 1 CHECK-NEXT: Type: I32 +CHECK-NEXT: Mutable: false +CHECK-NEXT: InitExpr: +CHECK-NEXT: Opcode: I32_CONST +CHECK-NEXT: Value: 1040 + +; __tls_base +CHECK-NEXT: - Index: 2 +CHECK-NEXT: Type: I32 CHECK-NEXT: Mutable: true CHECK-NEXT: InitExpr: CHECK-NEXT: Opcode: I32_CONST CHECK-NEXT: Value: 0 ; __tls_size -CHECK-NEXT: - Index: 2 +CHECK-NEXT: - Index: 3 CHECK-NEXT: Type: I32 CHECK-NEXT: Mutable: false CHECK-NEXT: InitExpr: @@ -33,7 +41,7 @@ CHECK-NEXT: Value: 0 ; __tls_align -CHECK-NEXT: - Index: 3 +CHECK-NEXT: - Index: 4 CHECK-NEXT: Type: I32 CHECK-NEXT: Mutable: false CHECK-NEXT: InitExpr: diff --git a/lld/test/wasm/pic-static.ll b/lld/test/wasm/pic-static.ll --- a/lld/test/wasm/pic-static.ll +++ b/lld/test/wasm/pic-static.ll @@ -64,16 +64,24 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66576 -; GOT.func.ret32 +; __stack_limit ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1040 + +; GOT.func.ret32 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 ; GOT.func.missing_function -; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -81,7 +89,7 @@ ; CHECK-NEXT: Value: 2 ; __table_base -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -89,7 +97,7 @@ ; CHECK-NEXT: Value: 1 ; GOT.mem.missing_float -; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -97,7 +105,7 @@ ; CHECK-NEXT: Value: 0 ; GOT.mem.global_float -; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: - Index: 6 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -105,7 +113,7 @@ ; CHECK-NEXT: Value: 1024 ; GOT.mem.ret32_ptr -; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: - Index: 7 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -113,7 +121,7 @@ ; CHECK-NEXT: Value: 1032 ; __memory_base -; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: - Index: 8 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: diff --git a/lld/test/wasm/tls-align.ll b/lld/test/wasm/tls-align.ll --- a/lld/test/wasm/tls-align.ll +++ b/lld/test/wasm/tls-align.ll @@ -26,16 +26,24 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66592 -; __tls_base +; __stack_limit ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1056 + +; __tls_base +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: true ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; __tls_size -; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -43,7 +51,7 @@ ; CHECK-NEXT: Value: 20 ; __tls_align -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: diff --git a/lld/test/wasm/tls.ll b/lld/test/wasm/tls.ll --- a/lld/test/wasm/tls.ll +++ b/lld/test/wasm/tls.ll @@ -36,16 +36,24 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 66576 -; __tls_base +; __stack_limit ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1040 + +; __tls_base +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: true ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; __tls_size -; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -53,7 +61,7 @@ ; CHECK-NEXT: Value: 8 ; __tls_align -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -66,7 +74,7 @@ ; Skip __wasm_call_ctors and __wasm_init_memory ; CHECK: - Index: 2 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 20002401200041004108FC0800000B +; CHECK-NEXT: Body: 20002402200041004108FC0800000B ; Expected body of __wasm_init_tls: ; local.get 0 @@ -79,7 +87,7 @@ ; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 2381808080004180808080006A0B +; CHECK-NEXT: Body: 2382808080004180808080006A0B ; Expected body of tls1_addr: ; global.get 1 @@ -89,7 +97,7 @@ ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 2381808080004184808080006A0B +; CHECK-NEXT: Body: 2382808080004184808080006A0B ; Expected body of tls1_addr: ; global.get 1 @@ -99,7 +107,7 @@ ; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 2383808080000B +; CHECK-NEXT: Body: 2384808080000B ; Expected body of tls1_addr: ; global.get 3 diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -500,6 +500,8 @@ // For non-PIC code WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true, 0); WasmSym::stackPointer->markLive(); + + WasmSym::stackLimit = createGlobalVariable("__stack_limit", false, 0); } if (config->sharedMemory && !config->shared) { diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -433,6 +433,11 @@ // linear memory. static GlobalSymbol *stackPointer; + // __stack_limit + // Global that holds the address of the end of the memory allocated for the + // explicit value stack in linear memory. + static GlobalSymbol *stackLimit; + // __tls_base // Global that holds the address of the base of the current thread's // TLS block. diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -70,6 +70,7 @@ DefinedData *WasmSym::heapBase; DefinedData *WasmSym::initMemoryFlag; GlobalSymbol *WasmSym::stackPointer; +GlobalSymbol *WasmSym::stackLimit; GlobalSymbol *WasmSym::tlsBase; GlobalSymbol *WasmSym::tlsSize; GlobalSymbol *WasmSym::tlsAlign; diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -211,10 +211,14 @@ error("stack size must be " + Twine(stackAlignment) + "-byte aligned"); log("mem: stack size = " + Twine(config->zStackSize)); log("mem: stack base = " + Twine(memoryPtr)); + uint32_t limitPtr = memoryPtr; memoryPtr += config->zStackSize; auto *sp = cast(WasmSym::stackPointer); sp->global->global.InitExpr.Value.Int32 = memoryPtr; log("mem: stack top = " + Twine(memoryPtr)); + auto *sl = cast(WasmSym::stackLimit); + sl->global->global.InitExpr.Value.Int32 = limitPtr; + log("mem: stack limit = " + Twine(limitPtr)); }; if (config->stackFirst) { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -77,7 +77,9 @@ // functions. It's OK to hardcode knowledge of specific symbols here; this // method is precisely there for fetching the signatures of known // Clang-provided symbols. - if (strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0 || + if (strcmp(Name, "__stack_pointer") == 0 || + strcmp(Name, "__stack_limit") == 0 || + strcmp(Name, "__tls_base") == 0 || strcmp(Name, "__memory_base") == 0 || strcmp(Name, "__table_base") == 0 || strcmp(Name, "__tls_size") == 0 || strcmp(Name, "__tls_align") == 0) { bool Mutable =