| ... | @@ -2054,6 +2054,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { | ... | @@ -2054,6 +2054,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { |
| 2054 | const decl = mod.declPtr(decl_index); | 2054 | const decl = mod.declPtr(decl_index); |
| 2055 | const atom_index = wasm.decls.get(decl_index).?; | 2055 | const atom_index = wasm.decls.get(decl_index).?; |
| 2056 | const atom = wasm.getAtomPtr(atom_index); | 2056 | const atom = wasm.getAtomPtr(atom_index); |
| | 2057 | atom.prev = null; |
| 2057 | wasm.symbols_free_list.append(gpa, atom.sym_index) catch {}; | 2058 | wasm.symbols_free_list.append(gpa, atom.sym_index) catch {}; |
| 2058 | _ = wasm.decls.remove(decl_index); | 2059 | _ = wasm.decls.remove(decl_index); |
| 2059 | wasm.symbols.items[atom.sym_index].tag = .dead; | 2060 | wasm.symbols.items[atom.sym_index].tag = .dead; |
| ... | @@ -2076,16 +2077,6 @@ pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { | ... | @@ -2076,16 +2077,6 @@ pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { |
| 2076 | // dwarf.freeDecl(decl_index); | 2077 | // dwarf.freeDecl(decl_index); |
| 2077 | // } | 2078 | // } |
| 2078 | | 2079 | |
| 2079 | if (atom.next) |next_atom_index| { | | |
| 2080 | const next_atom = wasm.getAtomPtr(next_atom_index); | | |
| 2081 | next_atom.prev = atom.prev; | | |
| 2082 | atom.next = null; | | |
| 2083 | } | | |
| 2084 | if (atom.prev) |prev_index| { | | |
| 2085 | const prev_atom = wasm.getAtomPtr(prev_index); | | |
| 2086 | prev_atom.next = atom.next; | | |
| 2087 | atom.prev = null; | | |
| 2088 | } | | |
| 2089 | } | 2080 | } |
| 2090 | | 2081 | |
| 2091 | /// Appends a new entry to the indirect function table | 2082 | /// Appends a new entry to the indirect function table |
| ... | @@ -2327,8 +2318,6 @@ pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void | ... | @@ -2327,8 +2318,6 @@ pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void |
| 2327 | const gpa = wasm.base.comp.gpa; | 2318 | const gpa = wasm.base.comp.gpa; |
| 2328 | const atom = wasm.getAtomPtr(atom_index); | 2319 | const atom = wasm.getAtomPtr(atom_index); |
| 2329 | if (wasm.atoms.getPtr(index)) |last_index_ptr| { | 2320 | if (wasm.atoms.getPtr(index)) |last_index_ptr| { |
| 2330 | const last = wasm.getAtomPtr(last_index_ptr.*); | | |
| 2331 | last.*.next = atom_index; | | |
| 2332 | atom.prev = last_index_ptr.*; | 2321 | atom.prev = last_index_ptr.*; |
| 2333 | last_index_ptr.* = atom_index; | 2322 | last_index_ptr.* = atom_index; |
| 2334 | } else { | 2323 | } else { |
| ... | @@ -2375,6 +2364,11 @@ fn allocateAtoms(wasm: *Wasm) !void { | ... | @@ -2375,6 +2364,11 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 2375 | while (it.next()) |entry| { | 2364 | while (it.next()) |entry| { |
| 2376 | const segment = &wasm.segments.items[entry.key_ptr.*]; | 2365 | const segment = &wasm.segments.items[entry.key_ptr.*]; |
| 2377 | var atom_index = entry.value_ptr.*; | 2366 | var atom_index = entry.value_ptr.*; |
| | 2367 | if (entry.key_ptr.* == wasm.code_section_index) { |
| | 2368 | // Code section is allocated upon writing as they are required to be ordered |
| | 2369 | // to synchronise with the function section. |
| | 2370 | continue; |
| | 2371 | } |
| 2378 | var offset: u32 = 0; | 2372 | var offset: u32 = 0; |
| 2379 | while (true) { | 2373 | while (true) { |
| 2380 | const atom = wasm.getAtomPtr(atom_index); | 2374 | const atom = wasm.getAtomPtr(atom_index); |
| ... | @@ -2387,28 +2381,17 @@ fn allocateAtoms(wasm: *Wasm) !void { | ... | @@ -2387,28 +2381,17 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 2387 | break :sym object.symtable[symbol_loc.index]; | 2381 | break :sym object.symtable[symbol_loc.index]; |
| 2388 | } else wasm.symbols.items[symbol_loc.index]; | 2382 | } else wasm.symbols.items[symbol_loc.index]; |
| 2389 | | 2383 | |
| | 2384 | // Dead symbols must be unlinked from the linked-list to prevent them |
| | 2385 | // from being emit into the binary. |
| 2390 | if (sym.isDead()) { | 2386 | if (sym.isDead()) { |
| 2391 | // Dead symbols must be unlinked from the linked-list to prevent them | 2387 | if (entry.value_ptr.* == atom_index and atom.prev != null) { |
| 2392 | // from being emit into the binary. | | |
| 2393 | if (atom.next) |next_index| { | | |
| 2394 | const next = wasm.getAtomPtr(next_index); | | |
| 2395 | next.prev = atom.prev; | | |
| 2396 | } else if (entry.value_ptr.* == atom_index) { | | |
| 2397 | // When the atom is dead and is also the first atom retrieved from wasm.atoms(index) we update | 2388 | // When the atom is dead and is also the first atom retrieved from wasm.atoms(index) we update |
| 2398 | // the entry to point it to the previous atom to ensure we do not start with a dead symbol that | 2389 | // the entry to point it to the previous atom to ensure we do not start with a dead symbol that |
| 2399 | // was removed and therefore do not emit any code at all. | 2390 | // was removed and therefore do not emit any code at all. |
| 2400 | if (atom.prev) |prev| { | 2391 | entry.value_ptr.* = atom.prev.?; |
| 2401 | entry.value_ptr.* = prev; | | |
| 2402 | } | | |
| 2403 | } | 2392 | } |
| 2404 | atom_index = atom.prev orelse { | 2393 | atom_index = atom.prev orelse break; |
| 2405 | atom.next = null; | | |
| 2406 | break; | | |
| 2407 | }; | | |
| 2408 | const prev = wasm.getAtomPtr(atom_index); | | |
| 2409 | prev.next = atom.next; | | |
| 2410 | atom.prev = null; | 2394 | atom.prev = null; |
| 2411 | atom.next = null; | | |
| 2412 | continue; | 2395 | continue; |
| 2413 | } | 2396 | } |
| 2414 | offset = @intCast(atom.alignment.forward(offset)); | 2397 | offset = @intCast(atom.alignment.forward(offset)); |
| ... | @@ -2546,16 +2529,6 @@ fn setupErrorsLen(wasm: *Wasm) !void { | ... | @@ -2546,16 +2529,6 @@ fn setupErrorsLen(wasm: *Wasm) !void { |
| 2546 | // if not, allcoate a new atom. | 2529 | // if not, allcoate a new atom. |
| 2547 | const atom_index = if (wasm.symbol_atom.get(loc)) |index| blk: { | 2530 | const atom_index = if (wasm.symbol_atom.get(loc)) |index| blk: { |
| 2548 | const atom = wasm.getAtomPtr(index); | 2531 | const atom = wasm.getAtomPtr(index); |
| 2549 | if (atom.next) |next_atom_index| { | | |
| 2550 | const next_atom = wasm.getAtomPtr(next_atom_index); | | |
| 2551 | next_atom.prev = atom.prev; | | |
| 2552 | atom.next = null; | | |
| 2553 | } | | |
| 2554 | if (atom.prev) |prev_index| { | | |
| 2555 | const prev_atom = wasm.getAtomPtr(prev_index); | | |
| 2556 | prev_atom.next = atom.next; | | |
| 2557 | atom.prev = null; | | |
| 2558 | } | | |
| 2559 | atom.deinit(gpa); | 2532 | atom.deinit(gpa); |
| 2560 | break :blk index; | 2533 | break :blk index; |
| 2561 | } else new_atom: { | 2534 | } else new_atom: { |
| ... | @@ -2658,18 +2631,12 @@ fn createSyntheticFunction( | ... | @@ -2658,18 +2631,12 @@ fn createSyntheticFunction( |
| 2658 | .sym_index = loc.index, | 2631 | .sym_index = loc.index, |
| 2659 | .file = null, | 2632 | .file = null, |
| 2660 | .alignment = .@"1", | 2633 | .alignment = .@"1", |
| 2661 | .next = null, | | |
| 2662 | .prev = null, | 2634 | .prev = null, |
| 2663 | .code = function_body.moveToUnmanaged(), | 2635 | .code = function_body.moveToUnmanaged(), |
| 2664 | .original_offset = 0, | 2636 | .original_offset = 0, |
| 2665 | }; | 2637 | }; |
| 2666 | try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom_index); | 2638 | try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom_index); |
| 2667 | try wasm.symbol_atom.putNoClobber(gpa, loc, atom_index); | 2639 | try wasm.symbol_atom.putNoClobber(gpa, loc, atom_index); |
| 2668 | | | |
| 2669 | // `allocateAtoms` has already been called, set the atom's offset manually. | | |
| 2670 | // This is fine to do manually as we insert the atom at the very end. | | |
| 2671 | const prev_atom = wasm.getAtom(atom.prev.?); | | |
| 2672 | atom.offset = prev_atom.offset + prev_atom.size; | | |
| 2673 | } | 2640 | } |
| 2674 | | 2641 | |
| 2675 | /// Unlike `createSyntheticFunction` this function is to be called by | 2642 | /// Unlike `createSyntheticFunction` this function is to be called by |
| ... | @@ -2695,7 +2662,6 @@ pub fn createFunction( | ... | @@ -2695,7 +2662,6 @@ pub fn createFunction( |
| 2695 | .sym_index = loc.index, | 2662 | .sym_index = loc.index, |
| 2696 | .file = null, | 2663 | .file = null, |
| 2697 | .alignment = .@"1", | 2664 | .alignment = .@"1", |
| 2698 | .next = null, | | |
| 2699 | .prev = null, | 2665 | .prev = null, |
| 2700 | .code = function_body.moveToUnmanaged(), | 2666 | .code = function_body.moveToUnmanaged(), |
| 2701 | .relocs = relocations.moveToUnmanaged(), | 2667 | .relocs = relocations.moveToUnmanaged(), |
| ... | @@ -3260,7 +3226,7 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u3 | ... | @@ -3260,7 +3226,7 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u3 |
| 3260 | break :blk index; | 3226 | break :blk index; |
| 3261 | }; | 3227 | }; |
| 3262 | } else if (mem.eql(u8, section_name, ".debug_ranges")) { | 3228 | } else if (mem.eql(u8, section_name, ".debug_ranges")) { |
| 3263 | return wasm.debug_line_index orelse blk: { | 3229 | return wasm.debug_ranges_index orelse blk: { |
| 3264 | wasm.debug_ranges_index = index; | 3230 | wasm.debug_ranges_index = index; |
| 3265 | try wasm.appendDummySegment(); | 3231 | try wasm.appendDummySegment(); |
| 3266 | break :blk index; | 3232 | break :blk index; |
| ... | @@ -3452,12 +3418,10 @@ fn resetState(wasm: *Wasm) void { | ... | @@ -3452,12 +3418,10 @@ fn resetState(wasm: *Wasm) void { |
| 3452 | var atom_it = wasm.decls.valueIterator(); | 3418 | var atom_it = wasm.decls.valueIterator(); |
| 3453 | while (atom_it.next()) |atom_index| { | 3419 | while (atom_it.next()) |atom_index| { |
| 3454 | const atom = wasm.getAtomPtr(atom_index.*); | 3420 | const atom = wasm.getAtomPtr(atom_index.*); |
| 3455 | atom.next = null; | | |
| 3456 | atom.prev = null; | 3421 | atom.prev = null; |
| 3457 | | 3422 | |
| 3458 | for (atom.locals.items) |local_atom_index| { | 3423 | for (atom.locals.items) |local_atom_index| { |
| 3459 | const local_atom = wasm.getAtomPtr(local_atom_index); | 3424 | const local_atom = wasm.getAtomPtr(local_atom_index); |
| 3460 | local_atom.next = null; | | |
| 3461 | local_atom.prev = null; | 3425 | local_atom.prev = null; |
| 3462 | } | 3426 | } |
| 3463 | } | 3427 | } |
| ... | @@ -4085,46 +4049,29 @@ fn writeToFile( | ... | @@ -4085,46 +4049,29 @@ fn writeToFile( |
| 4085 | } | 4049 | } |
| 4086 | | 4050 | |
| 4087 | // Code section | 4051 | // Code section |
| 4088 | var code_section_size: u32 = 0; | 4052 | if (wasm.code_section_index != null) { |
| 4089 | if (wasm.code_section_index) |code_index| { | | |
| 4090 | const header_offset = try reserveVecSectionHeader(&binary_bytes); | 4053 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 4091 | var atom_index = wasm.atoms.get(code_index).?; | 4054 | const start_offset = binary_bytes.items.len - 5; // minus 5 so start offset is 5 to include entry count |
| 4092 | | 4055 | |
| 4093 | // The code section must be sorted in line with the function order. | 4056 | var func_it = wasm.functions.iterator(); |
| 4094 | var sorted_atoms = try std.ArrayList(*const Atom).initCapacity(gpa, wasm.functions.count()); | 4057 | while (func_it.next()) |entry| { |
| 4095 | defer sorted_atoms.deinit(); | 4058 | const sym_loc: SymbolLoc = .{ .index = entry.value_ptr.sym_index, .file = entry.key_ptr.file }; |
| 4096 | | 4059 | const atom_index = wasm.symbol_atom.get(sym_loc).?; |
| 4097 | while (true) { | | |
| 4098 | const atom = wasm.getAtomPtr(atom_index); | 4060 | const atom = wasm.getAtomPtr(atom_index); |
| | 4061 | |
| 4099 | if (!is_obj) { | 4062 | if (!is_obj) { |
| 4100 | atom.resolveRelocs(wasm); | 4063 | atom.resolveRelocs(wasm); |
| 4101 | } | 4064 | } |
| 4102 | sorted_atoms.appendAssumeCapacity(atom); // found more code atoms than functions | 4065 | atom.offset = @intCast(binary_bytes.items.len - start_offset); |
| 4103 | atom_index = atom.prev orelse break; | 4066 | try leb.writeULEB128(binary_writer, atom.size); |
| 4104 | } | 4067 | try binary_writer.writeAll(atom.code.items); |
| 4105 | assert(wasm.functions.count() == sorted_atoms.items.len); | | |
| 4106 | | | |
| 4107 | const atom_sort_fn = struct { | | |
| 4108 | fn sort(ctx: *const Wasm, lhs: *const Atom, rhs: *const Atom) bool { | | |
| 4109 | const lhs_sym = lhs.symbolLoc().getSymbol(ctx); | | |
| 4110 | const rhs_sym = rhs.symbolLoc().getSymbol(ctx); | | |
| 4111 | return lhs_sym.index < rhs_sym.index; | | |
| 4112 | } | | |
| 4113 | }.sort; | | |
| 4114 | | | |
| 4115 | mem.sort(*const Atom, sorted_atoms.items, wasm, atom_sort_fn); | | |
| 4116 | | | |
| 4117 | for (sorted_atoms.items) |sorted_atom| { | | |
| 4118 | try leb.writeULEB128(binary_writer, sorted_atom.size); | | |
| 4119 | try binary_writer.writeAll(sorted_atom.code.items); | | |
| 4120 | } | 4068 | } |
| 4121 | | 4069 | |
| 4122 | code_section_size = @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)); | | |
| 4123 | try writeVecSectionHeader( | 4070 | try writeVecSectionHeader( |
| 4124 | binary_bytes.items, | 4071 | binary_bytes.items, |
| 4125 | header_offset, | 4072 | header_offset, |
| 4126 | .code, | 4073 | .code, |
| 4127 | code_section_size, | 4074 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 4128 | @intCast(wasm.functions.count()), | 4075 | @intCast(wasm.functions.count()), |
| 4129 | ); | 4076 | ); |
| 4130 | code_section_index = section_count; | 4077 | code_section_index = section_count; |
| ... | @@ -5301,14 +5248,8 @@ fn markReferences(wasm: *Wasm) !void { | ... | @@ -5301,14 +5248,8 @@ fn markReferences(wasm: *Wasm) !void { |
| 5301 | const object = &wasm.objects.items[file]; | 5248 | const object = &wasm.objects.items[file]; |
| 5302 | const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm); | 5249 | const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm); |
| 5303 | const atom = wasm.getAtom(atom_index); | 5250 | const atom = wasm.getAtom(atom_index); |
| 5304 | for (atom.relocs.items) |reloc| { | 5251 | const atom_sym = atom.symbolLoc().getSymbol(wasm); |
| 5305 | const target_loc: SymbolLoc = .{ .index = reloc.index, .file = atom.file }; | 5252 | atom_sym.mark(); |
| 5306 | const target_sym = target_loc.getSymbol(wasm); | | |
| 5307 | if (target_sym.isAlive() or !do_garbage_collect) { | | |
| 5308 | sym.mark(); | | |
| 5309 | continue; // Skip all other relocations as this debug atom is already marked now | | |
| 5310 | } | | |
| 5311 | } | | |
| 5312 | } | 5253 | } |
| 5313 | } | 5254 | } |
| 5314 | } | 5255 | } |