authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-02-01 18:55:35+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-02-01 19:10:56+01:00
log46f54b23ae604c3f99f51ca719d9085530f6b59c
tree66547a2f4b33e876afb0b29ea6799795959699fb
parent1aa0f8aa2f382fb56639ea6833a62c4b8b031247
signaturelock-open Commit is signed but in an unrecognized format.

link: make Wasm atoms fully owned by the linker


10 files changed, 354 insertions(+), 327 deletions(-)

src/Module.zig+3-3
...@@ -5266,7 +5266,7 @@ pub fn clearDecl(...@@ -5266,7 +5266,7 @@ pub fn clearDecl(
5266 .macho => .{ .macho = {} },5266 .macho => .{ .macho = {} },
5267 .plan9 => .{ .plan9 = {} },5267 .plan9 => .{ .plan9 = {} },
5268 .c => .{ .c = {} },5268 .c => .{ .c = {} },
5269 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },5269 .wasm => .{ .wasm = {} },
5270 .spirv => .{ .spirv = {} },5270 .spirv => .{ .spirv = {} },
5271 .nvptx => .{ .nvptx = {} },5271 .nvptx => .{ .nvptx = {} },
5272 };5272 };
...@@ -5374,7 +5374,7 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void...@@ -5374,7 +5374,7 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
5374 try macho.deleteDeclExport(decl_index, exp.options.name);5374 try macho.deleteDeclExport(decl_index, exp.options.name);
5375 }5375 }
5376 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {5376 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
5377 wasm.deleteExport(exp.link.wasm);5377 wasm.deleteDeclExport(decl_index);
5378 }5378 }
5379 if (mod.comp.bin_file.cast(link.File.Coff)) |coff| {5379 if (mod.comp.bin_file.cast(link.File.Coff)) |coff| {
5380 coff.deleteDeclExport(decl_index, exp.options.name);5380 coff.deleteDeclExport(decl_index, exp.options.name);
...@@ -5686,7 +5686,7 @@ pub fn allocateNewDecl(...@@ -5686,7 +5686,7 @@ pub fn allocateNewDecl(
5686 .macho => .{ .macho = {} },5686 .macho => .{ .macho = {} },
5687 .plan9 => .{ .plan9 = {} },5687 .plan9 => .{ .plan9 = {} },
5688 .c => .{ .c = {} },5688 .c => .{ .c = {} },
5689 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },5689 .wasm => .{ .wasm = {} },
5690 .spirv => .{ .spirv = {} },5690 .spirv => .{ .spirv = {} },
5691 .nvptx => .{ .nvptx = {} },5691 .nvptx => .{ .nvptx = {} },
5692 },5692 },
src/Sema.zig+1-1
...@@ -5570,7 +5570,7 @@ pub fn analyzeExport(...@@ -5570,7 +5570,7 @@ pub fn analyzeExport(
5570 .macho => .{ .macho = {} },5570 .macho => .{ .macho = {} },
5571 .plan9 => .{ .plan9 = {} },5571 .plan9 => .{ .plan9 = {} },
5572 .c => .{ .c = {} },5572 .c => .{ .c = {} },
5573 .wasm => .{ .wasm = .{} },5573 .wasm => .{ .wasm = {} },
5574 .spirv => .{ .spirv = {} },5574 .spirv => .{ .spirv = {} },
5575 .nvptx => .{ .nvptx = {} },5575 .nvptx => .{ .nvptx = {} },
5576 },5576 },
src/arch/wasm/CodeGen.zig+15-15
...@@ -1269,10 +1269,10 @@ fn genFunc(func: *CodeGen) InnerError!void {...@@ -1269,10 +1269,10 @@ fn genFunc(func: *CodeGen) InnerError!void {
12691269
1270 var emit: Emit = .{1270 var emit: Emit = .{
1271 .mir = mir,1271 .mir = mir,
1272 .bin_file = &func.bin_file.base,1272 .bin_file = func.bin_file,
1273 .code = func.code,1273 .code = func.code,
1274 .locals = func.locals.items,1274 .locals = func.locals.items,
1275 .decl = func.decl,1275 .decl_index = func.decl_index,
1276 .dbg_output = func.debug_output,1276 .dbg_output = func.debug_output,
1277 .prev_di_line = 0,1277 .prev_di_line = 0,
1278 .prev_di_column = 0,1278 .prev_di_column = 0,
...@@ -2115,21 +2115,20 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2115,21 +2115,20 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2115 const fn_info = fn_ty.fnInfo();2115 const fn_info = fn_ty.fnInfo();
2116 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, func.target);2116 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, func.target);
21172117
2118 const callee: ?*Decl = blk: {2118 const callee: ?Decl.Index = blk: {
2119 const func_val = func.air.value(pl_op.operand) orelse break :blk null;2119 const func_val = func.air.value(pl_op.operand) orelse break :blk null;
2120 const module = func.bin_file.base.options.module.?;2120 const module = func.bin_file.base.options.module.?;
21212121
2122 if (func_val.castTag(.function)) |function| {2122 if (func_val.castTag(.function)) |function| {
2123 const decl = module.declPtr(function.data.owner_decl);2123 _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);
2124 try decl.link.wasm.ensureInitialized(func.bin_file);2124 break :blk function.data.owner_decl;
2125 break :blk decl;
2126 } else if (func_val.castTag(.extern_fn)) |extern_fn| {2125 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
2127 const ext_decl = module.declPtr(extern_fn.data.owner_decl);2126 const ext_decl = module.declPtr(extern_fn.data.owner_decl);
2128 const ext_info = ext_decl.ty.fnInfo();2127 const ext_info = ext_decl.ty.fnInfo();
2129 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, func.target);2128 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, func.target);
2130 defer func_type.deinit(func.gpa);2129 defer func_type.deinit(func.gpa);
2131 const atom = &ext_decl.link.wasm;2130 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl);
2132 try atom.ensureInitialized(func.bin_file);2131 const atom = func.bin_file.getAtomPtr(atom_index);
2133 ext_decl.fn_link.wasm.type_index = try func.bin_file.putOrGetFuncType(func_type);2132 ext_decl.fn_link.wasm.type_index = try func.bin_file.putOrGetFuncType(func_type);
2134 try func.bin_file.addOrUpdateImport(2133 try func.bin_file.addOrUpdateImport(
2135 mem.sliceTo(ext_decl.name, 0),2134 mem.sliceTo(ext_decl.name, 0),
...@@ -2137,11 +2136,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2137,11 +2136,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2137 ext_decl.getExternFn().?.lib_name,2136 ext_decl.getExternFn().?.lib_name,
2138 ext_decl.fn_link.wasm.type_index,2137 ext_decl.fn_link.wasm.type_index,
2139 );2138 );
2140 break :blk ext_decl;2139 break :blk extern_fn.data.owner_decl;
2141 } else if (func_val.castTag(.decl_ref)) |decl_ref| {2140 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
2142 const decl = module.declPtr(decl_ref.data);2141 _ = try func.bin_file.getOrCreateAtomForDecl(decl_ref.data);
2143 try decl.link.wasm.ensureInitialized(func.bin_file);2142 break :blk decl_ref.data;
2144 break :blk decl;
2145 }2143 }
2146 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});2144 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});
2147 };2145 };
...@@ -2162,7 +2160,8 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2162,7 +2160,8 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2162 }2160 }
21632161
2164 if (callee) |direct| {2162 if (callee) |direct| {
2165 try func.addLabel(.call, direct.link.wasm.sym_index);2163 const atom_index = func.bin_file.decls.get(direct).?;
2164 try func.addLabel(.call, func.bin_file.getAtom(atom_index).sym_index);
2166 } else {2165 } else {
2167 // in this case we call a function pointer2166 // in this case we call a function pointer
2168 // so load its value onto the stack2167 // so load its value onto the stack
...@@ -2758,9 +2757,10 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Ind...@@ -2758,9 +2757,10 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Ind
2758 }2757 }
27592758
2760 module.markDeclAlive(decl);2759 module.markDeclAlive(decl);
2761 try decl.link.wasm.ensureInitialized(func.bin_file);2760 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
2761 const atom = func.bin_file.getAtom(atom_index);
27622762
2763 const target_sym_index = decl.link.wasm.sym_index;2763 const target_sym_index = atom.sym_index;
2764 if (decl.ty.zigTypeTag() == .Fn) {2764 if (decl.ty.zigTypeTag() == .Fn) {
2765 try func.bin_file.addTableFunction(target_sym_index);2765 try func.bin_file.addTableFunction(target_sym_index);
2766 return WValue{ .function_index = target_sym_index };2766 return WValue{ .function_index = target_sym_index };
src/arch/wasm/Emit.zig+18-11
...@@ -11,8 +11,8 @@ const leb128 = std.leb;...@@ -11,8 +11,8 @@ const leb128 = std.leb;
1111
12/// Contains our list of instructions12/// Contains our list of instructions
13mir: Mir,13mir: Mir,
14/// Reference to the file handler14/// Reference to the Wasm module linker
15bin_file: *link.File,15bin_file: *link.File.Wasm,
16/// Possible error message. When set, the value is allocated and16/// Possible error message. When set, the value is allocated and
17/// must be freed manually.17/// must be freed manually.
18error_msg: ?*Module.ErrorMsg = null,18error_msg: ?*Module.ErrorMsg = null,
...@@ -21,7 +21,7 @@ code: *std.ArrayList(u8),...@@ -21,7 +21,7 @@ code: *std.ArrayList(u8),
21/// List of allocated locals.21/// List of allocated locals.
22locals: []const u8,22locals: []const u8,
23/// The declaration that code is being generated for.23/// The declaration that code is being generated for.
24decl: *Module.Decl,24decl_index: Module.Decl.Index,
2525
26// Debug information26// Debug information
27/// Holds the debug information for this emission27/// Holds the debug information for this emission
...@@ -252,8 +252,8 @@ fn offset(self: Emit) u32 {...@@ -252,8 +252,8 @@ fn offset(self: Emit) u32 {
252fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {252fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
253 @setCold(true);253 @setCold(true);
254 std.debug.assert(emit.error_msg == null);254 std.debug.assert(emit.error_msg == null);
255 // TODO: Determine the source location.255 const mod = emit.bin_file.base.options.module.?;
256 emit.error_msg = try Module.ErrorMsg.create(emit.bin_file.allocator, emit.decl.srcLoc(), format, args);256 emit.error_msg = try Module.ErrorMsg.create(emit.bin_file.base.allocator, mod.declPtr(emit.decl_index).srcLoc(), format, args);
257 return error.EmitFail;257 return error.EmitFail;
258}258}
259259
...@@ -304,8 +304,9 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void {...@@ -304,8 +304,9 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void {
304 const global_offset = emit.offset();304 const global_offset = emit.offset();
305 try emit.code.appendSlice(&buf);305 try emit.code.appendSlice(&buf);
306306
307 // globals can have index 0 as it represents the stack pointer307 const atom_index = emit.bin_file.decls.get(emit.decl_index).?;
308 try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{308 const atom = emit.bin_file.getAtomPtr(atom_index);
309 try atom.relocs.append(emit.bin_file.base.allocator, .{
309 .index = label,310 .index = label,
310 .offset = global_offset,311 .offset = global_offset,
311 .relocation_type = .R_WASM_GLOBAL_INDEX_LEB,312 .relocation_type = .R_WASM_GLOBAL_INDEX_LEB,
...@@ -361,7 +362,9 @@ fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -361,7 +362,9 @@ fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void {
361 try emit.code.appendSlice(&buf);362 try emit.code.appendSlice(&buf);
362363
363 if (label != 0) {364 if (label != 0) {
364 try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{365 const atom_index = emit.bin_file.decls.get(emit.decl_index).?;
366 const atom = emit.bin_file.getAtomPtr(atom_index);
367 try atom.relocs.append(emit.bin_file.base.allocator, .{
365 .offset = call_offset,368 .offset = call_offset,
366 .index = label,369 .index = label,
367 .relocation_type = .R_WASM_FUNCTION_INDEX_LEB,370 .relocation_type = .R_WASM_FUNCTION_INDEX_LEB,
...@@ -387,7 +390,9 @@ fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -387,7 +390,9 @@ fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void {
387 try emit.code.appendSlice(&buf);390 try emit.code.appendSlice(&buf);
388391
389 if (symbol_index != 0) {392 if (symbol_index != 0) {
390 try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{393 const atom_index = emit.bin_file.decls.get(emit.decl_index).?;
394 const atom = emit.bin_file.getAtomPtr(atom_index);
395 try atom.relocs.append(emit.bin_file.base.allocator, .{
391 .offset = index_offset,396 .offset = index_offset,
392 .index = symbol_index,397 .index = symbol_index,
393 .relocation_type = .R_WASM_TABLE_INDEX_SLEB,398 .relocation_type = .R_WASM_TABLE_INDEX_SLEB,
...@@ -399,7 +404,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -399,7 +404,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {
399 const extra_index = emit.mir.instructions.items(.data)[inst].payload;404 const extra_index = emit.mir.instructions.items(.data)[inst].payload;
400 const mem = emit.mir.extraData(Mir.Memory, extra_index).data;405 const mem = emit.mir.extraData(Mir.Memory, extra_index).data;
401 const mem_offset = emit.offset() + 1;406 const mem_offset = emit.offset() + 1;
402 const is_wasm32 = emit.bin_file.options.target.cpu.arch == .wasm32;407 const is_wasm32 = emit.bin_file.base.options.target.cpu.arch == .wasm32;
403 if (is_wasm32) {408 if (is_wasm32) {
404 try emit.code.append(std.wasm.opcode(.i32_const));409 try emit.code.append(std.wasm.opcode(.i32_const));
405 var buf: [5]u8 = undefined;410 var buf: [5]u8 = undefined;
...@@ -413,7 +418,9 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -413,7 +418,9 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {
413 }418 }
414419
415 if (mem.pointer != 0) {420 if (mem.pointer != 0) {
416 try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{421 const atom_index = emit.bin_file.decls.get(emit.decl_index).?;
422 const atom = emit.bin_file.getAtomPtr(atom_index);
423 try atom.relocs.append(emit.bin_file.base.allocator, .{
417 .offset = mem_offset,424 .offset = mem_offset,
418 .index = mem.pointer,425 .index = mem.pointer,
419 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64,426 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64,
src/link.zig+2-2
...@@ -267,7 +267,7 @@ pub const File = struct {...@@ -267,7 +267,7 @@ pub const File = struct {
267 macho: void,267 macho: void,
268 plan9: void,268 plan9: void,
269 c: void,269 c: void,
270 wasm: Wasm.DeclBlock,270 wasm: void,
271 spirv: void,271 spirv: void,
272 nvptx: void,272 nvptx: void,
273 };273 };
...@@ -289,7 +289,7 @@ pub const File = struct {...@@ -289,7 +289,7 @@ pub const File = struct {
289 macho: void,289 macho: void,
290 plan9: void,290 plan9: void,
291 c: void,291 c: void,
292 wasm: Wasm.Export,292 wasm: void,
293 spirv: void,293 spirv: void,
294 nvptx: void,294 nvptx: void,
295 };295 };
src/link/Dwarf.zig+13-12
...@@ -1099,7 +1099,7 @@ pub fn commitDeclState(...@@ -1099,7 +1099,7 @@ pub fn commitDeclState(
1099 },1099 },
1100 .wasm => {1100 .wasm => {
1101 const wasm_file = self.bin_file.cast(File.Wasm).?;1101 const wasm_file = self.bin_file.cast(File.Wasm).?;
1102 const debug_line = wasm_file.debug_line_atom.?.code;1102 const debug_line = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
1103 writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);1103 writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
1104 },1104 },
1105 else => unreachable,1105 else => unreachable,
...@@ -1177,7 +1177,7 @@ pub fn commitDeclState(...@@ -1177,7 +1177,7 @@ pub fn commitDeclState(
11771177
1178 .wasm => {1178 .wasm => {
1179 const wasm_file = self.bin_file.cast(File.Wasm).?;1179 const wasm_file = self.bin_file.cast(File.Wasm).?;
1180 const atom = wasm_file.debug_line_atom.?;1180 const atom = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?);
1181 const debug_line = &atom.code;1181 const debug_line = &atom.code;
1182 const segment_size = debug_line.items.len;1182 const segment_size = debug_line.items.len;
1183 if (needed_size != segment_size) {1183 if (needed_size != segment_size) {
...@@ -1345,7 +1345,8 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)...@@ -1345,7 +1345,8 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
1345 },1345 },
1346 .wasm => {1346 .wasm => {
1347 const wasm_file = self.bin_file.cast(File.Wasm).?;1347 const wasm_file = self.bin_file.cast(File.Wasm).?;
1348 const debug_info = &wasm_file.debug_info_atom.?.code;1348 const debug_info_index = wasm_file.debug_info_atom.?;
1349 const debug_info = &wasm_file.getAtomPtr(debug_info_index).code;
1349 try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false);1350 try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false);
1350 },1351 },
1351 else => unreachable,1352 else => unreachable,
...@@ -1441,7 +1442,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons...@@ -1441,7 +1442,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
1441 .wasm => {1442 .wasm => {
1442 const wasm_file = self.bin_file.cast(File.Wasm).?;1443 const wasm_file = self.bin_file.cast(File.Wasm).?;
1443 const info_atom = wasm_file.debug_info_atom.?;1444 const info_atom = wasm_file.debug_info_atom.?;
1444 const debug_info = &info_atom.code;1445 const debug_info = &wasm_file.getAtomPtr(info_atom).code;
1445 const segment_size = debug_info.items.len;1446 const segment_size = debug_info.items.len;
1446 if (needed_size != segment_size) {1447 if (needed_size != segment_size) {
1447 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});1448 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
...@@ -1504,8 +1505,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De...@@ -1504,8 +1505,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De
1504 .wasm => {1505 .wasm => {
1505 const wasm_file = self.bin_file.cast(File.Wasm).?;1506 const wasm_file = self.bin_file.cast(File.Wasm).?;
1506 const offset = atom.off + self.getRelocDbgLineOff();1507 const offset = atom.off + self.getRelocDbgLineOff();
1507 const atom_ = wasm_file.debug_line_atom.?;1508 const line_atom_index = wasm_file.debug_line_atom.?;
1508 mem.copy(u8, atom_.code.items[offset..], &data);1509 mem.copy(u8, wasm_file.getAtomPtr(line_atom_index).code.items[offset..], &data);
1509 },1510 },
1510 else => unreachable,1511 else => unreachable,
1511 }1512 }
...@@ -1722,7 +1723,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1722,7 +1723,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1722 },1723 },
1723 .wasm => {1724 .wasm => {
1724 const wasm_file = self.bin_file.cast(File.Wasm).?;1725 const wasm_file = self.bin_file.cast(File.Wasm).?;
1725 const debug_abbrev = &wasm_file.debug_abbrev_atom.?.code;1726 const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code;
1726 try debug_abbrev.resize(wasm_file.base.allocator, needed_size);1727 try debug_abbrev.resize(wasm_file.base.allocator, needed_size);
1727 mem.copy(u8, debug_abbrev.items, &abbrev_buf);1728 mem.copy(u8, debug_abbrev.items, &abbrev_buf);
1728 },1729 },
...@@ -1835,7 +1836,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u...@@ -1835,7 +1836,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
1835 },1836 },
1836 .wasm => {1837 .wasm => {
1837 const wasm_file = self.bin_file.cast(File.Wasm).?;1838 const wasm_file = self.bin_file.cast(File.Wasm).?;
1838 const debug_info = &wasm_file.debug_info_atom.?.code;1839 const debug_info = &wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code;
1839 try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);1840 try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);
1840 },1841 },
1841 else => unreachable,1842 else => unreachable,
...@@ -2156,7 +2157,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2156,7 +2157,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2156 },2157 },
2157 .wasm => {2158 .wasm => {
2158 const wasm_file = self.bin_file.cast(File.Wasm).?;2159 const wasm_file = self.bin_file.cast(File.Wasm).?;
2159 const debug_ranges = &wasm_file.debug_ranges_atom.?.code;2160 const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code;
2160 try debug_ranges.resize(wasm_file.base.allocator, needed_size);2161 try debug_ranges.resize(wasm_file.base.allocator, needed_size);
2161 mem.copy(u8, debug_ranges.items, di_buf.items);2162 mem.copy(u8, debug_ranges.items, di_buf.items);
2162 },2163 },
...@@ -2330,7 +2331,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2330,7 +2331,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2330 },2331 },
2331 .wasm => {2332 .wasm => {
2332 const wasm_file = self.bin_file.cast(File.Wasm).?;2333 const wasm_file = self.bin_file.cast(File.Wasm).?;
2333 const debug_line = &wasm_file.debug_line_atom.?.code;2334 const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
2334 mem.copy(u8, buffer, debug_line.items[first_fn.off..]);2335 mem.copy(u8, buffer, debug_line.items[first_fn.off..]);
2335 try debug_line.resize(self.allocator, debug_line.items.len + delta);2336 try debug_line.resize(self.allocator, debug_line.items.len + delta);
2336 mem.copy(u8, debug_line.items[first_fn.off + delta ..], buffer);2337 mem.copy(u8, debug_line.items[first_fn.off + delta ..], buffer);
...@@ -2381,7 +2382,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2381,7 +2382,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2381 },2382 },
2382 .wasm => {2383 .wasm => {
2383 const wasm_file = self.bin_file.cast(File.Wasm).?;2384 const wasm_file = self.bin_file.cast(File.Wasm).?;
2384 const debug_line = wasm_file.debug_line_atom.?.code;2385 const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
2385 writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);2386 writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);
2386 },2387 },
2387 else => unreachable,2388 else => unreachable,
...@@ -2526,7 +2527,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2526,7 +2527,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2526 },2527 },
2527 .wasm => {2528 .wasm => {
2528 const wasm_file = self.bin_file.cast(File.Wasm).?;2529 const wasm_file = self.bin_file.cast(File.Wasm).?;
2529 const debug_info = wasm_file.debug_info_atom.?.code;2530 const debug_info = wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code;
2530 mem.copy(u8, debug_info.items[atom.off + reloc.offset ..], &buf);2531 mem.copy(u8, debug_info.items[atom.off + reloc.offset ..], &buf);
2531 },2532 },
2532 else => unreachable,2533 else => unreachable,
src/link/Wasm.zig+275-247
...@@ -9,7 +9,7 @@ const fs = std.fs;...@@ -9,7 +9,7 @@ const fs = std.fs;
9const leb = std.leb;9const leb = std.leb;
10const log = std.log.scoped(.link);10const log = std.log.scoped(.link);
1111
12const Atom = @import("Wasm/Atom.zig");12pub const Atom = @import("Wasm/Atom.zig");
13const Dwarf = @import("Dwarf.zig");13const Dwarf = @import("Dwarf.zig");
14const Module = @import("../Module.zig");14const Module = @import("../Module.zig");
15const Compilation = @import("../Compilation.zig");15const Compilation = @import("../Compilation.zig");
...@@ -31,10 +31,7 @@ const Object = @import("Wasm/Object.zig");...@@ -31,10 +31,7 @@ const Object = @import("Wasm/Object.zig");
31const Archive = @import("Wasm/Archive.zig");31const Archive = @import("Wasm/Archive.zig");
32const types = @import("Wasm/types.zig");32const types = @import("Wasm/types.zig");
3333
34pub const base_tag = link.File.Tag.wasm;34pub const base_tag: link.File.Tag = .wasm;
35
36/// deprecated: Use `@import("Wasm/Atom.zig");`
37pub const DeclBlock = Atom;
3835
39base: link.File,36base: link.File,
40/// Output name of the file37/// Output name of the file
...@@ -47,18 +44,16 @@ llvm_object: ?*LlvmObject = null,...@@ -47,18 +44,16 @@ llvm_object: ?*LlvmObject = null,
47/// TODO: Allow setting this through a flag?44/// TODO: Allow setting this through a flag?
48host_name: []const u8 = "env",45host_name: []const u8 = "env",
49/// List of all `Decl` that are currently alive.46/// List of all `Decl` that are currently alive.
50/// This is ment for bookkeeping so we can safely cleanup all codegen memory47/// Each index maps to the corresponding `Atom.Index`.
51/// when calling `deinit`48decls: std.AutoHashMapUnmanaged(Module.Decl.Index, Atom.Index) = .{},
52decls: std.AutoHashMapUnmanaged(Module.Decl.Index, void) = .{},
53/// List of all symbols generated by Zig code.49/// List of all symbols generated by Zig code.
54symbols: std.ArrayListUnmanaged(Symbol) = .{},50symbols: std.ArrayListUnmanaged(Symbol) = .{},
55/// List of symbol indexes which are free to be used.51/// List of symbol indexes which are free to be used.
56symbols_free_list: std.ArrayListUnmanaged(u32) = .{},52symbols_free_list: std.ArrayListUnmanaged(u32) = .{},
57/// Maps atoms to their segment index53/// Maps atoms to their segment index
58atoms: std.AutoHashMapUnmanaged(u32, *Atom) = .{},54atoms: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{},
59/// Atoms managed and created by the linker. This contains atoms55/// List of all atoms.
60/// from object files, and not Atoms generated by a Decl.56managed_atoms: std.ArrayListUnmanaged(Atom) = .{},
61managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
62/// Represents the index into `segments` where the 'code' section57/// Represents the index into `segments` where the 'code' section
63/// lives.58/// lives.
64code_section_index: ?u32 = null,59code_section_index: ?u32 = null,
...@@ -148,7 +143,7 @@ undefs: std.StringArrayHashMapUnmanaged(SymbolLoc) = .{},...@@ -148,7 +143,7 @@ undefs: std.StringArrayHashMapUnmanaged(SymbolLoc) = .{},
148/// Maps a symbol's location to an atom. This can be used to find meta143/// Maps a symbol's location to an atom. This can be used to find meta
149/// data of a symbol, such as its size, or its offset to perform a relocation.144/// data of a symbol, such as its size, or its offset to perform a relocation.
150/// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped.145/// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped.
151symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, *Atom) = .{},146symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, Atom.Index) = .{},
152/// Maps a symbol's location to its export name, which may differ from the decl's name147/// Maps a symbol's location to its export name, which may differ from the decl's name
153/// which does the exporting.148/// which does the exporting.
154/// Note: The value represents the offset into the string table, rather than the actual string.149/// Note: The value represents the offset into the string table, rather than the actual string.
...@@ -165,14 +160,14 @@ error_table_symbol: ?u32 = null,...@@ -165,14 +160,14 @@ error_table_symbol: ?u32 = null,
165// unit contains Zig code. The lifetime of these atoms are extended160// unit contains Zig code. The lifetime of these atoms are extended
166// until the end of the compiler's lifetime. Meaning they're not freed161// until the end of the compiler's lifetime. Meaning they're not freed
167// during `flush()` in incremental-mode.162// during `flush()` in incremental-mode.
168debug_info_atom: ?*Atom = null,163debug_info_atom: ?Atom.Index = null,
169debug_line_atom: ?*Atom = null,164debug_line_atom: ?Atom.Index = null,
170debug_loc_atom: ?*Atom = null,165debug_loc_atom: ?Atom.Index = null,
171debug_ranges_atom: ?*Atom = null,166debug_ranges_atom: ?Atom.Index = null,
172debug_abbrev_atom: ?*Atom = null,167debug_abbrev_atom: ?Atom.Index = null,
173debug_str_atom: ?*Atom = null,168debug_str_atom: ?Atom.Index = null,
174debug_pubnames_atom: ?*Atom = null,169debug_pubnames_atom: ?Atom.Index = null,
175debug_pubtypes_atom: ?*Atom = null,170debug_pubtypes_atom: ?Atom.Index = null,
176171
177pub const Segment = struct {172pub const Segment = struct {
178 alignment: u32,173 alignment: u32,
...@@ -430,10 +425,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -430,10 +425,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
430 // at the end during `initializeCallCtorsFunction`.425 // at the end during `initializeCallCtorsFunction`.
431 }426 }
432427
433 if (!options.strip and options.module != null) {428 // if (!options.strip and options.module != null) {
434 wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, options.target);429 // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, options.target);
435 try wasm_bin.initDebugSections();430 // try wasm_bin.initDebugSections();
436 }431 // }
437432
438 return wasm_bin;433 return wasm_bin;
439}434}
...@@ -474,6 +469,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol...@@ -474,6 +469,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol
474 try wasm.globals.put(wasm.base.allocator, name_offset, loc);469 try wasm.globals.put(wasm.base.allocator, name_offset, loc);
475 return loc;470 return loc;
476}471}
472
477/// Initializes symbols and atoms for the debug sections473/// Initializes symbols and atoms for the debug sections
478/// Initialization is only done when compiling Zig code.474/// Initialization is only done when compiling Zig code.
479/// When Zig is invoked as a linker instead, the atoms475/// When Zig is invoked as a linker instead, the atoms
...@@ -516,6 +512,36 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {...@@ -516,6 +512,36 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
516 return true;512 return true;
517}513}
518514
515/// For a given `Module.Decl.Index` returns its corresponding `Atom.Index`.
516/// When the index was not found, a new `Atom` will be created, and its index will be returned.
517/// The newly created Atom is empty with default fields as specified by `Atom.empty`.
518pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: Module.Decl.Index) !Atom.Index {
519 const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);
520 if (!gop.found_existing) {
521 gop.value_ptr.* = try wasm.createAtom();
522 }
523 return gop.value_ptr.*;
524}
525
526/// Creates a new empty `Atom` and returns its `Atom.Index`
527fn createAtom(wasm: *Wasm) !Atom.Index {
528 const index = @intCast(Atom.Index, wasm.managed_atoms.items.len);
529 const atom = try wasm.managed_atoms.addOne(wasm.base.allocator);
530 atom.* = Atom.empty;
531 atom.sym_index = try wasm.allocateSymbol();
532 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, .{ .file = null, .index = atom.sym_index }, index);
533
534 return index;
535}
536
537pub inline fn getAtom(wasm: *const Wasm, index: Atom.Index) Atom {
538 return wasm.managed_atoms.items[index];
539}
540
541pub inline fn getAtomPtr(wasm: *Wasm, index: Atom.Index) *Atom {
542 return &wasm.managed_atoms.items[index];
543}
544
519/// Parses an archive file and will then parse each object file545/// Parses an archive file and will then parse each object file
520/// that was found in the archive file.546/// that was found in the archive file.
521/// Returns false when the file is not an archive file.547/// Returns false when the file is not an archive file.
...@@ -857,15 +883,16 @@ fn resolveLazySymbols(wasm: *Wasm) !void {...@@ -857,15 +883,16 @@ fn resolveLazySymbols(wasm: *Wasm) !void {
857 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);883 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
858 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.884 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.
859885
860 const atom = try wasm.base.allocator.create(Atom);886 // TODO: Can we use `createAtom` here while also re-using the symbol
861 errdefer wasm.base.allocator.destroy(atom);887 // from `createSyntheticSymbol`.
862 try wasm.managed_atoms.append(wasm.base.allocator, atom);888 const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len);
889 const atom = try wasm.managed_atoms.addOne(wasm.base.allocator);
863 atom.* = Atom.empty;890 atom.* = Atom.empty;
864 atom.sym_index = loc.index;891 atom.sym_index = loc.index;
865 atom.alignment = 1;892 atom.alignment = 1;
866893
867 try wasm.parseAtom(atom, .{ .data = .synthetic });894 try wasm.parseAtom(atom_index, .{ .data = .synthetic });
868 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom);895 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index);
869 }896 }
870897
871 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {898 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {
...@@ -873,15 +900,14 @@ fn resolveLazySymbols(wasm: *Wasm) !void {...@@ -873,15 +900,14 @@ fn resolveLazySymbols(wasm: *Wasm) !void {
873 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);900 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
874 _ = wasm.resolved_symbols.swapRemove(loc);901 _ = wasm.resolved_symbols.swapRemove(loc);
875902
876 const atom = try wasm.base.allocator.create(Atom);903 const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len);
877 errdefer wasm.base.allocator.destroy(atom);904 const atom = try wasm.managed_atoms.addOne(wasm.base.allocator);
878 try wasm.managed_atoms.append(wasm.base.allocator, atom);
879 atom.* = Atom.empty;905 atom.* = Atom.empty;
880 atom.sym_index = loc.index;906 atom.sym_index = loc.index;
881 atom.alignment = 1;907 atom.alignment = 1;
882908
883 try wasm.parseAtom(atom, .{ .data = .synthetic });909 try wasm.parseAtom(atom_index, .{ .data = .synthetic });
884 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom);910 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index);
885 }911 }
886}912}
887913
...@@ -920,16 +946,6 @@ pub fn deinit(wasm: *Wasm) void {...@@ -920,16 +946,6 @@ pub fn deinit(wasm: *Wasm) void {
920 if (wasm.llvm_object) |llvm_object| llvm_object.destroy(gpa);946 if (wasm.llvm_object) |llvm_object| llvm_object.destroy(gpa);
921 }947 }
922948
923 if (wasm.base.options.module) |mod| {
924 var decl_it = wasm.decls.keyIterator();
925 while (decl_it.next()) |decl_index_ptr| {
926 const decl = mod.declPtr(decl_index_ptr.*);
927 decl.link.wasm.deinit(gpa);
928 }
929 } else {
930 assert(wasm.decls.count() == 0);
931 }
932
933 for (wasm.func_types.items) |*func_type| {949 for (wasm.func_types.items) |*func_type| {
934 func_type.deinit(gpa);950 func_type.deinit(gpa);
935 }951 }
...@@ -954,9 +970,8 @@ pub fn deinit(wasm: *Wasm) void {...@@ -954,9 +970,8 @@ pub fn deinit(wasm: *Wasm) void {
954 wasm.symbol_atom.deinit(gpa);970 wasm.symbol_atom.deinit(gpa);
955 wasm.export_names.deinit(gpa);971 wasm.export_names.deinit(gpa);
956 wasm.atoms.deinit(gpa);972 wasm.atoms.deinit(gpa);
957 for (wasm.managed_atoms.items) |managed_atom| {973 for (wasm.managed_atoms.items) |*managed_atom| {
958 managed_atom.deinit(gpa);974 managed_atom.deinit(wasm);
959 gpa.destroy(managed_atom);
960 }975 }
961 wasm.managed_atoms.deinit(gpa);976 wasm.managed_atoms.deinit(gpa);
962 wasm.segments.deinit(gpa);977 wasm.segments.deinit(gpa);
...@@ -1014,18 +1029,24 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -1014,18 +1029,24 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
10141029
1015 const decl_index = func.owner_decl;1030 const decl_index = func.owner_decl;
1016 const decl = mod.declPtr(decl_index);1031 const decl = mod.declPtr(decl_index);
1017 const atom = &decl.link.wasm;1032 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
1018 try atom.ensureInitialized(wasm);1033 const atom = wasm.getAtomPtr(atom_index);
1019 const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);1034 atom.clear();
1020 if (gop.found_existing) {
1021 atom.clear();
1022 } else gop.value_ptr.* = {};
10231035
1024 var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl_index) else null;1036 // var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl_index) else null;
1025 defer if (decl_state) |*ds| ds.deinit();1037 // defer if (decl_state) |*ds| ds.deinit();
10261038
1027 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);1039 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
1028 defer code_writer.deinit();1040 defer code_writer.deinit();
1041 // const result = try codegen.generateFunction(
1042 // &wasm.base,
1043 // decl.srcLoc(),
1044 // func,
1045 // air,
1046 // liveness,
1047 // &code_writer,
1048 // if (decl_state) |*ds| .{ .dwarf = ds } else .none,
1049 // );
1029 const result = try codegen.generateFunction(1050 const result = try codegen.generateFunction(
1030 &wasm.base,1051 &wasm.base,
1031 decl.srcLoc(),1052 decl.srcLoc(),
...@@ -1033,7 +1054,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -1033,7 +1054,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
1033 air,1054 air,
1034 liveness,1055 liveness,
1035 &code_writer,1056 &code_writer,
1036 if (decl_state) |*ds| .{ .dwarf = ds } else .none,1057 .none,
1037 );1058 );
10381059
1039 const code = switch (result) {1060 const code = switch (result) {
...@@ -1045,19 +1066,19 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -1045,19 +1066,19 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
1045 },1066 },
1046 };1067 };
10471068
1048 if (wasm.dwarf) |*dwarf| {1069 // if (wasm.dwarf) |*dwarf| {
1049 try dwarf.commitDeclState(1070 // try dwarf.commitDeclState(
1050 mod,1071 // mod,
1051 decl_index,1072 // decl_index,
1052 // Actual value will be written after relocation.1073 // // Actual value will be written after relocation.
1053 // For Wasm, this is the offset relative to the code section1074 // // For Wasm, this is the offset relative to the code section
1054 // which isn't known until flush().1075 // // which isn't known until flush().
1055 0,1076 // 0,
1056 code.len,1077 // code.len,
1057 &decl_state.?,1078 // &decl_state.?,
1058 );1079 // );
1059 }1080 // }
1060 return wasm.finishUpdateDecl(decl, code);1081 return wasm.finishUpdateDecl(decl_index, code);
1061}1082}
10621083
1063// Generate code for the Decl, storing it in memory to be later written to1084// Generate code for the Decl, storing it in memory to be later written to
...@@ -1080,17 +1101,14 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1080,17 +1101,14 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1080 return;1101 return;
1081 }1102 }
10821103
1083 const atom = &decl.link.wasm;1104 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
1084 try atom.ensureInitialized(wasm);1105 const atom = wasm.getAtomPtr(atom_index);
1085 const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);1106 atom.clear();
1086 if (gop.found_existing) {
1087 atom.clear();
1088 } else gop.value_ptr.* = {};
10891107
1090 if (decl.isExtern()) {1108 if (decl.isExtern()) {
1091 const variable = decl.getVariable().?;1109 const variable = decl.getVariable().?;
1092 const name = mem.sliceTo(decl.name, 0);1110 const name = mem.sliceTo(decl.name, 0);
1093 return wasm.addOrUpdateImport(name, decl.link.wasm.sym_index, variable.lib_name, null);1111 return wasm.addOrUpdateImport(name, atom.sym_index, variable.lib_name, null);
1094 }1112 }
1095 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;1113 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
10961114
...@@ -1103,7 +1121,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1103,7 +1121,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1103 .{ .ty = decl.ty, .val = val },1121 .{ .ty = decl.ty, .val = val },
1104 &code_writer,1122 &code_writer,
1105 .none,1123 .none,
1106 .{ .parent_atom_index = decl.link.wasm.sym_index },1124 .{ .parent_atom_index = atom.sym_index },
1107 );1125 );
11081126
1109 const code = switch (res) {1127 const code = switch (res) {
...@@ -1115,7 +1133,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -1115,7 +1133,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1115 },1133 },
1116 };1134 };
11171135
1118 return wasm.finishUpdateDecl(decl, code);1136 return wasm.finishUpdateDecl(decl_index, code);
1119}1137}
11201138
1121pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {1139pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {
...@@ -1133,9 +1151,11 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I...@@ -1133,9 +1151,11 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I
1133 }1151 }
1134}1152}
11351153
1136fn finishUpdateDecl(wasm: *Wasm, decl: *Module.Decl, code: []const u8) !void {1154fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8) !void {
1137 const mod = wasm.base.options.module.?;1155 const mod = wasm.base.options.module.?;
1138 const atom: *Atom = &decl.link.wasm;1156 const decl = mod.declPtr(decl_index);
1157 const atom_index = wasm.decls.get(decl_index).?;
1158 const atom = wasm.getAtomPtr(atom_index);
1139 const symbol = &wasm.symbols.items[atom.sym_index];1159 const symbol = &wasm.symbols.items[atom.sym_index];
1140 const full_name = try decl.getFullyQualifiedName(mod);1160 const full_name = try decl.getFullyQualifiedName(mod);
1141 defer wasm.base.allocator.free(full_name);1161 defer wasm.base.allocator.free(full_name);
...@@ -1201,48 +1221,51 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In...@@ -1201,48 +1221,51 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
1201 const decl = mod.declPtr(decl_index);1221 const decl = mod.declPtr(decl_index);
12021222
1203 // Create and initialize a new local symbol and atom1223 // Create and initialize a new local symbol and atom
1204 const local_index = decl.link.wasm.locals.items.len;1224 const atom_index = try wasm.createAtom();
1225 const parent_atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
1226 const parent_atom = wasm.getAtomPtr(parent_atom_index);
1227 const local_index = parent_atom.locals.items.len;
1228 try parent_atom.locals.append(wasm.base.allocator, atom_index);
1205 const fqdn = try decl.getFullyQualifiedName(mod);1229 const fqdn = try decl.getFullyQualifiedName(mod);
1206 defer wasm.base.allocator.free(fqdn);1230 defer wasm.base.allocator.free(fqdn);
1207 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });1231 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });
1208 defer wasm.base.allocator.free(name);1232 defer wasm.base.allocator.free(name);
1209
1210 const atom = try decl.link.wasm.locals.addOne(wasm.base.allocator);
1211 atom.* = Atom.empty;
1212 try atom.ensureInitialized(wasm);
1213 atom.alignment = tv.ty.abiAlignment(wasm.base.options.target);
1214 wasm.symbols.items[atom.sym_index] = .{
1215 .name = try wasm.string_table.put(wasm.base.allocator, name),
1216 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
1217 .tag = .data,
1218 .index = undefined,
1219 };
1220
1221 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {});
1222
1223 var value_bytes = std.ArrayList(u8).init(wasm.base.allocator);1233 var value_bytes = std.ArrayList(u8).init(wasm.base.allocator);
1224 defer value_bytes.deinit();1234 defer value_bytes.deinit();
12251235
1226 const result = try codegen.generateSymbol(1236 const code = code: {
1227 &wasm.base,1237 const atom = wasm.getAtomPtr(atom_index);
1228 decl.srcLoc(),1238 atom.alignment = tv.ty.abiAlignment(wasm.base.options.target);
1229 tv,1239 wasm.symbols.items[atom.sym_index] = .{
1230 &value_bytes,1240 .name = try wasm.string_table.put(wasm.base.allocator, name),
1231 .none,1241 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
1232 .{1242 .tag = .data,
1233 .parent_atom_index = atom.sym_index,1243 .index = undefined,
1234 .addend = null,1244 };
1235 },1245 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {});
1236 );1246
1237 const code = switch (result) {1247 const result = try codegen.generateSymbol(
1238 .ok => value_bytes.items,1248 &wasm.base,
1239 .fail => |em| {1249 decl.srcLoc(),
1240 decl.analysis = .codegen_failure;1250 tv,
1241 try mod.failed_decls.put(mod.gpa, decl_index, em);1251 &value_bytes,
1242 return error.AnalysisFail;1252 .none,
1243 },1253 .{
1254 .parent_atom_index = atom.sym_index,
1255 .addend = null,
1256 },
1257 );
1258 break :code switch (result) {
1259 .ok => value_bytes.items,
1260 .fail => |em| {
1261 decl.analysis = .codegen_failure;
1262 try mod.failed_decls.put(mod.gpa, decl_index, em);
1263 return error.AnalysisFail;
1264 },
1265 };
1244 };1266 };
12451267
1268 const atom = wasm.getAtomPtr(atom_index);
1246 atom.size = @intCast(u32, code.len);1269 atom.size = @intCast(u32, code.len);
1247 try atom.code.appendSlice(wasm.base.allocator, code);1270 try atom.code.appendSlice(wasm.base.allocator, code);
1248 return atom.sym_index;1271 return atom.sym_index;
...@@ -1290,10 +1313,13 @@ pub fn getDeclVAddr(...@@ -1290,10 +1313,13 @@ pub fn getDeclVAddr(
1290) !u64 {1313) !u64 {
1291 const mod = wasm.base.options.module.?;1314 const mod = wasm.base.options.module.?;
1292 const decl = mod.declPtr(decl_index);1315 const decl = mod.declPtr(decl_index);
1293 try decl.link.wasm.ensureInitialized(wasm);1316
1294 const target_symbol_index = decl.link.wasm.sym_index;1317 const target_atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
1318 const target_symbol_index = wasm.getAtom(target_atom_index).sym_index;
1319
1295 assert(reloc_info.parent_atom_index != 0);1320 assert(reloc_info.parent_atom_index != 0);
1296 const atom = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;1321 const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
1322 const atom = wasm.getAtomPtr(atom_index);
1297 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;1323 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;
1298 if (decl.ty.zigTypeTag() == .Fn) {1324 if (decl.ty.zigTypeTag() == .Fn) {
1299 assert(reloc_info.addend == 0); // addend not allowed for function relocations1325 assert(reloc_info.addend == 0); // addend not allowed for function relocations
...@@ -1321,9 +1347,10 @@ pub fn getDeclVAddr(...@@ -1321,9 +1347,10 @@ pub fn getDeclVAddr(
1321 return target_symbol_index;1347 return target_symbol_index;
1322}1348}
13231349
1324pub fn deleteExport(wasm: *Wasm, exp: Export) void {1350pub fn deleteDeclExport(wasm: *Wasm, decl_index: Module.Decl.Index) void {
1325 if (wasm.llvm_object) |_| return;1351 if (wasm.llvm_object) |_| return;
1326 const sym_index = exp.sym_index orelse return;1352 const atom_index = wasm.decls.get(decl_index) orelse return;
1353 const sym_index = wasm.getAtom(atom_index).sym_index;
1327 const loc: SymbolLoc = .{ .file = null, .index = sym_index };1354 const loc: SymbolLoc = .{ .file = null, .index = sym_index };
1328 const symbol = loc.getSymbol(wasm);1355 const symbol = loc.getSymbol(wasm);
1329 const symbol_name = wasm.string_table.get(symbol.name);1356 const symbol_name = wasm.string_table.get(symbol.name);
...@@ -1349,7 +1376,8 @@ pub fn updateDeclExports(...@@ -1349,7 +1376,8 @@ pub fn updateDeclExports(
1349 }1376 }
13501377
1351 const decl = mod.declPtr(decl_index);1378 const decl = mod.declPtr(decl_index);
1352 if (decl.link.wasm.getSymbolIndex() == null) return; // unititialized1379 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
1380 const atom = wasm.getAtom(atom_index);
13531381
1354 for (exports) |exp| {1382 for (exports) |exp| {
1355 if (exp.options.section) |section| {1383 if (exp.options.section) |section| {
...@@ -1364,7 +1392,7 @@ pub fn updateDeclExports(...@@ -1364,7 +1392,7 @@ pub fn updateDeclExports(
13641392
1365 const export_name = try wasm.string_table.put(wasm.base.allocator, exp.options.name);1393 const export_name = try wasm.string_table.put(wasm.base.allocator, exp.options.name);
1366 if (wasm.globals.getPtr(export_name)) |existing_loc| {1394 if (wasm.globals.getPtr(export_name)) |existing_loc| {
1367 if (existing_loc.index == decl.link.wasm.sym_index) continue;1395 if (existing_loc.index == atom.sym_index) continue;
1368 const existing_sym: Symbol = existing_loc.getSymbol(wasm).*;1396 const existing_sym: Symbol = existing_loc.getSymbol(wasm).*;
13691397
1370 const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak;1398 const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak;
...@@ -1385,15 +1413,16 @@ pub fn updateDeclExports(...@@ -1385,15 +1413,16 @@ pub fn updateDeclExports(
1385 } else if (exp_is_weak) {1413 } else if (exp_is_weak) {
1386 continue; // to-be-exported symbol is weak, so we keep the existing symbol1414 continue; // to-be-exported symbol is weak, so we keep the existing symbol
1387 } else {1415 } else {
1388 existing_loc.index = decl.link.wasm.sym_index;1416 // TODO: Revisit this, why was this needed?
1417 existing_loc.index = atom.sym_index;
1389 existing_loc.file = null;1418 existing_loc.file = null;
1390 exp.link.wasm.sym_index = existing_loc.index;1419 // exp.link.wasm.sym_index = existing_loc.index;
1391 }1420 }
1392 }1421 }
13931422
1394 const exported_decl = mod.declPtr(exp.exported_decl);1423 const exported_atom_index = try wasm.getOrCreateAtomForDecl(exp.exported_decl);
1395 const sym_index = exported_decl.link.wasm.sym_index;1424 const exported_atom = wasm.getAtom(exported_atom_index);
1396 const sym_loc = exported_decl.link.wasm.symbolLoc();1425 const sym_loc = exported_atom.symbolLoc();
1397 const symbol = sym_loc.getSymbol(wasm);1426 const symbol = sym_loc.getSymbol(wasm);
1398 switch (exp.options.linkage) {1427 switch (exp.options.linkage) {
1399 .Internal => {1428 .Internal => {
...@@ -1429,7 +1458,6 @@ pub fn updateDeclExports(...@@ -1429,7 +1458,6 @@ pub fn updateDeclExports(
1429 // if the symbol was previously undefined, remove it as an import1458 // if the symbol was previously undefined, remove it as an import
1430 _ = wasm.imports.remove(sym_loc);1459 _ = wasm.imports.remove(sym_loc);
1431 _ = wasm.undefs.swapRemove(exp.options.name);1460 _ = wasm.undefs.swapRemove(exp.options.name);
1432 exp.link.wasm.sym_index = sym_index;
1433 }1461 }
1434}1462}
14351463
...@@ -1439,11 +1467,13 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {...@@ -1439,11 +1467,13 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
1439 }1467 }
1440 const mod = wasm.base.options.module.?;1468 const mod = wasm.base.options.module.?;
1441 const decl = mod.declPtr(decl_index);1469 const decl = mod.declPtr(decl_index);
1442 const atom = &decl.link.wasm;1470 const atom_index = wasm.decls.get(decl_index).?;
1471 const atom = wasm.getAtomPtr(atom_index);
1443 wasm.symbols_free_list.append(wasm.base.allocator, atom.sym_index) catch {};1472 wasm.symbols_free_list.append(wasm.base.allocator, atom.sym_index) catch {};
1444 _ = wasm.decls.remove(decl_index);1473 _ = wasm.decls.remove(decl_index);
1445 wasm.symbols.items[atom.sym_index].tag = .dead;1474 wasm.symbols.items[atom.sym_index].tag = .dead;
1446 for (atom.locals.items) |local_atom| {1475 for (atom.locals.items) |local_atom_index| {
1476 const local_atom = wasm.getAtom(local_atom_index);
1447 const local_symbol = &wasm.symbols.items[local_atom.sym_index];1477 const local_symbol = &wasm.symbols.items[local_atom.sym_index];
1448 local_symbol.tag = .dead; // also for any local symbol1478 local_symbol.tag = .dead; // also for any local symbol
1449 wasm.symbols_free_list.append(wasm.base.allocator, local_atom.sym_index) catch {};1479 wasm.symbols_free_list.append(wasm.base.allocator, local_atom.sym_index) catch {};
...@@ -1461,7 +1491,16 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {...@@ -1461,7 +1491,16 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
1461 // dwarf.freeDecl(decl_index);1491 // dwarf.freeDecl(decl_index);
1462 // }1492 // }
14631493
1464 atom.deinit(wasm.base.allocator);1494 if (atom.next) |next_atom_index| {
1495 const next_atom = wasm.getAtomPtr(next_atom_index);
1496 next_atom.prev = atom.prev;
1497 atom.next = null;
1498 }
1499 if (atom.prev) |prev_index| {
1500 const prev_atom = wasm.getAtomPtr(prev_index);
1501 prev_atom.next = atom.next;
1502 atom.prev = null;
1503 }
1465}1504}
14661505
1467/// Appends a new entry to the indirect function table1506/// Appends a new entry to the indirect function table
...@@ -1583,7 +1622,8 @@ const Kind = union(enum) {...@@ -1583,7 +1622,8 @@ const Kind = union(enum) {
1583};1622};
15841623
1585/// Parses an Atom and inserts its metadata into the corresponding sections.1624/// Parses an Atom and inserts its metadata into the corresponding sections.
1586fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void {1625fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
1626 const atom = wasm.getAtomPtr(atom_index);
1587 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);1627 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);
1588 const final_index: u32 = switch (kind) {1628 const final_index: u32 = switch (kind) {
1589 .function => |fn_data| result: {1629 .function => |fn_data| result: {
...@@ -1658,18 +1698,20 @@ fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void {...@@ -1658,18 +1698,20 @@ fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void {
1658 const segment: *Segment = &wasm.segments.items[final_index];1698 const segment: *Segment = &wasm.segments.items[final_index];
1659 segment.alignment = std.math.max(segment.alignment, atom.alignment);1699 segment.alignment = std.math.max(segment.alignment, atom.alignment);
16601700
1661 try wasm.appendAtomAtIndex(final_index, atom);1701 try wasm.appendAtomAtIndex(final_index, atom_index);
1662}1702}
16631703
1664/// From a given index, append the given `Atom` at the back of the linked list.1704/// From a given index, append the given `Atom` at the back of the linked list.
1665/// Simply inserts it into the map of atoms when it doesn't exist yet.1705/// Simply inserts it into the map of atoms when it doesn't exist yet.
1666pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom: *Atom) !void {1706pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void {
1667 if (wasm.atoms.getPtr(index)) |last| {1707 const atom = wasm.getAtomPtr(atom_index);
1668 last.*.next = atom;1708 if (wasm.atoms.getPtr(index)) |last_index_ptr| {
1669 atom.prev = last.*;1709 const last = wasm.getAtomPtr(last_index_ptr.*);
1670 last.* = atom;1710 last.*.next = atom_index;
1711 atom.prev = last_index_ptr.*;
1712 last_index_ptr.* = atom_index;
1671 } else {1713 } else {
1672 try wasm.atoms.putNoClobber(wasm.base.allocator, index, atom);1714 try wasm.atoms.putNoClobber(wasm.base.allocator, index, atom_index);
1673 }1715 }
1674}1716}
16751717
...@@ -1679,16 +1721,17 @@ fn allocateDebugAtoms(wasm: *Wasm) !void {...@@ -1679,16 +1721,17 @@ fn allocateDebugAtoms(wasm: *Wasm) !void {
1679 if (wasm.dwarf == null) return;1721 if (wasm.dwarf == null) return;
16801722
1681 const allocAtom = struct {1723 const allocAtom = struct {
1682 fn f(bin: *Wasm, maybe_index: *?u32, atom: *Atom) !void {1724 fn f(bin: *Wasm, maybe_index: *?u32, atom_index: Atom.Index) !void {
1683 const index = maybe_index.* orelse idx: {1725 const index = maybe_index.* orelse idx: {
1684 const index = @intCast(u32, bin.segments.items.len);1726 const index = @intCast(u32, bin.segments.items.len);
1685 try bin.appendDummySegment();1727 try bin.appendDummySegment();
1686 maybe_index.* = index;1728 maybe_index.* = index;
1687 break :idx index;1729 break :idx index;
1688 };1730 };
1731 const atom = bin.getAtomPtr(atom_index);
1689 atom.size = @intCast(u32, atom.code.items.len);1732 atom.size = @intCast(u32, atom.code.items.len);
1690 bin.symbols.items[atom.sym_index].index = index;1733 bin.symbols.items[atom.sym_index].index = index;
1691 try bin.appendAtomAtIndex(index, atom);1734 try bin.appendAtomAtIndex(index, atom_index);
1692 }1735 }
1693 }.f;1736 }.f;
16941737
...@@ -1710,15 +1753,16 @@ fn allocateAtoms(wasm: *Wasm) !void {...@@ -1710,15 +1753,16 @@ fn allocateAtoms(wasm: *Wasm) !void {
1710 var it = wasm.atoms.iterator();1753 var it = wasm.atoms.iterator();
1711 while (it.next()) |entry| {1754 while (it.next()) |entry| {
1712 const segment = &wasm.segments.items[entry.key_ptr.*];1755 const segment = &wasm.segments.items[entry.key_ptr.*];
1713 var atom: *Atom = entry.value_ptr.*.getFirst();1756 var atom_index = entry.value_ptr.*;
1714 var offset: u32 = 0;1757 var offset: u32 = 0;
1715 while (true) {1758 while (true) {
1759 const atom = wasm.getAtomPtr(atom_index);
1716 const symbol_loc = atom.symbolLoc();1760 const symbol_loc = atom.symbolLoc();
1717 if (wasm.code_section_index) |index| {1761 if (wasm.code_section_index) |index| {
1718 if (index == entry.key_ptr.*) {1762 if (index == entry.key_ptr.*) {
1719 if (!wasm.resolved_symbols.contains(symbol_loc)) {1763 if (!wasm.resolved_symbols.contains(symbol_loc)) {
1720 // only allocate resolved function body's.1764 // only allocate resolved function body's.
1721 atom = atom.next orelse break;1765 atom_index = atom.prev orelse break;
1722 continue;1766 continue;
1723 }1767 }
1724 }1768 }
...@@ -1732,8 +1776,7 @@ fn allocateAtoms(wasm: *Wasm) !void {...@@ -1732,8 +1776,7 @@ fn allocateAtoms(wasm: *Wasm) !void {
1732 atom.size,1776 atom.size,
1733 });1777 });
1734 offset += atom.size;1778 offset += atom.size;
1735 try wasm.symbol_atom.put(wasm.base.allocator, symbol_loc, atom); // Update atom pointers1779 atom_index = atom.prev orelse break;
1736 atom = atom.next orelse break;
1737 }1780 }
1738 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);1781 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);
1739 }1782 }
...@@ -1867,8 +1910,8 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void {...@@ -1867,8 +1910,8 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void {
1867 symbol.index = func_index;1910 symbol.index = func_index;
18681911
1869 // create the atom that will be output into the final binary1912 // create the atom that will be output into the final binary
1870 const atom = try wasm.base.allocator.create(Atom);1913 const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len);
1871 errdefer wasm.base.allocator.destroy(atom);1914 const atom = try wasm.managed_atoms.addOne(wasm.base.allocator);
1872 atom.* = .{1915 atom.* = .{
1873 .size = @intCast(u32, function_body.items.len),1916 .size = @intCast(u32, function_body.items.len),
1874 .offset = 0,1917 .offset = 0,
...@@ -1879,13 +1922,13 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void {...@@ -1879,13 +1922,13 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void {
1879 .prev = null,1922 .prev = null,
1880 .code = function_body.moveToUnmanaged(),1923 .code = function_body.moveToUnmanaged(),
1881 };1924 };
1882 try wasm.managed_atoms.append(wasm.base.allocator, atom);1925 try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom_index);
1883 try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom);1926 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index);
1884 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom);
18851927
1886 // `allocateAtoms` has already been called, set the atom's offset manually.1928 // `allocateAtoms` has already been called, set the atom's offset manually.
1887 // This is fine to do manually as we insert the atom at the very end.1929 // This is fine to do manually as we insert the atom at the very end.
1888 atom.offset = atom.prev.?.offset + atom.prev.?.size;1930 const prev_atom = wasm.getAtom(atom.prev.?);
1931 atom.offset = prev_atom.offset + prev_atom.size;
1889}1932}
18901933
1891fn setupImports(wasm: *Wasm) !void {1934fn setupImports(wasm: *Wasm) !void {
...@@ -2088,7 +2131,8 @@ fn setupExports(wasm: *Wasm) !void {...@@ -2088,7 +2131,8 @@ fn setupExports(wasm: *Wasm) !void {
2088 break :blk try wasm.string_table.put(wasm.base.allocator, sym_name);2131 break :blk try wasm.string_table.put(wasm.base.allocator, sym_name);
2089 };2132 };
2090 const exp: types.Export = if (symbol.tag == .data) exp: {2133 const exp: types.Export = if (symbol.tag == .data) exp: {
2091 const atom = wasm.symbol_atom.get(sym_loc).?;2134 const atom_index = wasm.symbol_atom.get(sym_loc).?;
2135 const atom = wasm.getAtom(atom_index);
2092 const va = atom.getVA(wasm, symbol);2136 const va = atom.getVA(wasm, symbol);
2093 const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len);2137 const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len);
2094 try wasm.wasm_globals.append(wasm.base.allocator, .{2138 try wasm.wasm_globals.append(wasm.base.allocator, .{
...@@ -2193,7 +2237,8 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -2193,7 +2237,8 @@ fn setupMemory(wasm: *Wasm) !void {
2193 const segment_index = wasm.data_segments.get(".synthetic").?;2237 const segment_index = wasm.data_segments.get(".synthetic").?;
2194 const segment = &wasm.segments.items[segment_index];2238 const segment = &wasm.segments.items[segment_index];
2195 segment.offset = 0; // for simplicity we store the entire VA into atom's offset.2239 segment.offset = 0; // for simplicity we store the entire VA into atom's offset.
2196 const atom = wasm.symbol_atom.get(loc).?;2240 const atom_index = wasm.symbol_atom.get(loc).?;
2241 const atom = wasm.getAtomPtr(atom_index);
2197 atom.offset = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment));2242 atom.offset = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment));
2198 }2243 }
21992244
...@@ -2226,7 +2271,8 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -2226,7 +2271,8 @@ fn setupMemory(wasm: *Wasm) !void {
2226 const segment_index = wasm.data_segments.get(".synthetic").?;2271 const segment_index = wasm.data_segments.get(".synthetic").?;
2227 const segment = &wasm.segments.items[segment_index];2272 const segment = &wasm.segments.items[segment_index];
2228 segment.offset = 0;2273 segment.offset = 0;
2229 const atom = wasm.symbol_atom.get(loc).?;2274 const atom_index = wasm.symbol_atom.get(loc).?;
2275 const atom = wasm.getAtomPtr(atom_index);
2230 atom.offset = @intCast(u32, memory_ptr);2276 atom.offset = @intCast(u32, memory_ptr);
2231 }2277 }
22322278
...@@ -2352,15 +2398,14 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {...@@ -2352,15 +2398,14 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
2352 // and then return said symbol's index. The final table will be populated2398 // and then return said symbol's index. The final table will be populated
2353 // during `flush` when we know all possible error names.2399 // during `flush` when we know all possible error names.
23542400
2355 // As sym_index '0' is reserved, we use it for our stack pointer symbol2401 const atom_index = try wasm.createAtom();
2356 const symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: {2402 const atom = wasm.getAtomPtr(atom_index);
2357 const index = @intCast(u32, wasm.symbols.items.len);2403 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
2358 _ = try wasm.symbols.addOne(wasm.base.allocator);2404 atom.alignment = slice_ty.abiAlignment(wasm.base.options.target);
2359 break :blk index;2405 const sym_index = atom.sym_index;
2360 };
23612406
2362 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");2407 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");
2363 const symbol = &wasm.symbols.items[symbol_index];2408 const symbol = &wasm.symbols.items[sym_index];
2364 symbol.* = .{2409 symbol.* = .{
2365 .name = sym_name,2410 .name = sym_name,
2366 .tag = .data,2411 .tag = .data,
...@@ -2369,20 +2414,11 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {...@@ -2369,20 +2414,11 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
2369 };2414 };
2370 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);2415 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
23712416
2372 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);2417 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
23732418
2374 const atom = try wasm.base.allocator.create(Atom);2419 log.debug("Error name table was created with symbol index: ({d})", .{sym_index});
2375 atom.* = Atom.empty;2420 wasm.error_table_symbol = sym_index;
2376 atom.sym_index = symbol_index;2421 return sym_index;
2377 atom.alignment = slice_ty.abiAlignment(wasm.base.options.target);
2378 try wasm.managed_atoms.append(wasm.base.allocator, atom);
2379 const loc = atom.symbolLoc();
2380 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
2381 try wasm.symbol_atom.put(wasm.base.allocator, loc, atom);
2382
2383 log.debug("Error name table was created with symbol index: ({d})", .{symbol_index});
2384 wasm.error_table_symbol = symbol_index;
2385 return symbol_index;
2386}2422}
23872423
2388/// Populates the error name table, when `error_table_symbol` is not null.2424/// Populates the error name table, when `error_table_symbol` is not null.
...@@ -2391,22 +2427,17 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {...@@ -2391,22 +2427,17 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
2391/// The table is what is being pointed to within the runtime bodies that are generated.2427/// The table is what is being pointed to within the runtime bodies that are generated.
2392fn populateErrorNameTable(wasm: *Wasm) !void {2428fn populateErrorNameTable(wasm: *Wasm) !void {
2393 const symbol_index = wasm.error_table_symbol orelse return;2429 const symbol_index = wasm.error_table_symbol orelse return;
2394 const atom: *Atom = wasm.symbol_atom.get(.{ .file = null, .index = symbol_index }).?;2430 const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = symbol_index }).?;
2431 const atom = wasm.getAtomPtr(atom_index);
2432
2395 // Rather than creating a symbol for each individual error name,2433 // Rather than creating a symbol for each individual error name,
2396 // we create a symbol for the entire region of error names. We then calculate2434 // we create a symbol for the entire region of error names. We then calculate
2397 // the pointers into the list using addends which are appended to the relocation.2435 // the pointers into the list using addends which are appended to the relocation.
2398 const names_atom = try wasm.base.allocator.create(Atom);2436 const names_atom_index = try wasm.createAtom();
2399 names_atom.* = Atom.empty;2437 const names_atom = wasm.getAtomPtr(names_atom_index);
2400 try wasm.managed_atoms.append(wasm.base.allocator, names_atom);
2401 const names_symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: {
2402 const index = @intCast(u32, wasm.symbols.items.len);
2403 _ = try wasm.symbols.addOne(wasm.base.allocator);
2404 break :blk index;
2405 };
2406 names_atom.sym_index = names_symbol_index;
2407 names_atom.alignment = 1;2438 names_atom.alignment = 1;
2408 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_names");2439 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_names");
2409 const names_symbol = &wasm.symbols.items[names_symbol_index];2440 const names_symbol = &wasm.symbols.items[names_atom.sym_index];
2410 names_symbol.* = .{2441 names_symbol.* = .{
2411 .name = sym_name,2442 .name = sym_name,
2412 .tag = .data,2443 .tag = .data,
...@@ -2430,7 +2461,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {...@@ -2430,7 +2461,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
2430 try atom.code.writer(wasm.base.allocator).writeIntLittle(u32, len - 1);2461 try atom.code.writer(wasm.base.allocator).writeIntLittle(u32, len - 1);
2431 // create relocation to the error name2462 // create relocation to the error name
2432 try atom.relocs.append(wasm.base.allocator, .{2463 try atom.relocs.append(wasm.base.allocator, .{
2433 .index = names_symbol_index,2464 .index = names_atom.sym_index,
2434 .relocation_type = .R_WASM_MEMORY_ADDR_I32,2465 .relocation_type = .R_WASM_MEMORY_ADDR_I32,
2435 .offset = offset,2466 .offset = offset,
2436 .addend = @intCast(i32, addend),2467 .addend = @intCast(i32, addend),
...@@ -2449,61 +2480,53 @@ fn populateErrorNameTable(wasm: *Wasm) !void {...@@ -2449,61 +2480,53 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
24492480
2450 const name_loc = names_atom.symbolLoc();2481 const name_loc = names_atom.symbolLoc();
2451 try wasm.resolved_symbols.put(wasm.base.allocator, name_loc, {});2482 try wasm.resolved_symbols.put(wasm.base.allocator, name_loc, {});
2452 try wasm.symbol_atom.put(wasm.base.allocator, name_loc, names_atom);2483 try wasm.symbol_atom.put(wasm.base.allocator, name_loc, names_atom_index);
24532484
2454 // link the atoms with the rest of the binary so they can be allocated2485 // link the atoms with the rest of the binary so they can be allocated
2455 // and relocations will be performed.2486 // and relocations will be performed.
2456 try wasm.parseAtom(atom, .{ .data = .read_only });2487 try wasm.parseAtom(atom_index, .{ .data = .read_only });
2457 try wasm.parseAtom(names_atom, .{ .data = .read_only });2488 try wasm.parseAtom(names_atom_index, .{ .data = .read_only });
2458}2489}
24592490
2460/// From a given index variable, creates a new debug section.2491/// From a given index variable, creates a new debug section.
2461/// This initializes the index, appends a new segment,2492/// This initializes the index, appends a new segment,
2462/// and finally, creates a managed `Atom`.2493/// and finally, creates a managed `Atom`.
2463pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !*Atom {2494pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !Atom.Index {
2464 const new_index = @intCast(u32, wasm.segments.items.len);2495 const new_index = @intCast(u32, wasm.segments.items.len);
2465 index.* = new_index;2496 index.* = new_index;
2466 try wasm.appendDummySegment();2497 try wasm.appendDummySegment();
24672498
2468 const sym_index = wasm.symbols_free_list.popOrNull() orelse idx: {2499 const atom_index = try wasm.createAtom();
2469 const tmp_index = @intCast(u32, wasm.symbols.items.len);2500 const atom = wasm.getAtomPtr(atom_index);
2470 _ = try wasm.symbols.addOne(wasm.base.allocator);2501 wasm.symbols.items[atom.sym_index] = .{
2471 break :idx tmp_index;
2472 };
2473 wasm.symbols.items[sym_index] = .{
2474 .tag = .section,2502 .tag = .section,
2475 .name = try wasm.string_table.put(wasm.base.allocator, name),2503 .name = try wasm.string_table.put(wasm.base.allocator, name),
2476 .index = 0,2504 .index = 0,
2477 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),2505 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
2478 };2506 };
24792507
2480 const atom = try wasm.base.allocator.create(Atom);
2481 atom.* = Atom.empty;
2482 atom.alignment = 1; // debug sections are always 1-byte-aligned2508 atom.alignment = 1; // debug sections are always 1-byte-aligned
2483 atom.sym_index = sym_index;2509 return atom_index;
2484 try wasm.managed_atoms.append(wasm.base.allocator, atom);
2485 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom);
2486 return atom;
2487}2510}
24882511
2489fn resetState(wasm: *Wasm) void {2512fn resetState(wasm: *Wasm) void {
2490 for (wasm.segment_info.values()) |segment_info| {2513 for (wasm.segment_info.values()) |segment_info| {
2491 wasm.base.allocator.free(segment_info.name);2514 wasm.base.allocator.free(segment_info.name);
2492 }2515 }
2493 if (wasm.base.options.module) |mod| {2516
2494 var decl_it = wasm.decls.keyIterator();2517 var atom_it = wasm.decls.valueIterator();
2495 while (decl_it.next()) |decl_index_ptr| {2518 while (atom_it.next()) |atom_index| {
2496 const decl = mod.declPtr(decl_index_ptr.*);2519 const atom = wasm.getAtomPtr(atom_index.*);
2497 const atom = &decl.link.wasm;2520 atom.next = null;
2498 atom.next = null;2521 atom.prev = null;
2499 atom.prev = null;2522
25002523 for (atom.locals.items) |local_atom_index| {
2501 for (atom.locals.items) |*local_atom| {2524 const local_atom = wasm.getAtomPtr(local_atom_index);
2502 local_atom.next = null;2525 local_atom.next = null;
2503 local_atom.prev = null;2526 local_atom.prev = null;
2504 }
2505 }2527 }
2506 }2528 }
2529
2507 wasm.functions.clearRetainingCapacity();2530 wasm.functions.clearRetainingCapacity();
2508 wasm.exports.clearRetainingCapacity();2531 wasm.exports.clearRetainingCapacity();
2509 wasm.segments.clearRetainingCapacity();2532 wasm.segments.clearRetainingCapacity();
...@@ -2800,28 +2823,29 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2800,28 +2823,29 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2800 try wasm.setupStart();2823 try wasm.setupStart();
2801 try wasm.setupImports();2824 try wasm.setupImports();
2802 if (wasm.base.options.module) |mod| {2825 if (wasm.base.options.module) |mod| {
2803 var decl_it = wasm.decls.keyIterator();2826 var decl_it = wasm.decls.iterator();
2804 while (decl_it.next()) |decl_index_ptr| {2827 while (decl_it.next()) |entry| {
2805 const decl = mod.declPtr(decl_index_ptr.*);2828 const decl = mod.declPtr(entry.key_ptr.*);
2806 if (decl.isExtern()) continue;2829 if (decl.isExtern()) continue;
2807 const atom = &decl.*.link.wasm;2830 const atom_index = entry.value_ptr.*;
2808 if (decl.ty.zigTypeTag() == .Fn) {2831 if (decl.ty.zigTypeTag() == .Fn) {
2809 try wasm.parseAtom(atom, .{ .function = decl.fn_link.wasm });2832 try wasm.parseAtom(atom_index, .{ .function = decl.fn_link.wasm });
2810 } else if (decl.getVariable()) |variable| {2833 } else if (decl.getVariable()) |variable| {
2811 if (!variable.is_mutable) {2834 if (!variable.is_mutable) {
2812 try wasm.parseAtom(atom, .{ .data = .read_only });2835 try wasm.parseAtom(atom_index, .{ .data = .read_only });
2813 } else if (variable.init.isUndefDeep()) {2836 } else if (variable.init.isUndefDeep()) {
2814 try wasm.parseAtom(atom, .{ .data = .uninitialized });2837 try wasm.parseAtom(atom_index, .{ .data = .uninitialized });
2815 } else {2838 } else {
2816 try wasm.parseAtom(atom, .{ .data = .initialized });2839 try wasm.parseAtom(atom_index, .{ .data = .initialized });
2817 }2840 }
2818 } else {2841 } else {
2819 try wasm.parseAtom(atom, .{ .data = .read_only });2842 try wasm.parseAtom(atom_index, .{ .data = .read_only });
2820 }2843 }
28212844
2822 // also parse atoms for a decl's locals2845 // also parse atoms for a decl's locals
2823 for (atom.locals.items) |*local_atom| {2846 const atom = wasm.getAtomPtr(atom_index);
2824 try wasm.parseAtom(local_atom, .{ .data = .read_only });2847 for (atom.locals.items) |local_atom_index| {
2848 try wasm.parseAtom(local_atom_index, .{ .data = .read_only });
2825 }2849 }
2826 }2850 }
28272851
...@@ -3066,20 +3090,22 @@ fn writeToFile(...@@ -3066,20 +3090,22 @@ fn writeToFile(
3066 var code_section_size: u32 = 0;3090 var code_section_size: u32 = 0;
3067 if (wasm.code_section_index) |code_index| {3091 if (wasm.code_section_index) |code_index| {
3068 const header_offset = try reserveVecSectionHeader(&binary_bytes);3092 const header_offset = try reserveVecSectionHeader(&binary_bytes);
3069 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();3093 var atom_index = wasm.atoms.get(code_index).?;
30703094
3071 // The code section must be sorted in line with the function order.3095 // The code section must be sorted in line with the function order.
3072 var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count());3096 var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count());
3073 defer sorted_atoms.deinit();3097 defer sorted_atoms.deinit();
30743098
3075 while (true) {3099 while (true) {
3100 var atom = wasm.getAtomPtr(atom_index);
3076 if (wasm.resolved_symbols.contains(atom.symbolLoc())) {3101 if (wasm.resolved_symbols.contains(atom.symbolLoc())) {
3077 if (!is_obj) {3102 if (!is_obj) {
3078 atom.resolveRelocs(wasm);3103 atom.resolveRelocs(wasm);
3079 }3104 }
3080 sorted_atoms.appendAssumeCapacity(atom);3105 sorted_atoms.appendAssumeCapacity(atom);
3081 }3106 }
3082 atom = atom.next orelse break;3107 // atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
3108 atom_index = atom.prev orelse break;
3083 }3109 }
30843110
3085 const atom_sort_fn = struct {3111 const atom_sort_fn = struct {
...@@ -3119,11 +3145,11 @@ fn writeToFile(...@@ -3119,11 +3145,11 @@ fn writeToFile(
3119 // do not output 'bss' section unless we import memory and therefore3145 // do not output 'bss' section unless we import memory and therefore
3120 // want to guarantee the data is zero initialized3146 // want to guarantee the data is zero initialized
3121 if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue;3147 if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue;
3122 const atom_index = entry.value_ptr.*;3148 const segment_index = entry.value_ptr.*;
3123 const segment = wasm.segments.items[atom_index];3149 const segment = wasm.segments.items[segment_index];
3124 if (segment.size == 0) continue; // do not emit empty segments3150 if (segment.size == 0) continue; // do not emit empty segments
3125 segment_count += 1;3151 segment_count += 1;
3126 var atom: *Atom = wasm.atoms.getPtr(atom_index).?.*.getFirst();3152 var atom_index = wasm.atoms.get(segment_index).?;
31273153
3128 // flag and index to memory section (currently, there can only be 1 memory section in wasm)3154 // flag and index to memory section (currently, there can only be 1 memory section in wasm)
3129 try leb.writeULEB128(binary_writer, @as(u32, 0));3155 try leb.writeULEB128(binary_writer, @as(u32, 0));
...@@ -3134,6 +3160,7 @@ fn writeToFile(...@@ -3134,6 +3160,7 @@ fn writeToFile(
3134 // fill in the offset table and the data segments3160 // fill in the offset table and the data segments
3135 var current_offset: u32 = 0;3161 var current_offset: u32 = 0;
3136 while (true) {3162 while (true) {
3163 const atom = wasm.getAtomPtr(atom_index);
3137 if (!is_obj) {3164 if (!is_obj) {
3138 atom.resolveRelocs(wasm);3165 atom.resolveRelocs(wasm);
3139 }3166 }
...@@ -3149,8 +3176,8 @@ fn writeToFile(...@@ -3149,8 +3176,8 @@ fn writeToFile(
3149 try binary_writer.writeAll(atom.code.items);3176 try binary_writer.writeAll(atom.code.items);
31503177
3151 current_offset += atom.size;3178 current_offset += atom.size;
3152 if (atom.next) |next| {3179 if (atom.prev) |prev| {
3153 atom = next;3180 atom_index = prev;
3154 } else {3181 } else {
3155 // also pad with zeroes when last atom to ensure3182 // also pad with zeroes when last atom to ensure
3156 // segments are aligned.3183 // segments are aligned.
...@@ -3192,15 +3219,15 @@ fn writeToFile(...@@ -3192,15 +3219,15 @@ fn writeToFile(
3192 }3219 }
31933220
3194 if (!wasm.base.options.strip) {3221 if (!wasm.base.options.strip) {
3195 if (wasm.dwarf) |*dwarf| {3222 // if (wasm.dwarf) |*dwarf| {
3196 const mod = wasm.base.options.module.?;3223 // const mod = wasm.base.options.module.?;
3197 try dwarf.writeDbgAbbrev();3224 // try dwarf.writeDbgAbbrev();
3198 // for debug info and ranges, the address is always 0,3225 // // for debug info and ranges, the address is always 0,
3199 // as locations are always offsets relative to 'code' section.3226 // // as locations are always offsets relative to 'code' section.
3200 try dwarf.writeDbgInfoHeader(mod, 0, code_section_size);3227 // try dwarf.writeDbgInfoHeader(mod, 0, code_section_size);
3201 try dwarf.writeDbgAranges(0, code_section_size);3228 // try dwarf.writeDbgAranges(0, code_section_size);
3202 try dwarf.writeDbgLineHeader();3229 // try dwarf.writeDbgLineHeader();
3203 }3230 // }
32043231
3205 var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator);3232 var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator);
3206 defer debug_bytes.deinit();3233 defer debug_bytes.deinit();
...@@ -3223,11 +3250,11 @@ fn writeToFile(...@@ -3223,11 +3250,11 @@ fn writeToFile(
32233250
3224 for (debug_sections) |item| {3251 for (debug_sections) |item| {
3225 if (item.index) |index| {3252 if (item.index) |index| {
3226 var atom = wasm.atoms.get(index).?.getFirst();3253 var atom = wasm.getAtomPtr(wasm.atoms.get(index).?);
3227 while (true) {3254 while (true) {
3228 atom.resolveRelocs(wasm);3255 atom.resolveRelocs(wasm);
3229 try debug_bytes.appendSlice(atom.code.items);3256 try debug_bytes.appendSlice(atom.code.items);
3230 atom = atom.next orelse break;3257 atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
3231 }3258 }
3232 try emitDebugSection(&binary_bytes, debug_bytes.items, item.name);3259 try emitDebugSection(&binary_bytes, debug_bytes.items, item.name);
3233 debug_bytes.clearRetainingCapacity();3260 debug_bytes.clearRetainingCapacity();
...@@ -3959,7 +3986,8 @@ fn emitSymbolTable(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:...@@ -3959,7 +3986,8 @@ fn emitSymbolTable(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
39593986
3960 if (symbol.isDefined()) {3987 if (symbol.isDefined()) {
3961 try leb.writeULEB128(writer, symbol.index);3988 try leb.writeULEB128(writer, symbol.index);
3962 const atom = wasm.symbol_atom.get(sym_loc).?;3989 const atom_index = wasm.symbol_atom.get(sym_loc).?;
3990 const atom = wasm.getAtom(atom_index);
3963 try leb.writeULEB128(writer, @as(u32, atom.offset));3991 try leb.writeULEB128(writer, @as(u32, atom.offset));
3964 try leb.writeULEB128(writer, @as(u32, atom.size));3992 try leb.writeULEB128(writer, @as(u32, atom.size));
3965 }3993 }
...@@ -4037,7 +4065,7 @@ fn emitCodeRelocations(...@@ -4037,7 +4065,7 @@ fn emitCodeRelocations(
4037 const reloc_start = binary_bytes.items.len;4065 const reloc_start = binary_bytes.items.len;
40384066
4039 var count: u32 = 0;4067 var count: u32 = 0;
4040 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();4068 var atom: *Atom = wasm.getAtomPtr(wasm.atoms.get(code_index).?);
4041 // for each atom, we calculate the uleb size and append that4069 // for each atom, we calculate the uleb size and append that
4042 var size_offset: u32 = 5; // account for code section size leb1284070 var size_offset: u32 = 5; // account for code section size leb128
4043 while (true) {4071 while (true) {
...@@ -4055,7 +4083,7 @@ fn emitCodeRelocations(...@@ -4055,7 +4083,7 @@ fn emitCodeRelocations(
4055 }4083 }
4056 log.debug("Emit relocation: {}", .{relocation});4084 log.debug("Emit relocation: {}", .{relocation});
4057 }4085 }
4058 atom = atom.next orelse break;4086 atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
4059 }4087 }
4060 if (count == 0) return;4088 if (count == 0) return;
4061 var buf: [5]u8 = undefined;4089 var buf: [5]u8 = undefined;
...@@ -4086,7 +4114,7 @@ fn emitDataRelocations(...@@ -4086,7 +4114,7 @@ fn emitDataRelocations(
4086 // for each atom, we calculate the uleb size and append that4114 // for each atom, we calculate the uleb size and append that
4087 var size_offset: u32 = 5; // account for code section size leb1284115 var size_offset: u32 = 5; // account for code section size leb128
4088 for (wasm.data_segments.values()) |segment_index| {4116 for (wasm.data_segments.values()) |segment_index| {
4089 var atom: *Atom = wasm.atoms.get(segment_index).?.getFirst();4117 var atom: *Atom = wasm.getAtomPtr(wasm.atoms.get(segment_index).?);
4090 while (true) {4118 while (true) {
4091 size_offset += getULEB128Size(atom.size);4119 size_offset += getULEB128Size(atom.size);
4092 for (atom.relocs.items) |relocation| {4120 for (atom.relocs.items) |relocation| {
...@@ -4105,7 +4133,7 @@ fn emitDataRelocations(...@@ -4105,7 +4133,7 @@ fn emitDataRelocations(
4105 }4133 }
4106 log.debug("Emit relocation: {}", .{relocation});4134 log.debug("Emit relocation: {}", .{relocation});
4107 }4135 }
4108 atom = atom.next orelse break;4136 atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
4109 }4137 }
4110 }4138 }
4111 if (count == 0) return;4139 if (count == 0) return;
src/link/Wasm/Atom.zig+20-24
...@@ -29,14 +29,17 @@ file: ?u16,...@@ -29,14 +29,17 @@ file: ?u16,
2929
30/// Next atom in relation to this atom.30/// Next atom in relation to this atom.
31/// When null, this atom is the last atom31/// When null, this atom is the last atom
32next: ?*Atom,32next: ?Atom.Index,
33/// Previous atom in relation to this atom.33/// Previous atom in relation to this atom.
34/// is null when this atom is the first in its order34/// is null when this atom is the first in its order
35prev: ?*Atom,35prev: ?Atom.Index,
3636
37/// Contains atoms local to a decl, all managed by this `Atom`.37/// Contains atoms local to a decl, all managed by this `Atom`.
38/// When the parent atom is being freed, it will also do so for all local atoms.38/// When the parent atom is being freed, it will also do so for all local atoms.
39locals: std.ArrayListUnmanaged(Atom) = .{},39locals: std.ArrayListUnmanaged(Atom.Index) = .{},
40
41/// Alias to an unsigned 32-bit integer
42pub const Index = u32;
4043
41/// Represents a default empty wasm `Atom`44/// Represents a default empty wasm `Atom`
42pub const empty: Atom = .{45pub const empty: Atom = .{
...@@ -50,14 +53,12 @@ pub const empty: Atom = .{...@@ -50,14 +53,12 @@ pub const empty: Atom = .{
50};53};
5154
52/// Frees all resources owned by this `Atom`.55/// Frees all resources owned by this `Atom`.
53pub fn deinit(atom: *Atom, gpa: Allocator) void {56pub fn deinit(atom: *Atom, wasm: *Wasm) void {
57 const gpa = wasm.base.allocator;
54 atom.relocs.deinit(gpa);58 atom.relocs.deinit(gpa);
55 atom.code.deinit(gpa);59 atom.code.deinit(gpa);
56
57 for (atom.locals.items) |*local| {
58 local.deinit(gpa);
59 }
60 atom.locals.deinit(gpa);60 atom.locals.deinit(gpa);
61 atom.* = undefined;
61}62}
6263
63/// Sets the length of relocations and code to '0',64/// Sets the length of relocations and code to '0',
...@@ -78,24 +79,11 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio...@@ -78,24 +79,11 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio
78 });79 });
79}80}
8081
81/// Returns the first `Atom` from a given atom
82pub fn getFirst(atom: *Atom) *Atom {
83 var tmp = atom;
84 while (tmp.prev) |prev| tmp = prev;
85 return tmp;
86}
87
88/// Returns the location of the symbol that represents this `Atom`82/// Returns the location of the symbol that represents this `Atom`
89pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {83pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
90 return .{ .file = atom.file, .index = atom.sym_index };84 return .{ .file = atom.file, .index = atom.sym_index };
91}85}
9286
93pub fn ensureInitialized(atom: *Atom, wasm_bin: *Wasm) !void {
94 if (atom.getSymbolIndex() != null) return; // already initialized
95 atom.sym_index = try wasm_bin.allocateSymbol();
96 try wasm_bin.symbol_atom.putNoClobber(wasm_bin.base.allocator, atom.symbolLoc(), atom);
97}
98
99pub fn getSymbolIndex(atom: Atom) ?u32 {87pub fn getSymbolIndex(atom: Atom) ?u32 {
100 if (atom.sym_index == 0) return null;88 if (atom.sym_index == 0) return null;
101 return atom.sym_index;89 return atom.sym_index;
...@@ -198,20 +186,28 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -198,20 +186,28 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
198 if (symbol.isUndefined()) {186 if (symbol.isUndefined()) {
199 return 0;187 return 0;
200 }188 }
201 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;189 const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse {
190 // this can only occur during incremental-compilation when a relocation
191 // still points to a freed decl. It is fine to emit the value 0 here
192 // as no actual code will point towards it.
193 return 0;
194 };
195 const target_atom = wasm_bin.getAtom(target_atom_index);
202 const va = @intCast(i32, target_atom.getVA(wasm_bin, symbol));196 const va = @intCast(i32, target_atom.getVA(wasm_bin, symbol));
203 return @intCast(u32, va + relocation.addend);197 return @intCast(u32, va + relocation.addend);
204 },198 },
205 .R_WASM_EVENT_INDEX_LEB => return symbol.index,199 .R_WASM_EVENT_INDEX_LEB => return symbol.index,
206 .R_WASM_SECTION_OFFSET_I32 => {200 .R_WASM_SECTION_OFFSET_I32 => {
207 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;201 const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;
202 const target_atom = wasm_bin.getAtom(target_atom_index);
208 const rel_value = @intCast(i32, target_atom.offset) + relocation.addend;203 const rel_value = @intCast(i32, target_atom.offset) + relocation.addend;
209 return @intCast(u32, rel_value);204 return @intCast(u32, rel_value);
210 },205 },
211 .R_WASM_FUNCTION_OFFSET_I32 => {206 .R_WASM_FUNCTION_OFFSET_I32 => {
212 const target_atom = wasm_bin.symbol_atom.get(target_loc) orelse {207 const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse {
213 return @bitCast(u32, @as(i32, -1));208 return @bitCast(u32, @as(i32, -1));
214 };209 };
210 const target_atom = wasm_bin.getAtom(target_atom_index);
215 const offset: u32 = 11 + Wasm.getULEB128Size(target_atom.size); // Header (11 bytes fixed-size) + body size (leb-encoded)211 const offset: u32 = 11 + Wasm.getULEB128Size(target_atom.size); // Header (11 bytes fixed-size) + body size (leb-encoded)
216 const rel_value = @intCast(i32, target_atom.offset + offset) + relocation.addend;212 const rel_value = @intCast(i32, target_atom.offset + offset) + relocation.addend;
217 return @intCast(u32, rel_value);213 return @intCast(u32, rel_value);
src/link/Wasm/Object.zig+5-10
...@@ -901,14 +901,9 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b...@@ -901,14 +901,9 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
901 continue; // found unknown section, so skip parsing into atom as we do not know how to handle it.901 continue; // found unknown section, so skip parsing into atom as we do not know how to handle it.
902 };902 };
903903
904 const atom = try gpa.create(Atom);904 const atom_index = @intCast(Atom.Index, wasm_bin.managed_atoms.items.len);
905 const atom = try wasm_bin.managed_atoms.addOne(gpa);
905 atom.* = Atom.empty;906 atom.* = Atom.empty;
906 errdefer {
907 atom.deinit(gpa);
908 gpa.destroy(atom);
909 }
910
911 try wasm_bin.managed_atoms.append(gpa, atom);
912 atom.file = object_index;907 atom.file = object_index;
913 atom.size = relocatable_data.size;908 atom.size = relocatable_data.size;
914 atom.alignment = relocatable_data.getAlignment(object);909 atom.alignment = relocatable_data.getAlignment(object);
...@@ -938,12 +933,12 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b...@@ -938,12 +933,12 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
938 .index = relocatable_data.getIndex(),933 .index = relocatable_data.getIndex(),
939 })) |symbols| {934 })) |symbols| {
940 atom.sym_index = symbols.pop();935 atom.sym_index = symbols.pop();
941 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);936 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom_index);
942937
943 // symbols referencing the same atom will be added as alias938 // symbols referencing the same atom will be added as alias
944 // or as 'parent' when they are global.939 // or as 'parent' when they are global.
945 while (symbols.popOrNull()) |idx| {940 while (symbols.popOrNull()) |idx| {
946 try wasm_bin.symbol_atom.putNoClobber(gpa, .{ .file = atom.file, .index = idx }, atom);941 try wasm_bin.symbol_atom.putNoClobber(gpa, .{ .file = atom.file, .index = idx }, atom_index);
947 const alias_symbol = object.symtable[idx];942 const alias_symbol = object.symtable[idx];
948 if (alias_symbol.isGlobal()) {943 if (alias_symbol.isGlobal()) {
949 atom.sym_index = idx;944 atom.sym_index = idx;
...@@ -956,7 +951,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b...@@ -956,7 +951,7 @@ pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_b
956 segment.alignment = std.math.max(segment.alignment, atom.alignment);951 segment.alignment = std.math.max(segment.alignment, atom.alignment);
957 }952 }
958953
959 try wasm_bin.appendAtomAtIndex(final_index, atom);954 try wasm_bin.appendAtomAtIndex(final_index, atom_index);
960 log.debug("Parsed into atom: '{s}' at segment index {d}", .{ object.string_table.get(object.symtable[atom.sym_index].name), final_index });955 log.debug("Parsed into atom: '{s}' at segment index {d}", .{ object.string_table.get(object.symtable[atom.sym_index].name), final_index });
961 }956 }
962}957}
test/link/wasm/export-data/build.zig+2-2
...@@ -23,8 +23,8 @@ pub fn build(b: *Builder) void {...@@ -23,8 +23,8 @@ pub fn build(b: *Builder) void {
23 check_lib.checkNext("type i32");23 check_lib.checkNext("type i32");
24 check_lib.checkNext("mutable false");24 check_lib.checkNext("mutable false");
25 check_lib.checkNext("i32.const {bar_address}");25 check_lib.checkNext("i32.const {bar_address}");
26 check_lib.checkComputeCompare("foo_address", .{ .op = .eq, .value = .{ .literal = 0 } });26 check_lib.checkComputeCompare("foo_address", .{ .op = .eq, .value = .{ .literal = 4 } });
27 check_lib.checkComputeCompare("bar_address", .{ .op = .eq, .value = .{ .literal = 4 } });27 check_lib.checkComputeCompare("bar_address", .{ .op = .eq, .value = .{ .literal = 0 } });
2828
29 check_lib.checkStart("Section export");29 check_lib.checkStart("Section export");
30 check_lib.checkNext("entries 3");30 check_lib.checkNext("entries 3");