[lld] 13ca0c8 - [lld][WebAssembly] Align __heap_base
Ayke van Laethem via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 24 05:03:34 PDT 2021
Author: Ayke van Laethem
Date: 2021-07-24T14:03:26+02:00
New Revision: 13ca0c87edd026813ef7cbf3fbeb0efdb9c8bd3c
URL: https://github.com/llvm/llvm-project/commit/13ca0c87edd026813ef7cbf3fbeb0efdb9c8bd3c
DIFF: https://github.com/llvm/llvm-project/commit/13ca0c87edd026813ef7cbf3fbeb0efdb9c8bd3c.diff
LOG: [lld][WebAssembly] Align __heap_base
__heap_base was not aligned. In practice, it will often be aligned
simply because it follows the stack, but when the stack is placed at the
beginning (with the --stack-first option), the __heap_base might be
unaligned. It could even be byte-aligned.
At least wasi-libc appears to expect that __heap_base is aligned:
https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/dlmalloc/src/malloc.c#L5224
While WebAssembly itself does not appear to require any alignment for
memory accesses, it is sometimes required when sharing a pointer
externally. For example, WASI might expect alignment up to 8:
https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-timestamp-u64
This issue got introduced with the addition of the --stack-first flag:
https://reviews.llvm.org/D46141
I suspect the lack of alignment wasn't intentional here.
Differential Revision: https://reviews.llvm.org/D106499
Added:
lld/test/wasm/Inputs/stack-first.s
Modified:
lld/test/wasm/stack-first.test
lld/wasm/Writer.cpp
Removed:
################################################################################
diff --git a/lld/test/wasm/Inputs/stack-first.s b/lld/test/wasm/Inputs/stack-first.s
new file mode 100644
index 0000000000000..a2a356b573a9b
--- /dev/null
+++ b/lld/test/wasm/Inputs/stack-first.s
@@ -0,0 +1,11 @@
+ .globl _start
+_start:
+ .functype _start () -> ()
+ end_function
+
+ .globl someByte
+ .type someByte, at object
+ .section .data.someByte,"",@
+someByte:
+ .int8 42
+ .size someByte, 1
diff --git a/lld/test/wasm/stack-first.test b/lld/test/wasm/stack-first.test
index 9d7f077d58cf0..72e1a006d5700 100644
--- a/lld/test/wasm/stack-first.test
+++ b/lld/test/wasm/stack-first.test
@@ -2,9 +2,10 @@
; memory. In this case the --stack-first option is being passed along with a
; stack size of 512. This means (since the stack grows down) the stack pointer
; global should be initialized to 512.
+; Also test that __heap_base is still aligned with the --stack-first option.
-RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/start.s -o %t.o
-RUN: wasm-ld -z stack-size=512 --stack-first --export=__data_end --export=__heap_base -o %t.wasm %t.o
+RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/stack-first.s -o %t.o
+RUN: wasm-ld -z stack-size=512 --stack-first --export=__data_end --export=__heap_base --export=someByte -o %t.wasm %t.o
RUN: obj2yaml %t.wasm | FileCheck %s
CHECK: - Type: GLOBAL
@@ -26,7 +27,13 @@ CHECK-NEXT: Type: I32
CHECK-NEXT: Mutable: false
CHECK-NEXT: InitExpr:
CHECK-NEXT: Opcode: I32_CONST
-CHECK-NEXT: Value: 512
+CHECK-NEXT: Value: 513
+CHECK-NEXT: - Index: 3
+CHECK-NEXT: Type: I32
+CHECK-NEXT: Mutable: false
+CHECK-NEXT: InitExpr:
+CHECK-NEXT: Opcode: I32_CONST
+CHECK-NEXT: Value: 528
CHECK-NEXT: - Type: EXPORT
CHECK-NEXT: Exports:
CHECK-NEXT: - Name: memory
@@ -35,9 +42,12 @@ CHECK-NEXT: Index: 0
CHECK-NEXT: - Name: _start
CHECK-NEXT: Kind: FUNCTION
CHECK-NEXT: Index: 0
-CHECK-NEXT: - Name: __data_end
+CHECK-NEXT: - Name: someByte
CHECK-NEXT: Kind: GLOBAL
CHECK-NEXT: Index: 1
-CHECK-NEXT: - Name: __heap_base
+CHECK-NEXT: - Name: __data_end
CHECK-NEXT: Kind: GLOBAL
CHECK-NEXT: Index: 2
+CHECK-NEXT: - Name: __heap_base
+CHECK-NEXT: Kind: GLOBAL
+CHECK-NEXT: Index: 3
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index e94ea179d4dd3..cf9356ba18a36 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -43,6 +43,7 @@ using namespace llvm::wasm;
namespace lld {
namespace wasm {
static constexpr int stackAlignment = 16;
+static constexpr int heapAlignment = 16;
namespace {
@@ -310,9 +311,12 @@ void Writer::layoutMemory() {
placeStack();
if (WasmSym::heapBase) {
- // Set `__heap_base` to directly follow the end of the stack or global data.
- // The fact that this comes last means that a malloc/brk implementation
- // can grow the heap at runtime.
+ // Set `__heap_base` to follow the end of the stack or global data. The
+ // fact that this comes last means that a malloc/brk implementation can
+ // grow the heap at runtime.
+ // We'll align the heap base here because memory allocators might expect
+ // __heap_base to be aligned already.
+ memoryPtr = alignTo(memoryPtr, heapAlignment);
log("mem: heap base = " + Twine(memoryPtr));
WasmSym::heapBase->setVA(memoryPtr);
}
More information about the llvm-commits
mailing list