| ... | @@ -335,8 +335,6 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -335,8 +335,6 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 335 | log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max}); | 335 | log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max}); |
| 336 | } | 336 | } |
| 337 | | 337 | |
| 338 | // Size of each section header | | |
| 339 | const header_size = 5 + 1; | | |
| 340 | var section_index: u32 = 0; | 338 | var section_index: u32 = 0; |
| 341 | // Index of the code section. Used to tell relocation table where the section lives. | 339 | // Index of the code section. Used to tell relocation table where the section lives. |
| 342 | var code_section_index: ?u32 = null; | 340 | var code_section_index: ?u32 = null; |
| ... | @@ -369,54 +367,50 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -369,54 +367,50 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 369 | } | 367 | } |
| 370 | } | 368 | } |
| 371 | | 369 | |
| 372 | try writeVecSectionHeader( | 370 | replaceVecSectionHeader(binary_bytes, header_offset, .type, @intCast(wasm.func_types.entries.len)); |
| 373 | binary_bytes.items, | | |
| 374 | header_offset, | | |
| 375 | .type, | | |
| 376 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 377 | @intCast(wasm.func_types.entries.len), | | |
| 378 | ); | | |
| 379 | section_index += 1; | 371 | section_index += 1; |
| 380 | } | 372 | } |
| 381 | | 373 | |
| 382 | // Import section | 374 | // Import section |
| 383 | const total_imports_len = wasm.function_imports.entries.len + wasm.global_imports.entries.len + | 375 | { |
| 384 | wasm.table_imports.entries.len + wasm.object_memory_imports.items.len + @intFromBool(import_memory); | 376 | var total_imports: usize = 0; |
| 385 | | | |
| 386 | if (total_imports_len > 0) { | | |
| 387 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 377 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 388 | | 378 | |
| 389 | for (wasm.function_imports.values()) |*function_import| { | 379 | for (wasm.function_imports.values()) |id| { |
| 390 | const module_name = function_import.moduleName(wasm).slice(wasm); | 380 | const module_name = id.moduleName(wasm).slice(wasm); |
| 391 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | 381 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 392 | try binary_writer.writeAll(module_name); | 382 | try binary_writer.writeAll(module_name); |
| 393 | | 383 | |
| 394 | const name = function_import.name(wasm).slice(wasm); | 384 | const name = id.name(wasm).slice(wasm); |
| 395 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | 385 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); |
| 396 | try binary_writer.writeAll(name); | 386 | try binary_writer.writeAll(name); |
| 397 | | 387 | |
| 398 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function)); | 388 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function)); |
| 399 | try leb.writeUleb128(binary_writer, @intFromEnum(function_import.functionType(wasm))); | 389 | try leb.writeUleb128(binary_writer, @intFromEnum(id.functionType(wasm))); |
| 400 | } | 390 | } |
| | 391 | total_imports += wasm.function_imports.entries.len; |
| 401 | | 392 | |
| 402 | for (wasm.table_imports.values()) |*table_import| { | 393 | for (wasm.table_imports.values()) |id| { |
| 403 | const module_name = table_import.moduleName(wasm).slice(wasm); | 394 | const table_import = id.value(wasm); |
| | 395 | const module_name = table_import.module_name.slice(wasm); |
| 404 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | 396 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 405 | try binary_writer.writeAll(module_name); | 397 | try binary_writer.writeAll(module_name); |
| 406 | | 398 | |
| 407 | const name = table_import.name(wasm).slice(wasm); | 399 | const name = id.key(wasm).slice(wasm); |
| 408 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | 400 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); |
| 409 | try binary_writer.writeAll(name); | 401 | try binary_writer.writeAll(name); |
| 410 | | 402 | |
| 411 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.table)); | 403 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.table)); |
| 412 | try leb.writeUleb128(binary_writer, std.wasm.reftype(table_import.reftype)); | 404 | try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to()))); |
| 413 | try emitLimits(binary_writer, table_import.limits); | 405 | try emitLimits(gpa, binary_bytes, table_import.limits()); |
| 414 | } | 406 | } |
| | 407 | total_imports += wasm.table_imports.entries.len; |
| 415 | | 408 | |
| 416 | for (wasm.object_memory_imports.items) |*memory_import| { | 409 | for (wasm.object_memory_imports.items) |*memory_import| { |
| 417 | try emitMemoryImport(wasm, binary_writer, memory_import); | 410 | try emitMemoryImport(wasm, binary_bytes, memory_import); |
| | 411 | total_imports += 1; |
| 418 | } else if (import_memory) { | 412 | } else if (import_memory) { |
| 419 | try emitMemoryImport(wasm, binary_writer, &.{ | 413 | try emitMemoryImport(wasm, binary_bytes, &.{ |
| 420 | .module_name = wasm.host_name, | 414 | .module_name = wasm.host_name, |
| 421 | .name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory, | 415 | .name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory, |
| 422 | .limits_min = wasm.memories.limits.min, | 416 | .limits_min = wasm.memories.limits.min, |
| ... | @@ -424,100 +418,87 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -424,100 +418,87 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 424 | .limits_has_max = wasm.memories.limits.flags.has_max, | 418 | .limits_has_max = wasm.memories.limits.flags.has_max, |
| 425 | .limits_is_shared = wasm.memories.limits.flags.is_shared, | 419 | .limits_is_shared = wasm.memories.limits.flags.is_shared, |
| 426 | }); | 420 | }); |
| | 421 | total_imports += 1; |
| 427 | } | 422 | } |
| 428 | | 423 | |
| 429 | for (wasm.global_imports.values()) |*global_import| { | 424 | for (wasm.global_imports.values()) |id| { |
| 430 | const module_name = global_import.module_name.slice(wasm); | 425 | const module_name = id.moduleName(wasm).slice(wasm); |
| 431 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | 426 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 432 | try binary_writer.writeAll(module_name); | 427 | try binary_writer.writeAll(module_name); |
| 433 | | 428 | |
| 434 | const name = global_import.name.slice(wasm); | 429 | const name = id.name(wasm).slice(wasm); |
| 435 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | 430 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); |
| 436 | try binary_writer.writeAll(name); | 431 | try binary_writer.writeAll(name); |
| 437 | | 432 | |
| 438 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.global)); | 433 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.global)); |
| 439 | try leb.writeUleb128(binary_writer, @intFromEnum(global_import.valtype)); | 434 | const global_type = id.globalType(wasm); |
| 440 | try binary_writer.writeByte(@intFromBool(global_import.mutable)); | 435 | try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.Valtype, global_type.valtype))); |
| | 436 | try binary_writer.writeByte(@intFromBool(global_type.mutable)); |
| 441 | } | 437 | } |
| | 438 | total_imports += wasm.global_imports.entries.len; |
| 442 | | 439 | |
| 443 | try writeVecSectionHeader( | 440 | replaceVecSectionHeader(binary_bytes, header_offset, .import, @intCast(total_imports)); |
| 444 | binary_bytes.items, | | |
| 445 | header_offset, | | |
| 446 | .import, | | |
| 447 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 448 | @intCast(total_imports_len), | | |
| 449 | ); | | |
| 450 | section_index += 1; | 441 | section_index += 1; |
| 451 | } | 442 | } |
| 452 | | 443 | |
| 453 | // Function section | 444 | // Function section |
| 454 | if (wasm.functions.count() != 0) { | 445 | if (wasm.functions.count() != 0) { |
| 455 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 446 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 456 | for (wasm.functions.values()) |function| { | 447 | for (wasm.functions.keys()) |function| { |
| 457 | try leb.writeUleb128(binary_writer, function.func.type_index); | 448 | try leb.writeUleb128(binary_writer, @intFromEnum(function.typeIndex(wasm))); |
| 458 | } | 449 | } |
| 459 | | 450 | |
| 460 | try writeVecSectionHeader( | 451 | replaceVecSectionHeader(binary_bytes, header_offset, .function, @intCast(wasm.functions.count())); |
| 461 | binary_bytes.items, | | |
| 462 | header_offset, | | |
| 463 | .function, | | |
| 464 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 465 | @intCast(wasm.functions.count()), | | |
| 466 | ); | | |
| 467 | section_index += 1; | 452 | section_index += 1; |
| 468 | } | 453 | } |
| 469 | | 454 | |
| 470 | // Table section | 455 | // Table section |
| 471 | if (wasm.tables.items.len > 0) { | 456 | if (wasm.tables.entries.len > 0) { |
| 472 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 457 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 473 | | 458 | |
| 474 | for (wasm.tables.items) |table| { | 459 | for (wasm.tables.keys()) |table| { |
| 475 | try leb.writeUleb128(binary_writer, std.wasm.reftype(table.reftype)); | 460 | try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table.refType(wasm)))); |
| 476 | try emitLimits(binary_writer, table.limits); | 461 | try emitLimits(gpa, binary_bytes, table.limits(wasm)); |
| 477 | } | 462 | } |
| 478 | | 463 | |
| 479 | try writeVecSectionHeader( | 464 | replaceVecSectionHeader(binary_bytes, header_offset, .table, @intCast(wasm.tables.entries.len)); |
| 480 | binary_bytes.items, | | |
| 481 | header_offset, | | |
| 482 | .table, | | |
| 483 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 484 | @intCast(wasm.tables.items.len), | | |
| 485 | ); | | |
| 486 | section_index += 1; | 465 | section_index += 1; |
| 487 | } | 466 | } |
| 488 | | 467 | |
| 489 | // Memory section | 468 | // Memory section. wasm currently only supports 1 linear memory segment. |
| 490 | if (!import_memory) { | 469 | if (!import_memory) { |
| 491 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 470 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 492 | | 471 | try emitLimits(gpa, binary_bytes, wasm.memories.limits); |
| 493 | try emitLimits(binary_writer, wasm.memories.limits); | 472 | replaceVecSectionHeader(binary_bytes, header_offset, .memory, 1); |
| 494 | try writeVecSectionHeader( | | |
| 495 | binary_bytes.items, | | |
| 496 | header_offset, | | |
| 497 | .memory, | | |
| 498 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 499 | 1, // wasm currently only supports 1 linear memory segment | | |
| 500 | ); | | |
| 501 | section_index += 1; | 473 | section_index += 1; |
| 502 | } | 474 | } |
| 503 | | 475 | |
| 504 | // Global section (used to emit stack pointer) | 476 | // Global section (used to emit stack pointer) |
| 505 | if (wasm.output_globals.items.len > 0) { | 477 | if (wasm.globals.entries.len > 0) { |
| 506 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 478 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 507 | | 479 | |
| 508 | for (wasm.output_globals.items) |global| { | 480 | for (wasm.globals.keys()) |global_resolution| { |
| 509 | try binary_writer.writeByte(@intFromEnum(global.global_type.valtype)); | 481 | switch (global_resolution.unpack(wasm)) { |
| 510 | try binary_writer.writeByte(@intFromBool(global.global_type.mutable)); | 482 | .unresolved => unreachable, |
| 511 | try emitInit(binary_writer, global.init); | 483 | .__heap_base => @panic("TODO"), |
| | 484 | .__heap_end => @panic("TODO"), |
| | 485 | .__stack_pointer => @panic("TODO"), |
| | 486 | .__tls_align => @panic("TODO"), |
| | 487 | .__tls_base => @panic("TODO"), |
| | 488 | .__tls_size => @panic("TODO"), |
| | 489 | .__zig_error_name_table => @panic("TODO"), |
| | 490 | .object_global => |i| { |
| | 491 | const global = i.ptr(wasm); |
| | 492 | try binary_writer.writeByte(@intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to()))); |
| | 493 | try binary_writer.writeByte(@intFromBool(global.flags.global_type.mutable)); |
| | 494 | try emitExpr(wasm, binary_bytes, global.expr); |
| | 495 | }, |
| | 496 | .nav_exe => @panic("TODO"), |
| | 497 | .nav_obj => @panic("TODO"), |
| | 498 | } |
| 512 | } | 499 | } |
| 513 | | 500 | |
| 514 | try writeVecSectionHeader( | 501 | replaceVecSectionHeader(binary_bytes, header_offset, .global, @intCast(wasm.globals.entries.len)); |
| 515 | binary_bytes.items, | | |
| 516 | header_offset, | | |
| 517 | .global, | | |
| 518 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 519 | @intCast(wasm.output_globals.items.len), | | |
| 520 | ); | | |
| 521 | section_index += 1; | 502 | section_index += 1; |
| 522 | } | 503 | } |
| 523 | | 504 | |
| ... | @@ -540,25 +521,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -540,25 +521,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 540 | try leb.writeUleb128(binary_writer, @as(u32, 0)); | 521 | try leb.writeUleb128(binary_writer, @as(u32, 0)); |
| 541 | } | 522 | } |
| 542 | | 523 | |
| 543 | try writeVecSectionHeader( | 524 | const n_items: u32 = @intCast(wasm.exports.items.len + @intFromBool(export_memory)); |
| 544 | binary_bytes.items, | 525 | replaceVecSectionHeader(binary_bytes, header_offset, .@"export", n_items); |
| 545 | header_offset, | | |
| 546 | .@"export", | | |
| 547 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 548 | @intCast(wasm.exports.items.len + @intFromBool(export_memory)), | | |
| 549 | ); | | |
| 550 | section_index += 1; | 526 | section_index += 1; |
| 551 | } | 527 | } |
| 552 | | 528 | |
| 553 | if (wasm.entry) |entry_index| { | 529 | if (Wasm.FunctionIndex.fromResolution(wasm.entry_resolution)) |entry_index| { |
| 554 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 530 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 555 | try writeVecSectionHeader( | 531 | replaceVecSectionHeader(binary_bytes, header_offset, .start, @intFromEnum(entry_index)); |
| 556 | binary_bytes.items, | | |
| 557 | header_offset, | | |
| 558 | .start, | | |
| 559 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 560 | entry_index, | | |
| 561 | ); | | |
| 562 | } | 532 | } |
| 563 | | 533 | |
| 564 | // element section (function table) | 534 | // element section (function table) |
| ... | @@ -586,26 +556,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -586,26 +556,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 586 | try leb.writeUleb128(binary_writer, sym.index); | 556 | try leb.writeUleb128(binary_writer, sym.index); |
| 587 | } | 557 | } |
| 588 | | 558 | |
| 589 | try writeVecSectionHeader( | 559 | replaceVecSectionHeader(binary_bytes, header_offset, .element, 1); |
| 590 | binary_bytes.items, | | |
| 591 | header_offset, | | |
| 592 | .element, | | |
| 593 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 594 | 1, | | |
| 595 | ); | | |
| 596 | section_index += 1; | 560 | section_index += 1; |
| 597 | } | 561 | } |
| 598 | | 562 | |
| 599 | // When the shared-memory option is enabled, we *must* emit the 'data count' section. | 563 | // When the shared-memory option is enabled, we *must* emit the 'data count' section. |
| 600 | if (f.data_segment_groups.items.len > 0 and shared_memory) { | 564 | if (f.data_segment_groups.items.len > 0 and shared_memory) { |
| 601 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 565 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 602 | try writeVecSectionHeader( | 566 | replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len)); |
| 603 | binary_bytes.items, | | |
| 604 | header_offset, | | |
| 605 | .data_count, | | |
| 606 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 607 | @intCast(f.data_segment_groups.items.len), | | |
| 608 | ); | | |
| 609 | } | 567 | } |
| 610 | | 568 | |
| 611 | // Code section. | 569 | // Code section. |
| ... | @@ -636,13 +594,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -636,13 +594,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 636 | }, | 594 | }, |
| 637 | }; | 595 | }; |
| 638 | | 596 | |
| 639 | try writeVecSectionHeader( | 597 | replaceVecSectionHeader(binary_bytes, header_offset, .code, @intCast(wasm.functions.entries.len)); |
| 640 | binary_bytes.items, | | |
| 641 | header_offset, | | |
| 642 | .code, | | |
| 643 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 644 | @intCast(wasm.functions.count()), | | |
| 645 | ); | | |
| 646 | code_section_index = section_index; | 598 | code_section_index = section_index; |
| 647 | section_index += 1; | 599 | section_index += 1; |
| 648 | } | 600 | } |
| ... | @@ -682,13 +634,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | ... | @@ -682,13 +634,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { |
| 682 | } | 634 | } |
| 683 | assert(group_index == f.data_segment_groups.items.len); | 635 | assert(group_index == f.data_segment_groups.items.len); |
| 684 | | 636 | |
| 685 | try writeVecSectionHeader( | 637 | replaceVecSectionHeader(binary_bytes, header_offset, .data, group_index); |
| 686 | binary_bytes.items, | | |
| 687 | header_offset, | | |
| 688 | .data, | | |
| 689 | @intCast(binary_bytes.items.len - header_offset - header_size), | | |
| 690 | group_index, | | |
| 691 | ); | | |
| 692 | data_section_index = section_index; | 638 | data_section_index = section_index; |
| 693 | section_index += 1; | 639 | section_index += 1; |
| 694 | } | 640 | } |
| ... | @@ -768,7 +714,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), arena | ... | @@ -768,7 +714,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), arena |
| 768 | }; | 714 | }; |
| 769 | | 715 | |
| 770 | var globals: std.MultiArrayList(NamedIndex) = .empty; | 716 | var globals: std.MultiArrayList(NamedIndex) = .empty; |
| 771 | try globals.ensureTotalCapacityPrecise(arena, wasm.output_globals.items.len + wasm.global_imports.items.len); | 717 | try globals.ensureTotalCapacityPrecise(arena, wasm.globals.items.len + wasm.global_imports.items.len); |
| 772 | | 718 | |
| 773 | var segments: std.MultiArrayList(NamedIndex) = .empty; | 719 | var segments: std.MultiArrayList(NamedIndex) = .empty; |
| 774 | try segments.ensureTotalCapacityPrecise(arena, wasm.data_segments.count()); | 720 | try segments.ensureTotalCapacityPrecise(arena, wasm.data_segments.count()); |
| ... | @@ -844,10 +790,8 @@ fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void { | ... | @@ -844,10 +790,8 @@ fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void { |
| 844 | } | 790 | } |
| 845 | | 791 | |
| 846 | fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | 792 | fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { |
| 847 | // unlike regular section, we don't emit the count | 793 | try bytes.appendNTimes(gpa, 0, section_header_size); |
| 848 | const header_size = 1 + 5; | 794 | return @intCast(bytes.items.len - section_header_size); |
| 849 | try bytes.appendNTimes(gpa, 0, header_size); | | |
| 850 | return @intCast(bytes.items.len - header_size); | | |
| 851 | } | 795 | } |
| 852 | | 796 | |
| 853 | fn emitNameSubsection( | 797 | fn emitNameSubsection( |
| ... | @@ -1106,38 +1050,57 @@ fn wantSegmentMerge(wasm: *const Wasm, a_index: Wasm.DataSegment.Index, b_index: | ... | @@ -1106,38 +1050,57 @@ fn wantSegmentMerge(wasm: *const Wasm, a_index: Wasm.DataSegment.Index, b_index: |
| 1106 | return a_prefix.len > 0 and mem.eql(u8, a_prefix, b_prefix); | 1050 | return a_prefix.len > 0 and mem.eql(u8, a_prefix, b_prefix); |
| 1107 | } | 1051 | } |
| 1108 | | 1052 | |
| | 1053 | /// section id + fixed leb contents size + fixed leb vector length |
| | 1054 | const section_header_reserve_size = 1 + 5 + 5; |
| | 1055 | const section_header_size = 5 + 1; |
| | 1056 | |
| 1109 | fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | 1057 | fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { |
| 1110 | // section id + fixed leb contents size + fixed leb vector length | 1058 | try bytes.appendNTimes(gpa, 0, section_header_reserve_size); |
| 1111 | const header_size = 1 + 5 + 5; | 1059 | return @intCast(bytes.items.len - section_header_reserve_size); |
| 1112 | try bytes.appendNTimes(gpa, 0, header_size); | | |
| 1113 | return @intCast(bytes.items.len - header_size); | | |
| 1114 | } | 1060 | } |
| 1115 | | 1061 | |
| 1116 | fn writeVecSectionHeader(buffer: []u8, offset: u32, section: std.wasm.Section, size: u32, items: u32) !void { | 1062 | fn replaceVecSectionHeader( |
| 1117 | var buf: [1 + 5 + 5]u8 = undefined; | 1063 | bytes: *std.ArrayListUnmanaged(u8), |
| 1118 | buf[0] = @intFromEnum(section); | 1064 | offset: u32, |
| 1119 | leb.writeUnsignedFixed(5, buf[1..6], size); | 1065 | section: std.wasm.Section, |
| 1120 | leb.writeUnsignedFixed(5, buf[6..], items); | 1066 | n_items: u32, |
| 1121 | buffer[offset..][0..buf.len].* = buf; | 1067 | ) void { |
| | 1068 | const size: u32 = @intCast(bytes.items.len - offset - section_header_size); |
| | 1069 | var buf: [section_header_reserve_size]u8 = undefined; |
| | 1070 | var fbw = std.io.fixedBufferStream(&buf); |
| | 1071 | const w = fbw.writer(); |
| | 1072 | w.writeByte(@intFromEnum(section)) catch unreachable; |
| | 1073 | leb.writeUleb128(w, size) catch unreachable; |
| | 1074 | leb.writeUleb128(w, n_items) catch unreachable; |
| | 1075 | bytes.replaceRangeAssumeCapacity(offset, section_header_reserve_size, fbw.getWritten()); |
| 1122 | } | 1076 | } |
| 1123 | | 1077 | |
| 1124 | fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void { | 1078 | fn emitLimits( |
| 1125 | try writer.writeByte(limits.flags); | 1079 | gpa: Allocator, |
| 1126 | try leb.writeUleb128(writer, limits.min); | 1080 | binary_bytes: *std.ArrayListUnmanaged(u8), |
| 1127 | if (limits.flags.has_max) try leb.writeUleb128(writer, limits.max); | 1081 | limits: std.wasm.Limits, |
| | 1082 | ) Allocator.Error!void { |
| | 1083 | try binary_bytes.append(gpa, @bitCast(limits.flags)); |
| | 1084 | try leb.writeUleb128(binary_bytes.writer(gpa), limits.min); |
| | 1085 | if (limits.flags.has_max) try leb.writeUleb128(binary_bytes.writer(gpa), limits.max); |
| 1128 | } | 1086 | } |
| 1129 | | 1087 | |
| 1130 | fn emitMemoryImport(wasm: *Wasm, writer: anytype, memory_import: *const Wasm.MemoryImport) Allocator.Error!void { | 1088 | fn emitMemoryImport( |
| | 1089 | wasm: *Wasm, |
| | 1090 | binary_bytes: *std.ArrayListUnmanaged(u8), |
| | 1091 | memory_import: *const Wasm.MemoryImport, |
| | 1092 | ) Allocator.Error!void { |
| | 1093 | const gpa = wasm.base.comp.gpa; |
| 1131 | const module_name = memory_import.module_name.slice(wasm); | 1094 | const module_name = memory_import.module_name.slice(wasm); |
| 1132 | try leb.writeUleb128(writer, @as(u32, @intCast(module_name.len))); | 1095 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len))); |
| 1133 | try writer.writeAll(module_name); | 1096 | try binary_bytes.appendSlice(gpa, module_name); |
| 1134 | | 1097 | |
| 1135 | const name = memory_import.name.slice(wasm); | 1098 | const name = memory_import.name.slice(wasm); |
| 1136 | try leb.writeUleb128(writer, @as(u32, @intCast(name.len))); | 1099 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); |
| 1137 | try writer.writeAll(name); | 1100 | try binary_bytes.appendSlice(gpa, name); |
| 1138 | | 1101 | |
| 1139 | try writer.writeByte(@intFromEnum(std.wasm.ExternalKind.memory)); | 1102 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory)); |
| 1140 | try emitLimits(writer, memory_import.limits()); | 1103 | try emitLimits(gpa, binary_bytes, memory_import.limits()); |
| 1141 | } | 1104 | } |
| 1142 | | 1105 | |
| 1143 | pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void { | 1106 | pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void { |
| ... | @@ -1166,6 +1129,12 @@ pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void { | ... | @@ -1166,6 +1129,12 @@ pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void { |
| 1166 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.end)); | 1129 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.end)); |
| 1167 | } | 1130 | } |
| 1168 | | 1131 | |
| | 1132 | pub fn emitExpr(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), expr: Wasm.Expr) Allocator.Error!void { |
| | 1133 | const gpa = wasm.base.comp.gpa; |
| | 1134 | const slice = expr.slice(wasm); |
| | 1135 | try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode |
| | 1136 | } |
| | 1137 | |
| 1169 | //fn emitLinkSection( | 1138 | //fn emitLinkSection( |
| 1170 | // wasm: *Wasm, | 1139 | // wasm: *Wasm, |
| 1171 | // binary_bytes: *std.ArrayListUnmanaged(u8), | 1140 | // binary_bytes: *std.ArrayListUnmanaged(u8), |