| ... | @@ -404,6 +404,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -404,6 +404,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 404 | // The table contains all decl's with its corresponding offset into | 404 | // The table contains all decl's with its corresponding offset into |
| 405 | // the 'data' section | 405 | // the 'data' section |
| 406 | const offset_table_size = @intCast(u32, self.offset_table.items.len * ptr_width); | 406 | const offset_table_size = @intCast(u32, self.offset_table.items.len * ptr_width); |
| | 407 | // The size of the emulated stack |
| | 408 | const stack_size = @intCast(u32, self.base.options.stack_size_override orelse std.wasm.page_size); |
| 407 | | 409 | |
| 408 | // The size of the data, this together with `offset_table_size` amounts to the | 410 | // The size of the data, this together with `offset_table_size` amounts to the |
| 409 | // total size of the 'data' section | 411 | // total size of the 'data' section |
| ... | @@ -487,7 +489,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -487,7 +489,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 487 | } | 489 | } |
| 488 | | 490 | |
| 489 | // Memory section | 491 | // Memory section |
| 490 | if (data_size != 0) { | 492 | { |
| 491 | const header_offset = try reserveVecSectionHeader(file); | 493 | const header_offset = try reserveVecSectionHeader(file); |
| 492 | const writer = file.writer(); | 494 | const writer = file.writer(); |
| 493 | | 495 | |
| ... | @@ -498,7 +500,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -498,7 +500,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 498 | writer, | 500 | writer, |
| 499 | try std.math.divCeil( | 501 | try std.math.divCeil( |
| 500 | u32, | 502 | u32, |
| 501 | offset_table_size + data_size, | 503 | offset_table_size + data_size + stack_size, |
| 502 | std.wasm.page_size, | 504 | std.wasm.page_size, |
| 503 | ), | 505 | ), |
| 504 | ); | 506 | ); |
| ... | @@ -511,6 +513,34 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -511,6 +513,34 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 511 | ); | 513 | ); |
| 512 | } | 514 | } |
| 513 | | 515 | |
| | 516 | // Global section (used to emit stack pointer) |
| | 517 | { |
| | 518 | // We emit the emulated stack at the end of the data section, |
| | 519 | // 'growing' downwards towards the program memory. |
| | 520 | // TODO: Have linker resolve the offset table, so we can emit the stack |
| | 521 | // at the start so we can't overwrite program memory with the stack. |
| | 522 | const sp_value = offset_table_size + data_size + std.wasm.page_size; |
| | 523 | const mutable = true; // stack pointer MUST be mutable |
| | 524 | const header_offset = try reserveVecSectionHeader(file); |
| | 525 | const writer = file.writer(); |
| | 526 | |
| | 527 | try writer.writeByte(wasm.valtype(.i32)); |
| | 528 | try writer.writeByte(@boolToInt(mutable)); |
| | 529 | |
| | 530 | // set the initial value of the stack pointer to the data size + stack size |
| | 531 | try writer.writeByte(wasm.opcode(.i32_const)); |
| | 532 | try leb.writeILEB128(writer, @bitCast(i32, sp_value)); |
| | 533 | try writer.writeByte(wasm.opcode(.end)); |
| | 534 | |
| | 535 | try writeVecSectionHeader( |
| | 536 | file, |
| | 537 | header_offset, |
| | 538 | .global, |
| | 539 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| | 540 | @as(u32, 1), |
| | 541 | ); |
| | 542 | } |
| | 543 | |
| 514 | // Export section | 544 | // Export section |
| 515 | if (self.base.options.module) |module| { | 545 | if (self.base.options.module) |module| { |
| 516 | const header_offset = try reserveVecSectionHeader(file); | 546 | const header_offset = try reserveVecSectionHeader(file); |