aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2021-11-17 08:58:08 +0100
committerLuuk de Gram <luuk@degram.dev>2021-11-21 21:07:51 +0100
commitc18bc08e3c658f50faf7668f8940a11326f3947a (patch)
tree90f40dbeecbcd09c0a96c4aaa716d66496fe5d01 /src
parent05330bbe0ddd3057a1badea92a7823a2b1f4d68a (diff)
downloadzig-c18bc08e3c658f50faf7668f8940a11326f3947a.tar.gz
zig-c18bc08e3c658f50faf7668f8940a11326f3947a.zip
wasm: Linker - emit stack pointer
The self-hosted wasm linker now emits a mutable global. This entry represents the stack pointer, which has an initial value of offset table size + data size + stack size. Stack size can either be set by the user, or has the default of a single wasm page (64KiB).
Diffstat (limited to 'src')
-rw-r--r--src/link/Wasm.zig34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index a19d014dbe..cf05fcd94a 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -404,6 +404,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
// The table contains all decl's with its corresponding offset into
// the 'data' section
const offset_table_size = @intCast(u32, self.offset_table.items.len * ptr_width);
+ // The size of the emulated stack
+ const stack_size = @intCast(u32, self.base.options.stack_size_override orelse std.wasm.page_size);
// The size of the data, this together with `offset_table_size` amounts to the
// total size of the 'data' section
@@ -487,7 +489,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
}
// Memory section
- if (data_size != 0) {
+ {
const header_offset = try reserveVecSectionHeader(file);
const writer = file.writer();
@@ -498,7 +500,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
writer,
try std.math.divCeil(
u32,
- offset_table_size + data_size,
+ offset_table_size + data_size + stack_size,
std.wasm.page_size,
),
);
@@ -511,6 +513,34 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
);
}
+ // Global section (used to emit stack pointer)
+ {
+ // We emit the emulated stack at the end of the data section,
+ // 'growing' downwards towards the program memory.
+ // TODO: Have linker resolve the offset table, so we can emit the stack
+ // at the start so we can't overwrite program memory with the stack.
+ const sp_value = offset_table_size + data_size + std.wasm.page_size;
+ const mutable = true; // stack pointer MUST be mutable
+ const header_offset = try reserveVecSectionHeader(file);
+ const writer = file.writer();
+
+ try writer.writeByte(wasm.valtype(.i32));
+ try writer.writeByte(@boolToInt(mutable));
+
+ // set the initial value of the stack pointer to the data size + stack size
+ try writer.writeByte(wasm.opcode(.i32_const));
+ try leb.writeILEB128(writer, @bitCast(i32, sp_value));
+ try writer.writeByte(wasm.opcode(.end));
+
+ try writeVecSectionHeader(
+ file,
+ header_offset,
+ .global,
+ @intCast(u32, (try file.getPos()) - header_offset - header_size),
+ @as(u32, 1),
+ );
+ }
+
// Export section
if (self.base.options.module) |module| {
const header_offset = try reserveVecSectionHeader(file);