| ... | @@ -9,7 +9,7 @@ const fs = std.fs; | ... | @@ -9,7 +9,7 @@ const fs = std.fs; |
| 9 | const leb = std.leb; | 9 | const leb = std.leb; |
| 10 | const log = std.log.scoped(.link); | 10 | const log = std.log.scoped(.link); |
| 11 | | 11 | |
| 12 | const Atom = @import("Wasm/Atom.zig"); | 12 | pub const Atom = @import("Wasm/Atom.zig"); |
| 13 | const Dwarf = @import("Dwarf.zig"); | 13 | const Dwarf = @import("Dwarf.zig"); |
| 14 | const Module = @import("../Module.zig"); | 14 | const Module = @import("../Module.zig"); |
| 15 | const Compilation = @import("../Compilation.zig"); | 15 | const Compilation = @import("../Compilation.zig"); |
| ... | @@ -31,10 +31,7 @@ const Object = @import("Wasm/Object.zig"); | ... | @@ -31,10 +31,7 @@ const Object = @import("Wasm/Object.zig"); |
| 31 | const Archive = @import("Wasm/Archive.zig"); | 31 | const Archive = @import("Wasm/Archive.zig"); |
| 32 | const types = @import("Wasm/types.zig"); | 32 | const types = @import("Wasm/types.zig"); |
| 33 | | 33 | |
| 34 | pub const base_tag = link.File.Tag.wasm; | 34 | pub const base_tag: link.File.Tag = .wasm; |
| 35 | | | |
| 36 | /// deprecated: Use `@import("Wasm/Atom.zig");` | | |
| 37 | pub const DeclBlock = Atom; | | |
| 38 | | 35 | |
| 39 | base: link.File, | 36 | base: link.File, |
| 40 | /// Output name of the file | 37 | /// 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? |
| 48 | host_name: []const u8 = "env", | 45 | host_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 memory | 47 | /// Each index maps to the corresponding `Atom.Index`. |
| 51 | /// when calling `deinit` | 48 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, Atom.Index) = .{}, |
| 52 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, void) = .{}, | | |
| 53 | /// List of all symbols generated by Zig code. | 49 | /// List of all symbols generated by Zig code. |
| 54 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | 50 | symbols: 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. |
| 56 | symbols_free_list: std.ArrayListUnmanaged(u32) = .{}, | 52 | symbols_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 57 | /// Maps atoms to their segment index | 53 | /// Maps atoms to their segment index |
| 58 | atoms: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, | 54 | atoms: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 59 | /// Atoms managed and created by the linker. This contains atoms | 55 | /// List of all atoms. |
| 60 | /// from object files, and not Atoms generated by a Decl. | 56 | managed_atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 61 | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, | | |
| 62 | /// Represents the index into `segments` where the 'code' section | 57 | /// Represents the index into `segments` where the 'code' section |
| 63 | /// lives. | 58 | /// lives. |
| 64 | code_section_index: ?u32 = null, | 59 | code_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 meta | 143 | /// 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. |
| 151 | symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, *Atom) = .{}, | 146 | symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, Atom.Index) = .{}, |
| 152 | /// Maps a symbol's location to its export name, which may differ from the decl's name | 147 | /// 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 extended | 160 | // unit contains Zig code. The lifetime of these atoms are extended |
| 166 | // until the end of the compiler's lifetime. Meaning they're not freed | 161 | // 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. |
| 168 | debug_info_atom: ?*Atom = null, | 163 | debug_info_atom: ?Atom.Index = null, |
| 169 | debug_line_atom: ?*Atom = null, | 164 | debug_line_atom: ?Atom.Index = null, |
| 170 | debug_loc_atom: ?*Atom = null, | 165 | debug_loc_atom: ?Atom.Index = null, |
| 171 | debug_ranges_atom: ?*Atom = null, | 166 | debug_ranges_atom: ?Atom.Index = null, |
| 172 | debug_abbrev_atom: ?*Atom = null, | 167 | debug_abbrev_atom: ?Atom.Index = null, |
| 173 | debug_str_atom: ?*Atom = null, | 168 | debug_str_atom: ?Atom.Index = null, |
| 174 | debug_pubnames_atom: ?*Atom = null, | 169 | debug_pubnames_atom: ?Atom.Index = null, |
| 175 | debug_pubtypes_atom: ?*Atom = null, | 170 | debug_pubtypes_atom: ?Atom.Index = null, |
| 176 | | 171 | |
| 177 | pub const Segment = struct { | 172 | pub 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 | } |
| 432 | | 427 | |
| 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 | // } |
| 437 | | 432 | |
| 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 sections | 473 | /// 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 atoms | 475 | /// 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 | } |
| 518 | | 514 | |
| | 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`. |
| | 518 | pub 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` |
| | 527 | fn 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 | |
| | 537 | pub inline fn getAtom(wasm: *const Wasm, index: Atom.Index) Atom { |
| | 538 | return wasm.managed_atoms.items[index]; |
| | 539 | } |
| | 540 | |
| | 541 | pub 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 file | 545 | /// 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. |
| 859 | | 885 | |
| 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; |
| 866 | | 893 | |
| 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 | } |
| 870 | | 897 | |
| 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); |
| 875 | | 902 | |
| 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; |
| 882 | | 908 | |
| 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 | } |
| 887 | | 913 | |
| ... | @@ -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 | } |
| 922 | | 948 | |
| 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 |
| 1014 | | 1029 | |
| 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.* = {}; | | |
| 1023 | | 1035 | |
| 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(); |
| 1026 | | 1038 | |
| 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 | ); |
| 1038 | | 1059 | |
| 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 | }; |
| 1047 | | 1068 | |
| 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 section | 1074 | // // 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 | } |
| 1062 | | 1083 | |
| 1063 | // Generate code for the Decl, storing it in memory to be later written to | 1084 | // 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 | } |
| 1082 | | 1103 | |
| 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.* = {}; | | |
| 1089 | | 1107 | |
| 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; |
| 1096 | | 1114 | |
| ... | @@ -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 | ); |
| 1108 | | 1126 | |
| 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 | }; |
| 1117 | | 1135 | |
| 1118 | return wasm.finishUpdateDecl(decl, code); | 1136 | return wasm.finishUpdateDecl(decl_index, code); |
| 1119 | } | 1137 | } |
| 1120 | | 1138 | |
| 1121 | pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void { | 1139 | pub 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 | } |
| 1135 | | 1153 | |
| 1136 | fn finishUpdateDecl(wasm: *Wasm, decl: *Module.Decl, code: []const u8) !void { | 1154 | fn 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); |
| 1202 | | 1222 | |
| 1203 | // Create and initialize a new local symbol and atom | 1223 | // 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(); |
| 1225 | | 1235 | |
| 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 | }; |
| 1245 | | 1267 | |
| | 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 relocations | 1325 | 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 | } |
| 1323 | | 1349 | |
| 1324 | pub fn deleteExport(wasm: *Wasm, exp: Export) void { | 1350 | pub 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 | } |
| 1350 | | 1377 | |
| 1351 | const decl = mod.declPtr(decl_index); | 1378 | const decl = mod.declPtr(decl_index); |
| 1352 | if (decl.link.wasm.getSymbolIndex() == null) return; // unititialized | 1379 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); |
| | 1380 | const atom = wasm.getAtom(atom_index); |
| 1353 | | 1381 | |
| 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( |
| 1364 | | 1392 | |
| 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).*; |
| 1369 | | 1397 | |
| 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 symbol | 1414 | 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 | } |
| 1393 | | 1422 | |
| 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 import | 1458 | // 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 | } |
| 1435 | | 1463 | |
| ... | @@ -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 symbol | 1478 | 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 | // } |
| 1463 | | 1493 | |
| 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 | } |
| 1466 | | 1505 | |
| 1467 | /// Appends a new entry to the indirect function table | 1506 | /// 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 | }; |
| 1584 | | 1623 | |
| 1585 | /// Parses an Atom and inserts its metadata into the corresponding sections. | 1624 | /// Parses an Atom and inserts its metadata into the corresponding sections. |
| 1586 | fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void { | 1625 | fn 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); |
| 1660 | | 1700 | |
| 1661 | try wasm.appendAtomAtIndex(final_index, atom); | 1701 | try wasm.appendAtomAtIndex(final_index, atom_index); |
| 1662 | } | 1702 | } |
| 1663 | | 1703 | |
| 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. |
| 1666 | pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom: *Atom) !void { | 1706 | pub 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 | } |
| 1675 | | 1717 | |
| ... | @@ -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; |
| 1680 | | 1722 | |
| 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; |
| 1694 | | 1737 | |
| ... | @@ -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 pointers | 1779 | 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; |
| 1868 | | 1911 | |
| 1869 | // create the atom that will be output into the final binary | 1912 | // 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); | | |
| 1885 | | 1927 | |
| 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 | } |
| 1890 | | 1933 | |
| 1891 | fn setupImports(wasm: *Wasm) !void { | 1934 | fn 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 | } |
| 2199 | | 2244 | |
| ... | @@ -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 | } |
| 2232 | | 2278 | |
| ... | @@ -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 populated | 2398 | // 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. |
| 2354 | | 2400 | |
| 2355 | // As sym_index '0' is reserved, we use it for our stack pointer symbol | 2401 | 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 | }; | | |
| 2361 | | 2406 | |
| 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); |
| 2371 | | 2416 | |
| 2372 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 2417 | try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {}); |
| 2373 | | 2418 | |
| 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 | } |
| 2387 | | 2423 | |
| 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. |
| 2392 | fn populateErrorNameTable(wasm: *Wasm) !void { | 2428 | fn 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 calculate | 2434 | // 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 name | 2462 | // 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 { |
| 2449 | | 2480 | |
| 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); |
| 2453 | | 2484 | |
| 2454 | // link the atoms with the rest of the binary so they can be allocated | 2485 | // 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 | } |
| 2459 | | 2490 | |
| 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`. |
| 2463 | pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !*Atom { | 2494 | pub 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(); |
| 2467 | | 2498 | |
| 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 | }; |
| 2479 | | 2507 | |
| 2480 | const atom = try wasm.base.allocator.create(Atom); | | |
| 2481 | atom.* = Atom.empty; | | |
| 2482 | atom.alignment = 1; // debug sections are always 1-byte-aligned | 2508 | 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 | } |
| 2488 | | 2511 | |
| 2489 | fn resetState(wasm: *Wasm) void { | 2512 | fn 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 | |
| 2500 | | 2523 | 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 | } |
| 2821 | | 2844 | |
| 2822 | // also parse atoms for a decl's locals | 2845 | // 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 | } |
| 2827 | | 2851 | |
| ... | @@ -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).?; |
| 3070 | | 3094 | |
| 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(); |
| 3074 | | 3098 | |
| 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 | } |
| 3084 | | 3110 | |
| 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 therefore | 3145 | // do not output 'bss' section unless we import memory and therefore |
| 3120 | // want to guarantee the data is zero initialized | 3146 | // 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 segments | 3150 | 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).?; |
| 3127 | | 3153 | |
| 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 segments | 3160 | // 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); |
| 3150 | | 3177 | |
| 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 ensure | 3182 | // 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 | } |
| 3193 | | 3220 | |
| 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 | // } |
| 3204 | | 3231 | |
| 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( |
| 3223 | | 3250 | |
| 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: |
| 3959 | | 3986 | |
| 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; |
| 4038 | | 4066 | |
| 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 that | 4069 | // for each atom, we calculate the uleb size and append that |
| 4042 | var size_offset: u32 = 5; // account for code section size leb128 | 4070 | 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 that | 4114 | // for each atom, we calculate the uleb size and append that |
| 4087 | var size_offset: u32 = 5; // account for code section size leb128 | 4115 | 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; |