| ... | ... | @@ -9,7 +9,7 @@ const fs = std.fs; |
| 9 | 9 | const leb = std.leb; |
| 10 | 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 | 13 | const Dwarf = @import("Dwarf.zig"); |
| 14 | 14 | const Module = @import("../Module.zig"); |
| 15 | 15 | const Compilation = @import("../Compilation.zig"); |
| ... | ... | @@ -31,10 +31,7 @@ const Object = @import("Wasm/Object.zig"); |
| 31 | 31 | const Archive = @import("Wasm/Archive.zig"); |
| 32 | 32 | const types = @import("Wasm/types.zig"); |
| 33 | 33 | |
| 34 | | pub const base_tag = link.File.Tag.wasm; |
| 35 | | |
| 36 | | /// deprecated: Use `@import("Wasm/Atom.zig");` |
| 37 | | pub const DeclBlock = Atom; |
| 34 | pub const base_tag: link.File.Tag = .wasm; |
| 38 | 35 | |
| 39 | 36 | base: link.File, |
| 40 | 37 | /// Output name of the file |
| ... | ... | @@ -47,18 +44,16 @@ llvm_object: ?*LlvmObject = null, |
| 47 | 44 | /// TODO: Allow setting this through a flag? |
| 48 | 45 | host_name: []const u8 = "env", |
| 49 | 46 | /// List of all `Decl` that are currently alive. |
| 50 | | /// This is ment for bookkeeping so we can safely cleanup all codegen memory |
| 51 | | /// when calling `deinit` |
| 52 | | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, void) = .{}, |
| 47 | /// Each index maps to the corresponding `Atom.Index`. |
| 48 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, Atom.Index) = .{}, |
| 53 | 49 | /// List of all symbols generated by Zig code. |
| 54 | 50 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 55 | 51 | /// List of symbol indexes which are free to be used. |
| 56 | 52 | symbols_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 57 | 53 | /// Maps atoms to their segment index |
| 58 | | atoms: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, |
| 59 | | /// Atoms managed and created by the linker. This contains atoms |
| 60 | | /// from object files, and not Atoms generated by a Decl. |
| 61 | | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 54 | atoms: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 55 | /// List of all atoms. |
| 56 | managed_atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 62 | 57 | /// Represents the index into `segments` where the 'code' section |
| 63 | 58 | /// lives. |
| 64 | 59 | code_section_index: ?u32 = null, |
| ... | ... | @@ -148,7 +143,7 @@ undefs: std.StringArrayHashMapUnmanaged(SymbolLoc) = .{}, |
| 148 | 143 | /// Maps a symbol's location to an atom. This can be used to find meta |
| 149 | 144 | /// data of a symbol, such as its size, or its offset to perform a relocation. |
| 150 | 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 | 147 | /// Maps a symbol's location to its export name, which may differ from the decl's name |
| 153 | 148 | /// which does the exporting. |
| 154 | 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 | 160 | // unit contains Zig code. The lifetime of these atoms are extended |
| 166 | 161 | // until the end of the compiler's lifetime. Meaning they're not freed |
| 167 | 162 | // during `flush()` in incremental-mode. |
| 168 | | debug_info_atom: ?*Atom = null, |
| 169 | | debug_line_atom: ?*Atom = null, |
| 170 | | debug_loc_atom: ?*Atom = null, |
| 171 | | debug_ranges_atom: ?*Atom = null, |
| 172 | | debug_abbrev_atom: ?*Atom = null, |
| 173 | | debug_str_atom: ?*Atom = null, |
| 174 | | debug_pubnames_atom: ?*Atom = null, |
| 175 | | debug_pubtypes_atom: ?*Atom = null, |
| 163 | debug_info_atom: ?Atom.Index = null, |
| 164 | debug_line_atom: ?Atom.Index = null, |
| 165 | debug_loc_atom: ?Atom.Index = null, |
| 166 | debug_ranges_atom: ?Atom.Index = null, |
| 167 | debug_abbrev_atom: ?Atom.Index = null, |
| 168 | debug_str_atom: ?Atom.Index = null, |
| 169 | debug_pubnames_atom: ?Atom.Index = null, |
| 170 | debug_pubtypes_atom: ?Atom.Index = null, |
| 176 | 171 | |
| 177 | 172 | pub const Segment = struct { |
| 178 | 173 | alignment: u32, |
| ... | ... | @@ -430,10 +425,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 430 | 425 | // at the end during `initializeCallCtorsFunction`. |
| 431 | 426 | } |
| 432 | 427 | |
| 433 | | if (!options.strip and options.module != null) { |
| 434 | | wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, options.target); |
| 435 | | try wasm_bin.initDebugSections(); |
| 436 | | } |
| 428 | // if (!options.strip and options.module != null) { |
| 429 | // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, options.target); |
| 430 | // try wasm_bin.initDebugSections(); |
| 431 | // } |
| 437 | 432 | |
| 438 | 433 | return wasm_bin; |
| 439 | 434 | } |
| ... | ... | @@ -474,6 +469,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol |
| 474 | 469 | try wasm.globals.put(wasm.base.allocator, name_offset, loc); |
| 475 | 470 | return loc; |
| 476 | 471 | } |
| 472 | |
| 477 | 473 | /// Initializes symbols and atoms for the debug sections |
| 478 | 474 | /// Initialization is only done when compiling Zig code. |
| 479 | 475 | /// When Zig is invoked as a linker instead, the atoms |
| ... | ... | @@ -516,6 +512,36 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool { |
| 516 | 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 | 545 | /// Parses an archive file and will then parse each object file |
| 520 | 546 | /// that was found in the archive file. |
| 521 | 547 | /// Returns false when the file is not an archive file. |
| ... | ... | @@ -857,15 +883,16 @@ fn resolveLazySymbols(wasm: *Wasm) !void { |
| 857 | 883 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| 858 | 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); |
| 861 | | errdefer wasm.base.allocator.destroy(atom); |
| 862 | | try wasm.managed_atoms.append(wasm.base.allocator, atom); |
| 886 | // TODO: Can we use `createAtom` here while also re-using the symbol |
| 887 | // from `createSyntheticSymbol`. |
| 888 | const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); |
| 889 | const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); |
| 863 | 890 | atom.* = Atom.empty; |
| 864 | 891 | atom.sym_index = loc.index; |
| 865 | 892 | atom.alignment = 1; |
| 866 | 893 | |
| 867 | | try wasm.parseAtom(atom, .{ .data = .synthetic }); |
| 868 | | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom); |
| 894 | try wasm.parseAtom(atom_index, .{ .data = .synthetic }); |
| 895 | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); |
| 869 | 896 | } |
| 870 | 897 | |
| 871 | 898 | if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| { |
| ... | ... | @@ -873,15 +900,14 @@ fn resolveLazySymbols(wasm: *Wasm) !void { |
| 873 | 900 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| 874 | 901 | _ = wasm.resolved_symbols.swapRemove(loc); |
| 875 | 902 | |
| 876 | | const atom = try wasm.base.allocator.create(Atom); |
| 877 | | errdefer wasm.base.allocator.destroy(atom); |
| 878 | | try wasm.managed_atoms.append(wasm.base.allocator, atom); |
| 903 | const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); |
| 904 | const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); |
| 879 | 905 | atom.* = Atom.empty; |
| 880 | 906 | atom.sym_index = loc.index; |
| 881 | 907 | atom.alignment = 1; |
| 882 | 908 | |
| 883 | | try wasm.parseAtom(atom, .{ .data = .synthetic }); |
| 884 | | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom); |
| 909 | try wasm.parseAtom(atom_index, .{ .data = .synthetic }); |
| 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 | 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 | 949 | for (wasm.func_types.items) |*func_type| { |
| 934 | 950 | func_type.deinit(gpa); |
| 935 | 951 | } |
| ... | ... | @@ -954,9 +970,8 @@ pub fn deinit(wasm: *Wasm) void { |
| 954 | 970 | wasm.symbol_atom.deinit(gpa); |
| 955 | 971 | wasm.export_names.deinit(gpa); |
| 956 | 972 | wasm.atoms.deinit(gpa); |
| 957 | | for (wasm.managed_atoms.items) |managed_atom| { |
| 958 | | managed_atom.deinit(gpa); |
| 959 | | gpa.destroy(managed_atom); |
| 973 | for (wasm.managed_atoms.items) |*managed_atom| { |
| 974 | managed_atom.deinit(wasm); |
| 960 | 975 | } |
| 961 | 976 | wasm.managed_atoms.deinit(gpa); |
| 962 | 977 | wasm.segments.deinit(gpa); |
| ... | ... | @@ -1014,18 +1029,24 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes |
| 1014 | 1029 | |
| 1015 | 1030 | const decl_index = func.owner_decl; |
| 1016 | 1031 | const decl = mod.declPtr(decl_index); |
| 1017 | | const atom = &decl.link.wasm; |
| 1018 | | try atom.ensureInitialized(wasm); |
| 1019 | | const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index); |
| 1020 | | if (gop.found_existing) { |
| 1021 | | atom.clear(); |
| 1022 | | } else gop.value_ptr.* = {}; |
| 1032 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); |
| 1033 | const atom = wasm.getAtomPtr(atom_index); |
| 1034 | atom.clear(); |
| 1023 | 1035 | |
| 1024 | | 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(); |
| 1036 | // var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl_index) else null; |
| 1037 | // defer if (decl_state) |*ds| ds.deinit(); |
| 1026 | 1038 | |
| 1027 | 1039 | var code_writer = std.ArrayList(u8).init(wasm.base.allocator); |
| 1028 | 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 | 1050 | const result = try codegen.generateFunction( |
| 1030 | 1051 | &wasm.base, |
| 1031 | 1052 | decl.srcLoc(), |
| ... | ... | @@ -1033,7 +1054,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes |
| 1033 | 1054 | air, |
| 1034 | 1055 | liveness, |
| 1035 | 1056 | &code_writer, |
| 1036 | | if (decl_state) |*ds| .{ .dwarf = ds } else .none, |
| 1057 | .none, |
| 1037 | 1058 | ); |
| 1038 | 1059 | |
| 1039 | 1060 | const code = switch (result) { |
| ... | ... | @@ -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| { |
| 1049 | | try dwarf.commitDeclState( |
| 1050 | | mod, |
| 1051 | | decl_index, |
| 1052 | | // Actual value will be written after relocation. |
| 1053 | | // For Wasm, this is the offset relative to the code section |
| 1054 | | // which isn't known until flush(). |
| 1055 | | 0, |
| 1056 | | code.len, |
| 1057 | | &decl_state.?, |
| 1058 | | ); |
| 1059 | | } |
| 1060 | | return wasm.finishUpdateDecl(decl, code); |
| 1069 | // if (wasm.dwarf) |*dwarf| { |
| 1070 | // try dwarf.commitDeclState( |
| 1071 | // mod, |
| 1072 | // decl_index, |
| 1073 | // // Actual value will be written after relocation. |
| 1074 | // // For Wasm, this is the offset relative to the code section |
| 1075 | // // which isn't known until flush(). |
| 1076 | // 0, |
| 1077 | // code.len, |
| 1078 | // &decl_state.?, |
| 1079 | // ); |
| 1080 | // } |
| 1081 | return wasm.finishUpdateDecl(decl_index, code); |
| 1061 | 1082 | } |
| 1062 | 1083 | |
| 1063 | 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 | 1101 | return; |
| 1081 | 1102 | } |
| 1082 | 1103 | |
| 1083 | | const atom = &decl.link.wasm; |
| 1084 | | try atom.ensureInitialized(wasm); |
| 1085 | | const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index); |
| 1086 | | if (gop.found_existing) { |
| 1087 | | atom.clear(); |
| 1088 | | } else gop.value_ptr.* = {}; |
| 1104 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); |
| 1105 | const atom = wasm.getAtomPtr(atom_index); |
| 1106 | atom.clear(); |
| 1089 | 1107 | |
| 1090 | 1108 | if (decl.isExtern()) { |
| 1091 | 1109 | const variable = decl.getVariable().?; |
| 1092 | 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 | 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 | 1121 | .{ .ty = decl.ty, .val = val }, |
| 1104 | 1122 | &code_writer, |
| 1105 | 1123 | .none, |
| 1106 | | .{ .parent_atom_index = decl.link.wasm.sym_index }, |
| 1124 | .{ .parent_atom_index = atom.sym_index }, |
| 1107 | 1125 | ); |
| 1108 | 1126 | |
| 1109 | 1127 | const code = switch (res) { |
| ... | ... | @@ -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 | 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 | 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 | 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 | 1159 | const symbol = &wasm.symbols.items[atom.sym_index]; |
| 1140 | 1160 | const full_name = try decl.getFullyQualifiedName(mod); |
| 1141 | 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 | 1221 | const decl = mod.declPtr(decl_index); |
| 1202 | 1222 | |
| 1203 | 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 | 1229 | const fqdn = try decl.getFullyQualifiedName(mod); |
| 1206 | 1230 | defer wasm.base.allocator.free(fqdn); |
| 1207 | 1231 | const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index }); |
| 1208 | 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 | 1233 | var value_bytes = std.ArrayList(u8).init(wasm.base.allocator); |
| 1224 | 1234 | defer value_bytes.deinit(); |
| 1225 | 1235 | |
| 1226 | | const result = try codegen.generateSymbol( |
| 1227 | | &wasm.base, |
| 1228 | | decl.srcLoc(), |
| 1229 | | tv, |
| 1230 | | &value_bytes, |
| 1231 | | .none, |
| 1232 | | .{ |
| 1233 | | .parent_atom_index = atom.sym_index, |
| 1234 | | .addend = null, |
| 1235 | | }, |
| 1236 | | ); |
| 1237 | | const code = switch (result) { |
| 1238 | | .ok => value_bytes.items, |
| 1239 | | .fail => |em| { |
| 1240 | | decl.analysis = .codegen_failure; |
| 1241 | | try mod.failed_decls.put(mod.gpa, decl_index, em); |
| 1242 | | return error.AnalysisFail; |
| 1243 | | }, |
| 1236 | const code = code: { |
| 1237 | const atom = wasm.getAtomPtr(atom_index); |
| 1238 | atom.alignment = tv.ty.abiAlignment(wasm.base.options.target); |
| 1239 | wasm.symbols.items[atom.sym_index] = .{ |
| 1240 | .name = try wasm.string_table.put(wasm.base.allocator, name), |
| 1241 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), |
| 1242 | .tag = .data, |
| 1243 | .index = undefined, |
| 1244 | }; |
| 1245 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {}); |
| 1246 | |
| 1247 | const result = try codegen.generateSymbol( |
| 1248 | &wasm.base, |
| 1249 | decl.srcLoc(), |
| 1250 | tv, |
| 1251 | &value_bytes, |
| 1252 | .none, |
| 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 | 1269 | atom.size = @intCast(u32, code.len); |
| 1247 | 1270 | try atom.code.appendSlice(wasm.base.allocator, code); |
| 1248 | 1271 | return atom.sym_index; |
| ... | ... | @@ -1290,10 +1313,13 @@ pub fn getDeclVAddr( |
| 1290 | 1313 | ) !u64 { |
| 1291 | 1314 | const mod = wasm.base.options.module.?; |
| 1292 | 1315 | const decl = mod.declPtr(decl_index); |
| 1293 | | try decl.link.wasm.ensureInitialized(wasm); |
| 1294 | | const target_symbol_index = decl.link.wasm.sym_index; |
| 1316 | |
| 1317 | const target_atom_index = try wasm.getOrCreateAtomForDecl(decl_index); |
| 1318 | const target_symbol_index = wasm.getAtom(target_atom_index).sym_index; |
| 1319 | |
| 1295 | 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 | 1323 | const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; |
| 1298 | 1324 | if (decl.ty.zigTypeTag() == .Fn) { |
| 1299 | 1325 | assert(reloc_info.addend == 0); // addend not allowed for function relocations |
| ... | ... | @@ -1321,9 +1347,10 @@ pub fn getDeclVAddr( |
| 1321 | 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 | 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 | 1354 | const loc: SymbolLoc = .{ .file = null, .index = sym_index }; |
| 1328 | 1355 | const symbol = loc.getSymbol(wasm); |
| 1329 | 1356 | const symbol_name = wasm.string_table.get(symbol.name); |
| ... | ... | @@ -1349,7 +1376,8 @@ pub fn updateDeclExports( |
| 1349 | 1376 | } |
| 1350 | 1377 | |
| 1351 | 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 | 1382 | for (exports) |exp| { |
| 1355 | 1383 | if (exp.options.section) |section| { |
| ... | ... | @@ -1364,7 +1392,7 @@ pub fn updateDeclExports( |
| 1364 | 1392 | |
| 1365 | 1393 | const export_name = try wasm.string_table.put(wasm.base.allocator, exp.options.name); |
| 1366 | 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 | 1396 | const existing_sym: Symbol = existing_loc.getSymbol(wasm).*; |
| 1369 | 1397 | |
| 1370 | 1398 | const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak; |
| ... | ... | @@ -1385,15 +1413,16 @@ pub fn updateDeclExports( |
| 1385 | 1413 | } else if (exp_is_weak) { |
| 1386 | 1414 | continue; // to-be-exported symbol is weak, so we keep the existing symbol |
| 1387 | 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 | 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); |
| 1395 | | const sym_index = exported_decl.link.wasm.sym_index; |
| 1396 | | const sym_loc = exported_decl.link.wasm.symbolLoc(); |
| 1423 | const exported_atom_index = try wasm.getOrCreateAtomForDecl(exp.exported_decl); |
| 1424 | const exported_atom = wasm.getAtom(exported_atom_index); |
| 1425 | const sym_loc = exported_atom.symbolLoc(); |
| 1397 | 1426 | const symbol = sym_loc.getSymbol(wasm); |
| 1398 | 1427 | switch (exp.options.linkage) { |
| 1399 | 1428 | .Internal => { |
| ... | ... | @@ -1429,7 +1458,6 @@ pub fn updateDeclExports( |
| 1429 | 1458 | // if the symbol was previously undefined, remove it as an import |
| 1430 | 1459 | _ = wasm.imports.remove(sym_loc); |
| 1431 | 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 | 1467 | } |
| 1440 | 1468 | const mod = wasm.base.options.module.?; |
| 1441 | 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 | 1472 | wasm.symbols_free_list.append(wasm.base.allocator, atom.sym_index) catch {}; |
| 1444 | 1473 | _ = wasm.decls.remove(decl_index); |
| 1445 | 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 | 1477 | const local_symbol = &wasm.symbols.items[local_atom.sym_index]; |
| 1448 | 1478 | local_symbol.tag = .dead; // also for any local symbol |
| 1449 | 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 | 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 | 1506 | /// Appends a new entry to the indirect function table |
| ... | ... | @@ -1583,7 +1622,8 @@ const Kind = union(enum) { |
| 1583 | 1622 | }; |
| 1584 | 1623 | |
| 1585 | 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 | 1627 | const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); |
| 1588 | 1628 | const final_index: u32 = switch (kind) { |
| 1589 | 1629 | .function => |fn_data| result: { |
| ... | ... | @@ -1658,18 +1698,20 @@ fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void { |
| 1658 | 1698 | const segment: *Segment = &wasm.segments.items[final_index]; |
| 1659 | 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 | 1704 | /// From a given index, append the given `Atom` at the back of the linked list. |
| 1665 | 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 { |
| 1667 | | if (wasm.atoms.getPtr(index)) |last| { |
| 1668 | | last.*.next = atom; |
| 1669 | | atom.prev = last.*; |
| 1670 | | last.* = atom; |
| 1706 | pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void { |
| 1707 | const atom = wasm.getAtomPtr(atom_index); |
| 1708 | if (wasm.atoms.getPtr(index)) |last_index_ptr| { |
| 1709 | const last = wasm.getAtomPtr(last_index_ptr.*); |
| 1710 | last.*.next = atom_index; |
| 1711 | atom.prev = last_index_ptr.*; |
| 1712 | last_index_ptr.* = atom_index; |
| 1671 | 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 | 1721 | if (wasm.dwarf == null) return; |
| 1680 | 1722 | |
| 1681 | 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 | 1725 | const index = maybe_index.* orelse idx: { |
| 1684 | 1726 | const index = @intCast(u32, bin.segments.items.len); |
| 1685 | 1727 | try bin.appendDummySegment(); |
| 1686 | 1728 | maybe_index.* = index; |
| 1687 | 1729 | break :idx index; |
| 1688 | 1730 | }; |
| 1731 | const atom = bin.getAtomPtr(atom_index); |
| 1689 | 1732 | atom.size = @intCast(u32, atom.code.items.len); |
| 1690 | 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 | 1736 | }.f; |
| 1694 | 1737 | |
| ... | ... | @@ -1710,15 +1753,16 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 1710 | 1753 | var it = wasm.atoms.iterator(); |
| 1711 | 1754 | while (it.next()) |entry| { |
| 1712 | 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 | 1757 | var offset: u32 = 0; |
| 1715 | 1758 | while (true) { |
| 1759 | const atom = wasm.getAtomPtr(atom_index); |
| 1716 | 1760 | const symbol_loc = atom.symbolLoc(); |
| 1717 | 1761 | if (wasm.code_section_index) |index| { |
| 1718 | 1762 | if (index == entry.key_ptr.*) { |
| 1719 | 1763 | if (!wasm.resolved_symbols.contains(symbol_loc)) { |
| 1720 | 1764 | // only allocate resolved function body's. |
| 1721 | | atom = atom.next orelse break; |
| 1765 | atom_index = atom.prev orelse break; |
| 1722 | 1766 | continue; |
| 1723 | 1767 | } |
| 1724 | 1768 | } |
| ... | ... | @@ -1732,8 +1776,7 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 1732 | 1776 | atom.size, |
| 1733 | 1777 | }); |
| 1734 | 1778 | offset += atom.size; |
| 1735 | | try wasm.symbol_atom.put(wasm.base.allocator, symbol_loc, atom); // Update atom pointers |
| 1736 | | atom = atom.next orelse break; |
| 1779 | atom_index = atom.prev orelse break; |
| 1737 | 1780 | } |
| 1738 | 1781 | segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment); |
| 1739 | 1782 | } |
| ... | ... | @@ -1867,8 +1910,8 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1867 | 1910 | symbol.index = func_index; |
| 1868 | 1911 | |
| 1869 | 1912 | // create the atom that will be output into the final binary |
| 1870 | | const atom = try wasm.base.allocator.create(Atom); |
| 1871 | | errdefer wasm.base.allocator.destroy(atom); |
| 1913 | const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); |
| 1914 | const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); |
| 1872 | 1915 | atom.* = .{ |
| 1873 | 1916 | .size = @intCast(u32, function_body.items.len), |
| 1874 | 1917 | .offset = 0, |
| ... | ... | @@ -1879,13 +1922,13 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1879 | 1922 | .prev = null, |
| 1880 | 1923 | .code = function_body.moveToUnmanaged(), |
| 1881 | 1924 | }; |
| 1882 | | try wasm.managed_atoms.append(wasm.base.allocator, atom); |
| 1883 | | try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom); |
| 1884 | | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom); |
| 1925 | try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom_index); |
| 1926 | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); |
| 1885 | 1927 | |
| 1886 | 1928 | // `allocateAtoms` has already been called, set the atom's offset manually. |
| 1887 | 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 | 1934 | fn setupImports(wasm: *Wasm) !void { |
| ... | ... | @@ -2088,7 +2131,8 @@ fn setupExports(wasm: *Wasm) !void { |
| 2088 | 2131 | break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); |
| 2089 | 2132 | }; |
| 2090 | 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 | 2136 | const va = atom.getVA(wasm, symbol); |
| 2093 | 2137 | const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len); |
| 2094 | 2138 | try wasm.wasm_globals.append(wasm.base.allocator, .{ |
| ... | ... | @@ -2193,7 +2237,8 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2193 | 2237 | const segment_index = wasm.data_segments.get(".synthetic").?; |
| 2194 | 2238 | const segment = &wasm.segments.items[segment_index]; |
| 2195 | 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 | 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 | 2271 | const segment_index = wasm.data_segments.get(".synthetic").?; |
| 2227 | 2272 | const segment = &wasm.segments.items[segment_index]; |
| 2228 | 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 | 2276 | atom.offset = @intCast(u32, memory_ptr); |
| 2231 | 2277 | } |
| 2232 | 2278 | |
| ... | ... | @@ -2352,15 +2398,14 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { |
| 2352 | 2398 | // and then return said symbol's index. The final table will be populated |
| 2353 | 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 |
| 2356 | | const symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: { |
| 2357 | | const index = @intCast(u32, wasm.symbols.items.len); |
| 2358 | | _ = try wasm.symbols.addOne(wasm.base.allocator); |
| 2359 | | break :blk index; |
| 2360 | | }; |
| 2401 | const atom_index = try wasm.createAtom(); |
| 2402 | const atom = wasm.getAtomPtr(atom_index); |
| 2403 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 2404 | atom.alignment = slice_ty.abiAlignment(wasm.base.options.target); |
| 2405 | const sym_index = atom.sym_index; |
| 2361 | 2406 | |
| 2362 | 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 | 2409 | symbol.* = .{ |
| 2365 | 2410 | .name = sym_name, |
| 2366 | 2411 | .tag = .data, |
| ... | ... | @@ -2369,20 +2414,11 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { |
| 2369 | 2414 | }; |
| 2370 | 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); |
| 2375 | | atom.* = Atom.empty; |
| 2376 | | atom.sym_index = symbol_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; |
| 2419 | log.debug("Error name table was created with symbol index: ({d})", .{sym_index}); |
| 2420 | wasm.error_table_symbol = sym_index; |
| 2421 | return sym_index; |
| 2386 | 2422 | } |
| 2387 | 2423 | |
| 2388 | 2424 | /// Populates the error name table, when `error_table_symbol` is not null. |
| ... | ... | @@ -2391,22 +2427,17 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { |
| 2391 | 2427 | /// The table is what is being pointed to within the runtime bodies that are generated. |
| 2392 | 2428 | fn populateErrorNameTable(wasm: *Wasm) !void { |
| 2393 | 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 | 2433 | // Rather than creating a symbol for each individual error name, |
| 2396 | 2434 | // we create a symbol for the entire region of error names. We then calculate |
| 2397 | 2435 | // the pointers into the list using addends which are appended to the relocation. |
| 2398 | | const names_atom = try wasm.base.allocator.create(Atom); |
| 2399 | | names_atom.* = Atom.empty; |
| 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; |
| 2436 | const names_atom_index = try wasm.createAtom(); |
| 2437 | const names_atom = wasm.getAtomPtr(names_atom_index); |
| 2407 | 2438 | names_atom.alignment = 1; |
| 2408 | 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 | 2441 | names_symbol.* = .{ |
| 2411 | 2442 | .name = sym_name, |
| 2412 | 2443 | .tag = .data, |
| ... | ... | @@ -2430,7 +2461,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { |
| 2430 | 2461 | try atom.code.writer(wasm.base.allocator).writeIntLittle(u32, len - 1); |
| 2431 | 2462 | // create relocation to the error name |
| 2432 | 2463 | try atom.relocs.append(wasm.base.allocator, .{ |
| 2433 | | .index = names_symbol_index, |
| 2464 | .index = names_atom.sym_index, |
| 2434 | 2465 | .relocation_type = .R_WASM_MEMORY_ADDR_I32, |
| 2435 | 2466 | .offset = offset, |
| 2436 | 2467 | .addend = @intCast(i32, addend), |
| ... | ... | @@ -2449,61 +2480,53 @@ fn populateErrorNameTable(wasm: *Wasm) !void { |
| 2449 | 2480 | |
| 2450 | 2481 | const name_loc = names_atom.symbolLoc(); |
| 2451 | 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 | 2485 | // link the atoms with the rest of the binary so they can be allocated |
| 2455 | 2486 | // and relocations will be performed. |
| 2456 | | try wasm.parseAtom(atom, .{ .data = .read_only }); |
| 2457 | | try wasm.parseAtom(names_atom, .{ .data = .read_only }); |
| 2487 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 2488 | try wasm.parseAtom(names_atom_index, .{ .data = .read_only }); |
| 2458 | 2489 | } |
| 2459 | 2490 | |
| 2460 | 2491 | /// From a given index variable, creates a new debug section. |
| 2461 | 2492 | /// This initializes the index, appends a new segment, |
| 2462 | 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 | 2495 | const new_index = @intCast(u32, wasm.segments.items.len); |
| 2465 | 2496 | index.* = new_index; |
| 2466 | 2497 | try wasm.appendDummySegment(); |
| 2467 | 2498 | |
| 2468 | | const sym_index = wasm.symbols_free_list.popOrNull() orelse idx: { |
| 2469 | | const tmp_index = @intCast(u32, wasm.symbols.items.len); |
| 2470 | | _ = try wasm.symbols.addOne(wasm.base.allocator); |
| 2471 | | break :idx tmp_index; |
| 2472 | | }; |
| 2473 | | wasm.symbols.items[sym_index] = .{ |
| 2499 | const atom_index = try wasm.createAtom(); |
| 2500 | const atom = wasm.getAtomPtr(atom_index); |
| 2501 | wasm.symbols.items[atom.sym_index] = .{ |
| 2474 | 2502 | .tag = .section, |
| 2475 | 2503 | .name = try wasm.string_table.put(wasm.base.allocator, name), |
| 2476 | 2504 | .index = 0, |
| 2477 | 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 | 2508 | atom.alignment = 1; // debug sections are always 1-byte-aligned |
| 2483 | | atom.sym_index = sym_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; |
| 2509 | return atom_index; |
| 2487 | 2510 | } |
| 2488 | 2511 | |
| 2489 | 2512 | fn resetState(wasm: *Wasm) void { |
| 2490 | 2513 | for (wasm.segment_info.values()) |segment_info| { |
| 2491 | 2514 | wasm.base.allocator.free(segment_info.name); |
| 2492 | 2515 | } |
| 2493 | | if (wasm.base.options.module) |mod| { |
| 2494 | | var decl_it = wasm.decls.keyIterator(); |
| 2495 | | while (decl_it.next()) |decl_index_ptr| { |
| 2496 | | const decl = mod.declPtr(decl_index_ptr.*); |
| 2497 | | const atom = &decl.link.wasm; |
| 2498 | | atom.next = null; |
| 2499 | | atom.prev = null; |
| 2500 | | |
| 2501 | | for (atom.locals.items) |*local_atom| { |
| 2502 | | local_atom.next = null; |
| 2503 | | local_atom.prev = null; |
| 2504 | | } |
| 2516 | |
| 2517 | var atom_it = wasm.decls.valueIterator(); |
| 2518 | while (atom_it.next()) |atom_index| { |
| 2519 | const atom = wasm.getAtomPtr(atom_index.*); |
| 2520 | atom.next = null; |
| 2521 | atom.prev = null; |
| 2522 | |
| 2523 | for (atom.locals.items) |local_atom_index| { |
| 2524 | const local_atom = wasm.getAtomPtr(local_atom_index); |
| 2525 | local_atom.next = null; |
| 2526 | local_atom.prev = null; |
| 2505 | 2527 | } |
| 2506 | 2528 | } |
| 2529 | |
| 2507 | 2530 | wasm.functions.clearRetainingCapacity(); |
| 2508 | 2531 | wasm.exports.clearRetainingCapacity(); |
| 2509 | 2532 | wasm.segments.clearRetainingCapacity(); |
| ... | ... | @@ -2800,28 +2823,29 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2800 | 2823 | try wasm.setupStart(); |
| 2801 | 2824 | try wasm.setupImports(); |
| 2802 | 2825 | if (wasm.base.options.module) |mod| { |
| 2803 | | var decl_it = wasm.decls.keyIterator(); |
| 2804 | | while (decl_it.next()) |decl_index_ptr| { |
| 2805 | | const decl = mod.declPtr(decl_index_ptr.*); |
| 2826 | var decl_it = wasm.decls.iterator(); |
| 2827 | while (decl_it.next()) |entry| { |
| 2828 | const decl = mod.declPtr(entry.key_ptr.*); |
| 2806 | 2829 | if (decl.isExtern()) continue; |
| 2807 | | const atom = &decl.*.link.wasm; |
| 2830 | const atom_index = entry.value_ptr.*; |
| 2808 | 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 | 2833 | } else if (decl.getVariable()) |variable| { |
| 2811 | 2834 | if (!variable.is_mutable) { |
| 2812 | | try wasm.parseAtom(atom, .{ .data = .read_only }); |
| 2835 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 2813 | 2836 | } else if (variable.init.isUndefDeep()) { |
| 2814 | | try wasm.parseAtom(atom, .{ .data = .uninitialized }); |
| 2837 | try wasm.parseAtom(atom_index, .{ .data = .uninitialized }); |
| 2815 | 2838 | } else { |
| 2816 | | try wasm.parseAtom(atom, .{ .data = .initialized }); |
| 2839 | try wasm.parseAtom(atom_index, .{ .data = .initialized }); |
| 2817 | 2840 | } |
| 2818 | 2841 | } else { |
| 2819 | | try wasm.parseAtom(atom, .{ .data = .read_only }); |
| 2842 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 2820 | 2843 | } |
| 2821 | 2844 | |
| 2822 | 2845 | // also parse atoms for a decl's locals |
| 2823 | | for (atom.locals.items) |*local_atom| { |
| 2824 | | try wasm.parseAtom(local_atom, .{ .data = .read_only }); |
| 2846 | const atom = wasm.getAtomPtr(atom_index); |
| 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 | 3090 | var code_section_size: u32 = 0; |
| 3067 | 3091 | if (wasm.code_section_index) |code_index| { |
| 3068 | 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 | 3095 | // The code section must be sorted in line with the function order. |
| 3072 | 3096 | var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count()); |
| 3073 | 3097 | defer sorted_atoms.deinit(); |
| 3074 | 3098 | |
| 3075 | 3099 | while (true) { |
| 3100 | var atom = wasm.getAtomPtr(atom_index); |
| 3076 | 3101 | if (wasm.resolved_symbols.contains(atom.symbolLoc())) { |
| 3077 | 3102 | if (!is_obj) { |
| 3078 | 3103 | atom.resolveRelocs(wasm); |
| 3079 | 3104 | } |
| 3080 | 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 | 3111 | const atom_sort_fn = struct { |
| ... | ... | @@ -3119,11 +3145,11 @@ fn writeToFile( |
| 3119 | 3145 | // do not output 'bss' section unless we import memory and therefore |
| 3120 | 3146 | // want to guarantee the data is zero initialized |
| 3121 | 3147 | if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue; |
| 3122 | | const atom_index = entry.value_ptr.*; |
| 3123 | | const segment = wasm.segments.items[atom_index]; |
| 3148 | const segment_index = entry.value_ptr.*; |
| 3149 | const segment = wasm.segments.items[segment_index]; |
| 3124 | 3150 | if (segment.size == 0) continue; // do not emit empty segments |
| 3125 | 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 | 3154 | // flag and index to memory section (currently, there can only be 1 memory section in wasm) |
| 3129 | 3155 | try leb.writeULEB128(binary_writer, @as(u32, 0)); |
| ... | ... | @@ -3134,6 +3160,7 @@ fn writeToFile( |
| 3134 | 3160 | // fill in the offset table and the data segments |
| 3135 | 3161 | var current_offset: u32 = 0; |
| 3136 | 3162 | while (true) { |
| 3163 | const atom = wasm.getAtomPtr(atom_index); |
| 3137 | 3164 | if (!is_obj) { |
| 3138 | 3165 | atom.resolveRelocs(wasm); |
| 3139 | 3166 | } |
| ... | ... | @@ -3149,8 +3176,8 @@ fn writeToFile( |
| 3149 | 3176 | try binary_writer.writeAll(atom.code.items); |
| 3150 | 3177 | |
| 3151 | 3178 | current_offset += atom.size; |
| 3152 | | if (atom.next) |next| { |
| 3153 | | atom = next; |
| 3179 | if (atom.prev) |prev| { |
| 3180 | atom_index = prev; |
| 3154 | 3181 | } else { |
| 3155 | 3182 | // also pad with zeroes when last atom to ensure |
| 3156 | 3183 | // segments are aligned. |
| ... | ... | @@ -3192,15 +3219,15 @@ fn writeToFile( |
| 3192 | 3219 | } |
| 3193 | 3220 | |
| 3194 | 3221 | if (!wasm.base.options.strip) { |
| 3195 | | if (wasm.dwarf) |*dwarf| { |
| 3196 | | const mod = wasm.base.options.module.?; |
| 3197 | | try dwarf.writeDbgAbbrev(); |
| 3198 | | // for debug info and ranges, the address is always 0, |
| 3199 | | // as locations are always offsets relative to 'code' section. |
| 3200 | | try dwarf.writeDbgInfoHeader(mod, 0, code_section_size); |
| 3201 | | try dwarf.writeDbgAranges(0, code_section_size); |
| 3202 | | try dwarf.writeDbgLineHeader(); |
| 3203 | | } |
| 3222 | // if (wasm.dwarf) |*dwarf| { |
| 3223 | // const mod = wasm.base.options.module.?; |
| 3224 | // try dwarf.writeDbgAbbrev(); |
| 3225 | // // for debug info and ranges, the address is always 0, |
| 3226 | // // as locations are always offsets relative to 'code' section. |
| 3227 | // try dwarf.writeDbgInfoHeader(mod, 0, code_section_size); |
| 3228 | // try dwarf.writeDbgAranges(0, code_section_size); |
| 3229 | // try dwarf.writeDbgLineHeader(); |
| 3230 | // } |
| 3204 | 3231 | |
| 3205 | 3232 | var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator); |
| 3206 | 3233 | defer debug_bytes.deinit(); |
| ... | ... | @@ -3223,11 +3250,11 @@ fn writeToFile( |
| 3223 | 3250 | |
| 3224 | 3251 | for (debug_sections) |item| { |
| 3225 | 3252 | if (item.index) |index| { |
| 3226 | | var atom = wasm.atoms.get(index).?.getFirst(); |
| 3253 | var atom = wasm.getAtomPtr(wasm.atoms.get(index).?); |
| 3227 | 3254 | while (true) { |
| 3228 | 3255 | atom.resolveRelocs(wasm); |
| 3229 | 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 | 3259 | try emitDebugSection(&binary_bytes, debug_bytes.items, item.name); |
| 3233 | 3260 | debug_bytes.clearRetainingCapacity(); |
| ... | ... | @@ -3959,7 +3986,8 @@ fn emitSymbolTable(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: |
| 3959 | 3986 | |
| 3960 | 3987 | if (symbol.isDefined()) { |
| 3961 | 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 | 3991 | try leb.writeULEB128(writer, @as(u32, atom.offset)); |
| 3964 | 3992 | try leb.writeULEB128(writer, @as(u32, atom.size)); |
| 3965 | 3993 | } |
| ... | ... | @@ -4037,7 +4065,7 @@ fn emitCodeRelocations( |
| 4037 | 4065 | const reloc_start = binary_bytes.items.len; |
| 4038 | 4066 | |
| 4039 | 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 | 4069 | // for each atom, we calculate the uleb size and append that |
| 4042 | 4070 | var size_offset: u32 = 5; // account for code section size leb128 |
| 4043 | 4071 | while (true) { |
| ... | ... | @@ -4055,7 +4083,7 @@ fn emitCodeRelocations( |
| 4055 | 4083 | } |
| 4056 | 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 | 4088 | if (count == 0) return; |
| 4061 | 4089 | var buf: [5]u8 = undefined; |
| ... | ... | @@ -4086,7 +4114,7 @@ fn emitDataRelocations( |
| 4086 | 4114 | // for each atom, we calculate the uleb size and append that |
| 4087 | 4115 | var size_offset: u32 = 5; // account for code section size leb128 |
| 4088 | 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 | 4118 | while (true) { |
| 4091 | 4119 | size_offset += getULEB128Size(atom.size); |
| 4092 | 4120 | for (atom.relocs.items) |relocation| { |
| ... | ... | @@ -4105,7 +4133,7 @@ fn emitDataRelocations( |
| 4105 | 4133 | } |
| 4106 | 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 | 4139 | if (count == 0) return; |