| ... | @@ -37,12 +37,22 @@ pub const Relocation = types.Relocation; | ... | @@ -37,12 +37,22 @@ pub const Relocation = types.Relocation; |
| 37 | pub const base_tag: link.File.Tag = .wasm; | 37 | pub const base_tag: link.File.Tag = .wasm; |
| 38 | | 38 | |
| 39 | base: link.File, | 39 | base: link.File, |
| | 40 | /// Symbol name of the entry function to export |
| 40 | entry_name: ?[]const u8, | 41 | entry_name: ?[]const u8, |
| | 42 | /// When true, will allow undefined symbols |
| 41 | import_symbols: bool, | 43 | import_symbols: bool, |
| | 44 | /// List of *global* symbol names to export to the host environment. |
| 42 | export_symbol_names: []const []const u8, | 45 | export_symbol_names: []const []const u8, |
| | 46 | /// When defined, sets the start of the data section. |
| 43 | global_base: ?u64, | 47 | global_base: ?u64, |
| | 48 | /// When defined, sets the initial memory size of the memory. |
| 44 | initial_memory: ?u64, | 49 | initial_memory: ?u64, |
| | 50 | /// When defined, sets the maximum memory size of the memory. |
| 45 | max_memory: ?u64, | 51 | max_memory: ?u64, |
| | 52 | /// When true, will import the function table from the host environment. |
| | 53 | import_table: bool, |
| | 54 | /// When true, will export the function table to the host environment. |
| | 55 | export_table: bool, |
| 46 | /// Output name of the file | 56 | /// Output name of the file |
| 47 | name: []const u8, | 57 | name: []const u8, |
| 48 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. | 58 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. |
| ... | @@ -52,16 +62,8 @@ llvm_object: ?*LlvmObject = null, | ... | @@ -52,16 +62,8 @@ llvm_object: ?*LlvmObject = null, |
| 52 | /// to support existing code. | 62 | /// to support existing code. |
| 53 | /// TODO: Allow setting this through a flag? | 63 | /// TODO: Allow setting this through a flag? |
| 54 | host_name: []const u8 = "env", | 64 | host_name: []const u8 = "env", |
| 55 | /// List of all `Decl` that are currently alive. | | |
| 56 | /// Each index maps to the corresponding `Atom.Index`. | | |
| 57 | decls: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Atom.Index) = .{}, | | |
| 58 | /// Mapping between an `Atom` and its type index representing the Wasm | | |
| 59 | /// type of the function signature. | | |
| 60 | atom_types: std.AutoHashMapUnmanaged(Atom.Index, u32) = .{}, | | |
| 61 | /// List of all symbols generated by Zig code. | 65 | /// List of all symbols generated by Zig code. |
| 62 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | 66 | synthetic_symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 63 | /// List of symbol indexes which are free to be used. | | |
| 64 | symbols_free_list: std.ArrayListUnmanaged(u32) = .{}, | | |
| 65 | /// Maps atoms to their segment index | 67 | /// Maps atoms to their segment index |
| 66 | atoms: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, | 68 | atoms: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 67 | /// List of all atoms. | 69 | /// List of all atoms. |
| ... | @@ -107,8 +109,6 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{}, | ... | @@ -107,8 +109,6 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{}, |
| 107 | segment_info: std.AutoArrayHashMapUnmanaged(u32, types.Segment) = .{}, | 109 | segment_info: std.AutoArrayHashMapUnmanaged(u32, types.Segment) = .{}, |
| 108 | /// Deduplicated string table for strings used by symbols, imports and exports. | 110 | /// Deduplicated string table for strings used by symbols, imports and exports. |
| 109 | string_table: StringTable = .{}, | 111 | string_table: StringTable = .{}, |
| 110 | /// Debug information for wasm | | |
| 111 | dwarf: ?Dwarf = null, | | |
| 112 | | 112 | |
| 113 | // Output sections | 113 | // Output sections |
| 114 | /// Output type section | 114 | /// Output type section |
| ... | @@ -170,36 +170,10 @@ symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, Atom.Index) = .{}, | ... | @@ -170,36 +170,10 @@ symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, Atom.Index) = .{}, |
| 170 | /// Note: The value represents the offset into the string table, rather than the actual string. | 170 | /// Note: The value represents the offset into the string table, rather than the actual string. |
| 171 | export_names: std.AutoHashMapUnmanaged(SymbolLoc, u32) = .{}, | 171 | export_names: std.AutoHashMapUnmanaged(SymbolLoc, u32) = .{}, |
| 172 | | 172 | |
| 173 | /// Represents the symbol index of the error name table | | |
| 174 | /// When this is `null`, no code references an error using runtime `@errorName`. | | |
| 175 | /// During initializion, a symbol with corresponding atom will be created that is | | |
| 176 | /// used to perform relocations to the pointer of this table. | | |
| 177 | /// The actual table is populated during `flush`. | | |
| 178 | error_table_symbol: ?u32 = null, | | |
| 179 | | | |
| 180 | // Debug section atoms. These are only set when the current compilation | | |
| 181 | // unit contains Zig code. The lifetime of these atoms are extended | | |
| 182 | // until the end of the compiler's lifetime. Meaning they're not freed | | |
| 183 | // during `flush()` in incremental-mode. | | |
| 184 | debug_info_atom: ?Atom.Index = null, | | |
| 185 | debug_line_atom: ?Atom.Index = null, | | |
| 186 | debug_loc_atom: ?Atom.Index = null, | | |
| 187 | debug_ranges_atom: ?Atom.Index = null, | | |
| 188 | debug_abbrev_atom: ?Atom.Index = null, | | |
| 189 | debug_str_atom: ?Atom.Index = null, | | |
| 190 | debug_pubnames_atom: ?Atom.Index = null, | | |
| 191 | debug_pubtypes_atom: ?Atom.Index = null, | | |
| 192 | | | |
| 193 | /// List of atom indexes of functions that are generated by the backend, | 173 | /// List of atom indexes of functions that are generated by the backend, |
| 194 | /// rather than by the linker. | 174 | /// rather than by the linker. |
| 195 | synthetic_functions: std.ArrayListUnmanaged(Atom.Index) = .{}, | 175 | synthetic_functions: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 196 | | 176 | |
| 197 | /// Map for storing anonymous declarations. Each anonymous decl maps to its Atom's index. | | |
| 198 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Atom.Index) = .{}, | | |
| 199 | | | |
| 200 | import_table: bool, | | |
| 201 | export_table: bool, | | |
| 202 | | | |
| 203 | pub const Alignment = types.Alignment; | 177 | pub const Alignment = types.Alignment; |
| 204 | | 178 | |
| 205 | pub const Segment = struct { | 179 | pub const Segment = struct { |
| ... | @@ -238,27 +212,27 @@ pub const SymbolLoc = struct { | ... | @@ -238,27 +212,27 @@ pub const SymbolLoc = struct { |
| 238 | file: ?u16, | 212 | file: ?u16, |
| 239 | | 213 | |
| 240 | /// From a given location, returns the corresponding symbol in the wasm binary | 214 | /// From a given location, returns the corresponding symbol in the wasm binary |
| 241 | pub fn getSymbol(loc: SymbolLoc, wasm_bin: *const Wasm) *Symbol { | 215 | pub fn getSymbol(loc: SymbolLoc, wasm_file: *const Wasm) *Symbol { |
| 242 | if (wasm_bin.discarded.get(loc)) |new_loc| { | 216 | if (wasm_file.discarded.get(loc)) |new_loc| { |
| 243 | return new_loc.getSymbol(wasm_bin); | 217 | return new_loc.getSymbol(wasm_file); |
| 244 | } | 218 | } |
| 245 | if (loc.file) |object_index| { | 219 | if (loc.file) |object_index| { |
| 246 | const object = wasm_bin.objects.items[object_index]; | 220 | const object = wasm_file.objects.items[object_index]; |
| 247 | return &object.symtable[loc.index]; | 221 | return &object.symtable[loc.index]; |
| 248 | } | 222 | } |
| 249 | return &wasm_bin.symbols.items[loc.index]; | 223 | return &wasm_file.synthetic_symbols.items[loc.index]; |
| 250 | } | 224 | } |
| 251 | | 225 | |
| 252 | /// From a given location, returns the name of the symbol. | 226 | /// From a given location, returns the name of the symbol. |
| 253 | pub fn getName(loc: SymbolLoc, wasm_bin: *const Wasm) []const u8 { | 227 | pub fn getName(loc: SymbolLoc, wasm_file: *const Wasm) []const u8 { |
| 254 | if (wasm_bin.discarded.get(loc)) |new_loc| { | 228 | if (wasm_file.discarded.get(loc)) |new_loc| { |
| 255 | return new_loc.getName(wasm_bin); | 229 | return new_loc.getName(wasm_file); |
| 256 | } | 230 | } |
| 257 | if (loc.file) |object_index| { | 231 | if (loc.file) |object_index| { |
| 258 | const object = wasm_bin.objects.items[object_index]; | 232 | const object = wasm_file.objects.items[object_index]; |
| 259 | return object.string_table.get(object.symtable[loc.index].name); | 233 | return object.string_table.get(object.symtable[loc.index].name); |
| 260 | } | 234 | } |
| 261 | return wasm_bin.string_table.get(wasm_bin.symbols.items[loc.index].name); | 235 | return wasm_file.string_table.get(wasm_file.synthetic_symbols.items[loc.index].name); |
| 262 | } | 236 | } |
| 263 | | 237 | |
| 264 | /// From a given symbol location, returns the final location. | 238 | /// From a given symbol location, returns the final location. |
| ... | @@ -266,9 +240,9 @@ pub const SymbolLoc = struct { | ... | @@ -266,9 +240,9 @@ pub const SymbolLoc = struct { |
| 266 | /// in a different file, this will return said location. | 240 | /// in a different file, this will return said location. |
| 267 | /// If the symbol wasn't replaced by another, this will return | 241 | /// If the symbol wasn't replaced by another, this will return |
| 268 | /// the given location itwasm. | 242 | /// the given location itwasm. |
| 269 | pub fn finalLoc(loc: SymbolLoc, wasm_bin: *const Wasm) SymbolLoc { | 243 | pub fn finalLoc(loc: SymbolLoc, wasm_file: *const Wasm) SymbolLoc { |
| 270 | if (wasm_bin.discarded.get(loc)) |new_loc| { | 244 | if (wasm_file.discarded.get(loc)) |new_loc| { |
| 271 | return new_loc.finalLoc(wasm_bin); | 245 | return new_loc.finalLoc(wasm_file); |
| 272 | } | 246 | } |
| 273 | return loc; | 247 | return loc; |
| 274 | } | 248 | } |
| ... | @@ -594,10 +568,10 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol | ... | @@ -594,10 +568,10 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol |
| 594 | } | 568 | } |
| 595 | | 569 | |
| 596 | fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc { | 570 | fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc { |
| 597 | const sym_index = @as(u32, @intCast(wasm.symbols.items.len)); | 571 | const sym_index = @as(u32, @intCast(wasm.synthetic_symbols.items.len)); |
| 598 | const loc: SymbolLoc = .{ .index = sym_index, .file = null }; | 572 | const loc: SymbolLoc = .{ .index = sym_index, .file = null }; |
| 599 | const gpa = wasm.base.comp.gpa; | 573 | const gpa = wasm.base.comp.gpa; |
| 600 | try wasm.symbols.append(gpa, .{ | 574 | try wasm.synthetic_symbols.append(gpa, .{ |
| 601 | .name = name_offset, | 575 | .name = name_offset, |
| 602 | .flags = 0, | 576 | .flags = 0, |
| 603 | .tag = tag, | 577 | .tag = tag, |
| ... | @@ -609,24 +583,6 @@ fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) ! | ... | @@ -609,24 +583,6 @@ fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) ! |
| 609 | return loc; | 583 | return loc; |
| 610 | } | 584 | } |
| 611 | | 585 | |
| 612 | /// Initializes symbols and atoms for the debug sections | | |
| 613 | /// Initialization is only done when compiling Zig code. | | |
| 614 | /// When Zig is invoked as a linker instead, the atoms | | |
| 615 | /// and symbols come from the object files instead. | | |
| 616 | pub fn initDebugSections(wasm: *Wasm) !void { | | |
| 617 | if (wasm.dwarf == null) return; // not compiling Zig code, so no need to pre-initialize debug sections | | |
| 618 | assert(wasm.debug_info_index == null); | | |
| 619 | // this will create an Atom and set the index for us. | | |
| 620 | wasm.debug_info_atom = try wasm.createDebugSectionForIndex(&wasm.debug_info_index, ".debug_info"); | | |
| 621 | wasm.debug_line_atom = try wasm.createDebugSectionForIndex(&wasm.debug_line_index, ".debug_line"); | | |
| 622 | wasm.debug_loc_atom = try wasm.createDebugSectionForIndex(&wasm.debug_loc_index, ".debug_loc"); | | |
| 623 | wasm.debug_abbrev_atom = try wasm.createDebugSectionForIndex(&wasm.debug_abbrev_index, ".debug_abbrev"); | | |
| 624 | wasm.debug_ranges_atom = try wasm.createDebugSectionForIndex(&wasm.debug_ranges_index, ".debug_ranges"); | | |
| 625 | wasm.debug_str_atom = try wasm.createDebugSectionForIndex(&wasm.debug_str_index, ".debug_str"); | | |
| 626 | wasm.debug_pubnames_atom = try wasm.createDebugSectionForIndex(&wasm.debug_pubnames_index, ".debug_pubnames"); | | |
| 627 | wasm.debug_pubtypes_atom = try wasm.createDebugSectionForIndex(&wasm.debug_pubtypes_index, ".debug_pubtypes"); | | |
| 628 | } | | |
| 629 | | | |
| 630 | fn parseInputFiles(wasm: *Wasm, files: []const []const u8) !void { | 586 | fn parseInputFiles(wasm: *Wasm, files: []const []const u8) !void { |
| 631 | for (files) |path| { | 587 | for (files) |path| { |
| 632 | if (try wasm.parseObjectFile(path)) continue; | 588 | if (try wasm.parseObjectFile(path)) continue; |
| ... | @@ -652,33 +608,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool { | ... | @@ -652,33 +608,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool { |
| 652 | return true; | 608 | return true; |
| 653 | } | 609 | } |
| 654 | | 610 | |
| 655 | /// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`. | | |
| 656 | /// When the index was not found, a new `Atom` will be created, and its index will be returned. | | |
| 657 | /// The newly created Atom is empty with default fields as specified by `Atom.empty`. | | |
| 658 | pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) !Atom.Index { | | |
| 659 | const gpa = wasm.base.comp.gpa; | | |
| 660 | const gop = try wasm.decls.getOrPut(gpa, decl_index); | | |
| 661 | if (!gop.found_existing) { | | |
| 662 | const atom_index = try wasm.createAtom(); | | |
| 663 | gop.value_ptr.* = atom_index; | | |
| 664 | const atom = wasm.getAtom(atom_index); | | |
| 665 | const symbol = atom.symbolLoc().getSymbol(wasm); | | |
| 666 | const mod = wasm.base.comp.module.?; | | |
| 667 | const decl = mod.declPtr(decl_index); | | |
| 668 | const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); | | |
| 669 | symbol.name = try wasm.string_table.put(gpa, full_name); | | |
| 670 | } | | |
| 671 | return gop.value_ptr.*; | | |
| 672 | } | | |
| 673 | | | |
| 674 | /// Creates a new empty `Atom` and returns its `Atom.Index` | 611 | /// Creates a new empty `Atom` and returns its `Atom.Index` |
| 675 | fn createAtom(wasm: *Wasm) !Atom.Index { | 612 | pub fn createAtom(wasm: *Wasm, sym_index: u32) !Atom.Index { |
| 676 | const gpa = wasm.base.comp.gpa; | 613 | const gpa = wasm.base.comp.gpa; |
| 677 | const index: Atom.Index = @intCast(wasm.managed_atoms.items.len); | 614 | const index: Atom.Index = @intCast(wasm.managed_atoms.items.len); |
| 678 | const atom = try wasm.managed_atoms.addOne(gpa); | 615 | const atom = try wasm.managed_atoms.addOne(gpa); |
| 679 | atom.* = Atom.empty; | 616 | atom.* = Atom.empty; |
| 680 | atom.sym_index = try wasm.allocateSymbol(); | 617 | atom.sym_index = sym_index; |
| 681 | try wasm.symbol_atom.putNoClobber(gpa, .{ .file = null, .index = atom.sym_index }, index); | 618 | try wasm.symbol_atom.putNoClobber(gpa, .{ .file = null, .index = sym_index }, index); |
| 682 | | 619 | |
| 683 | return index; | 620 | return index; |
| 684 | } | 621 | } |
| ... | @@ -1386,40 +1323,12 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -1386,40 +1323,12 @@ pub fn deinit(wasm: *Wasm) void { |
| 1386 | archive.deinit(gpa); | 1323 | archive.deinit(gpa); |
| 1387 | } | 1324 | } |
| 1388 | | 1325 | |
| 1389 | // For decls and anon decls we free the memory of its atoms. | | |
| 1390 | // The memory of atoms parsed from object files is managed by | | |
| 1391 | // the object file itself, and therefore we can skip those. | | |
| 1392 | { | | |
| 1393 | var it = wasm.decls.valueIterator(); | | |
| 1394 | while (it.next()) |atom_index_ptr| { | | |
| 1395 | const atom = wasm.getAtomPtr(atom_index_ptr.*); | | |
| 1396 | for (atom.locals.items) |local_index| { | | |
| 1397 | const local_atom = wasm.getAtomPtr(local_index); | | |
| 1398 | local_atom.deinit(gpa); | | |
| 1399 | } | | |
| 1400 | atom.deinit(gpa); | | |
| 1401 | } | | |
| 1402 | } | | |
| 1403 | { | | |
| 1404 | for (wasm.anon_decls.values()) |atom_index| { | | |
| 1405 | const atom = wasm.getAtomPtr(atom_index); | | |
| 1406 | for (atom.locals.items) |local_index| { | | |
| 1407 | const local_atom = wasm.getAtomPtr(local_index); | | |
| 1408 | local_atom.deinit(gpa); | | |
| 1409 | } | | |
| 1410 | atom.deinit(gpa); | | |
| 1411 | } | | |
| 1412 | } | | |
| 1413 | for (wasm.synthetic_functions.items) |atom_index| { | 1326 | for (wasm.synthetic_functions.items) |atom_index| { |
| 1414 | const atom = wasm.getAtomPtr(atom_index); | 1327 | const atom = wasm.getAtomPtr(atom_index); |
| 1415 | atom.deinit(gpa); | 1328 | atom.deinit(gpa); |
| 1416 | } | 1329 | } |
| 1417 | | 1330 | |
| 1418 | wasm.decls.deinit(gpa); | 1331 | wasm.synthetic_symbols.deinit(gpa); |
| 1419 | wasm.anon_decls.deinit(gpa); | | |
| 1420 | wasm.atom_types.deinit(gpa); | | |
| 1421 | wasm.symbols.deinit(gpa); | | |
| 1422 | wasm.symbols_free_list.deinit(gpa); | | |
| 1423 | wasm.globals.deinit(gpa); | 1332 | wasm.globals.deinit(gpa); |
| 1424 | wasm.resolved_symbols.deinit(gpa); | 1333 | wasm.resolved_symbols.deinit(gpa); |
| 1425 | wasm.undefs.deinit(gpa); | 1334 | wasm.undefs.deinit(gpa); |
| ... | @@ -1446,32 +1355,6 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -1446,32 +1355,6 @@ pub fn deinit(wasm: *Wasm) void { |
| 1446 | | 1355 | |
| 1447 | wasm.string_table.deinit(gpa); | 1356 | wasm.string_table.deinit(gpa); |
| 1448 | wasm.synthetic_functions.deinit(gpa); | 1357 | wasm.synthetic_functions.deinit(gpa); |
| 1449 | | | |
| 1450 | if (wasm.dwarf) |*dwarf| { | | |
| 1451 | dwarf.deinit(); | | |
| 1452 | } | | |
| 1453 | } | | |
| 1454 | | | |
| 1455 | /// Allocates a new symbol and returns its index. | | |
| 1456 | /// Will re-use slots when a symbol was freed at an earlier stage. | | |
| 1457 | pub fn allocateSymbol(wasm: *Wasm) !u32 { | | |
| 1458 | const gpa = wasm.base.comp.gpa; | | |
| 1459 | | | |
| 1460 | try wasm.symbols.ensureUnusedCapacity(gpa, 1); | | |
| 1461 | const symbol: Symbol = .{ | | |
| 1462 | .name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls | | |
| 1463 | .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | | |
| 1464 | .tag = .undefined, // will be set after updateDecl | | |
| 1465 | .index = std.math.maxInt(u32), // will be set during atom parsing | | |
| 1466 | .virtual_address = std.math.maxInt(u32), // will be set during atom allocation | | |
| 1467 | }; | | |
| 1468 | if (wasm.symbols_free_list.popOrNull()) |index| { | | |
| 1469 | wasm.symbols.items[index] = symbol; | | |
| 1470 | return index; | | |
| 1471 | } | | |
| 1472 | const index = @as(u32, @intCast(wasm.symbols.items.len)); | | |
| 1473 | wasm.symbols.appendAssumeCapacity(symbol); | | |
| 1474 | return index; | | |
| 1475 | } | 1358 | } |
| 1476 | | 1359 | |
| 1477 | pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { | 1360 | pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| ... | @@ -1546,84 +1429,12 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) ! | ... | @@ -1546,84 +1429,12 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) ! |
| 1546 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 1429 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1547 | } | 1430 | } |
| 1548 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index); | 1431 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index); |
| 1549 | | | |
| 1550 | const tracy = trace(@src()); | | |
| 1551 | defer tracy.end(); | | |
| 1552 | | | |
| 1553 | const decl = mod.declPtr(decl_index); | | |
| 1554 | if (decl.val.getFunction(mod)) |_| { | | |
| 1555 | return; | | |
| 1556 | } else if (decl.val.getExternFunc(mod)) |_| { | | |
| 1557 | return; | | |
| 1558 | } | | |
| 1559 | | | |
| 1560 | const gpa = wasm.base.comp.gpa; | | |
| 1561 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); | | |
| 1562 | const atom = wasm.getAtomPtr(atom_index); | | |
| 1563 | atom.clear(); | | |
| 1564 | | | |
| 1565 | if (decl.isExtern(mod)) { | | |
| 1566 | const variable = decl.getOwnedVariable(mod).?; | | |
| 1567 | const name = mod.intern_pool.stringToSlice(decl.name); | | |
| 1568 | const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); | | |
| 1569 | return wasm.addOrUpdateImport(name, atom.sym_index, lib_name, null); | | |
| 1570 | } | | |
| 1571 | const val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; | | |
| 1572 | | | |
| 1573 | var code_writer = std.ArrayList(u8).init(gpa); | | |
| 1574 | defer code_writer.deinit(); | | |
| 1575 | | | |
| 1576 | const res = try codegen.generateSymbol( | | |
| 1577 | &wasm.base, | | |
| 1578 | decl.srcLoc(mod), | | |
| 1579 | .{ .ty = decl.ty, .val = val }, | | |
| 1580 | &code_writer, | | |
| 1581 | .none, | | |
| 1582 | .{ .parent_atom_index = atom.sym_index }, | | |
| 1583 | ); | | |
| 1584 | | | |
| 1585 | const code = switch (res) { | | |
| 1586 | .ok => code_writer.items, | | |
| 1587 | .fail => |em| { | | |
| 1588 | decl.analysis = .codegen_failure; | | |
| 1589 | try mod.failed_decls.put(mod.gpa, decl_index, em); | | |
| 1590 | return; | | |
| 1591 | }, | | |
| 1592 | }; | | |
| 1593 | | | |
| 1594 | return wasm.finishUpdateDecl(decl_index, code, .data); | | |
| 1595 | } | 1432 | } |
| 1596 | | 1433 | |
| 1597 | pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) !void { | 1434 | pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) !void { |
| 1598 | if (wasm.llvm_object) |_| return; | 1435 | if (wasm.llvm_object) |_| return; |
| 1599 | if (wasm.dwarf) |*dw| { | 1436 | _ = mod; |
| 1600 | const tracy = trace(@src()); | 1437 | _ = decl_index; |
| 1601 | defer tracy.end(); | | |
| 1602 | | | |
| 1603 | const decl = mod.declPtr(decl_index); | | |
| 1604 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); | | |
| 1605 | | | |
| 1606 | log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl }); | | |
| 1607 | try dw.updateDeclLineNumber(mod, decl_index); | | |
| 1608 | } | | |
| 1609 | } | | |
| 1610 | | | |
| 1611 | fn finishUpdateDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex, code: []const u8, symbol_tag: Symbol.Tag) !void { | | |
| 1612 | const gpa = wasm.base.comp.gpa; | | |
| 1613 | const mod = wasm.base.comp.module.?; | | |
| 1614 | const decl = mod.declPtr(decl_index); | | |
| 1615 | const atom_index = wasm.decls.get(decl_index).?; | | |
| 1616 | const atom = wasm.getAtomPtr(atom_index); | | |
| 1617 | const symbol = &wasm.symbols.items[atom.sym_index]; | | |
| 1618 | const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); | | |
| 1619 | symbol.name = try wasm.string_table.put(gpa, full_name); | | |
| 1620 | symbol.tag = symbol_tag; | | |
| 1621 | try atom.code.appendSlice(gpa, code); | | |
| 1622 | try wasm.resolved_symbols.put(gpa, atom.symbolLoc(), {}); | | |
| 1623 | | | |
| 1624 | atom.size = @intCast(code.len); | | |
| 1625 | if (code.len == 0) return; | | |
| 1626 | atom.alignment = decl.getAlignment(mod); | | |
| 1627 | } | 1438 | } |
| 1628 | | 1439 | |
| 1629 | /// From a given symbol location, returns its `wasm.GlobalType`. | 1440 | /// From a given symbol location, returns its `wasm.GlobalType`. |
| ... | @@ -1673,82 +1484,9 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { | ... | @@ -1673,82 +1484,9 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { |
| 1673 | /// Returns the symbol index of the local | 1484 | /// Returns the symbol index of the local |
| 1674 | /// The given `decl` is the parent decl whom owns the constant. | 1485 | /// The given `decl` is the parent decl whom owns the constant. |
| 1675 | pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { | 1486 | pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { |
| 1676 | const gpa = wasm.base.comp.gpa; | 1487 | _ = wasm; |
| 1677 | const mod = wasm.base.comp.module.?; | 1488 | _ = tv; |
| 1678 | assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions | 1489 | _ = decl_index; |
| 1679 | const decl = mod.declPtr(decl_index); | | |
| 1680 | | | |
| 1681 | const parent_atom_index = try wasm.getOrCreateAtomForDecl(decl_index); | | |
| 1682 | const parent_atom = wasm.getAtom(parent_atom_index); | | |
| 1683 | const local_index = parent_atom.locals.items.len; | | |
| 1684 | const fqn = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); | | |
| 1685 | const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{s}_{d}", .{ | | |
| 1686 | fqn, local_index, | | |
| 1687 | }); | | |
| 1688 | defer gpa.free(name); | | |
| 1689 | | | |
| 1690 | switch (try wasm.lowerConst(name, tv, decl.srcLoc(mod))) { | | |
| 1691 | .ok => |atom_index| { | | |
| 1692 | try wasm.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); | | |
| 1693 | return wasm.getAtom(atom_index).getSymbolIndex().?; | | |
| 1694 | }, | | |
| 1695 | .fail => |em| { | | |
| 1696 | decl.analysis = .codegen_failure; | | |
| 1697 | try mod.failed_decls.put(mod.gpa, decl_index, em); | | |
| 1698 | return error.CodegenFail; | | |
| 1699 | }, | | |
| 1700 | } | | |
| 1701 | } | | |
| 1702 | | | |
| 1703 | const LowerConstResult = union(enum) { | | |
| 1704 | ok: Atom.Index, | | |
| 1705 | fail: *Module.ErrorMsg, | | |
| 1706 | }; | | |
| 1707 | | | |
| 1708 | fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult { | | |
| 1709 | const gpa = wasm.base.comp.gpa; | | |
| 1710 | const mod = wasm.base.comp.module.?; | | |
| 1711 | | | |
| 1712 | // Create and initialize a new local symbol and atom | | |
| 1713 | const atom_index = try wasm.createAtom(); | | |
| 1714 | var value_bytes = std.ArrayList(u8).init(gpa); | | |
| 1715 | defer value_bytes.deinit(); | | |
| 1716 | | | |
| 1717 | const code = code: { | | |
| 1718 | const atom = wasm.getAtomPtr(atom_index); | | |
| 1719 | atom.alignment = tv.ty.abiAlignment(mod); | | |
| 1720 | wasm.symbols.items[atom.sym_index] = .{ | | |
| 1721 | .name = try wasm.string_table.put(gpa, name), | | |
| 1722 | .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | | |
| 1723 | .tag = .data, | | |
| 1724 | .index = undefined, | | |
| 1725 | .virtual_address = undefined, | | |
| 1726 | }; | | |
| 1727 | try wasm.resolved_symbols.putNoClobber(gpa, atom.symbolLoc(), {}); | | |
| 1728 | | | |
| 1729 | const result = try codegen.generateSymbol( | | |
| 1730 | &wasm.base, | | |
| 1731 | src_loc, | | |
| 1732 | tv, | | |
| 1733 | &value_bytes, | | |
| 1734 | .none, | | |
| 1735 | .{ | | |
| 1736 | .parent_atom_index = atom.sym_index, | | |
| 1737 | .addend = null, | | |
| 1738 | }, | | |
| 1739 | ); | | |
| 1740 | break :code switch (result) { | | |
| 1741 | .ok => value_bytes.items, | | |
| 1742 | .fail => |em| { | | |
| 1743 | return .{ .fail = em }; | | |
| 1744 | }, | | |
| 1745 | }; | | |
| 1746 | }; | | |
| 1747 | | | |
| 1748 | const atom = wasm.getAtomPtr(atom_index); | | |
| 1749 | atom.size = @intCast(code.len); | | |
| 1750 | try atom.code.appendSlice(gpa, code); | | |
| 1751 | return .{ .ok = atom_index }; | | |
| 1752 | } | 1490 | } |
| 1753 | | 1491 | |
| 1754 | /// Returns the symbol index from a symbol of which its flag is set global, | 1492 | /// Returns the symbol index from a symbol of which its flag is set global, |
| ... | @@ -1757,34 +1495,8 @@ fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.Src | ... | @@ -1757,34 +1495,8 @@ fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.Src |
| 1757 | /// and then returns the index to it. | 1495 | /// and then returns the index to it. |
| 1758 | pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u32 { | 1496 | pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u32 { |
| 1759 | _ = lib_name; | 1497 | _ = lib_name; |
| 1760 | const gpa = wasm.base.comp.gpa; | 1498 | _ = name; |
| 1761 | const name_index = try wasm.string_table.put(gpa, name); | 1499 | _ = wasm; |
| 1762 | const gop = try wasm.globals.getOrPut(gpa, name_index); | | |
| 1763 | if (gop.found_existing) { | | |
| 1764 | return gop.value_ptr.*.index; | | |
| 1765 | } | | |
| 1766 | | | |
| 1767 | var symbol: Symbol = .{ | | |
| 1768 | .name = name_index, | | |
| 1769 | .flags = 0, | | |
| 1770 | .index = undefined, // index to type will be set after merging function symbols | | |
| 1771 | .tag = .function, | | |
| 1772 | .virtual_address = undefined, | | |
| 1773 | }; | | |
| 1774 | symbol.setGlobal(true); | | |
| 1775 | symbol.setUndefined(true); | | |
| 1776 | | | |
| 1777 | const sym_index = if (wasm.symbols_free_list.popOrNull()) |index| index else blk: { | | |
| 1778 | const index: u32 = @intCast(wasm.symbols.items.len); | | |
| 1779 | try wasm.symbols.ensureUnusedCapacity(gpa, 1); | | |
| 1780 | wasm.symbols.items.len += 1; | | |
| 1781 | break :blk index; | | |
| 1782 | }; | | |
| 1783 | wasm.symbols.items[sym_index] = symbol; | | |
| 1784 | gop.value_ptr.* = .{ .index = sym_index, .file = null }; | | |
| 1785 | try wasm.resolved_symbols.put(gpa, gop.value_ptr.*, {}); | | |
| 1786 | try wasm.undefs.putNoClobber(gpa, name_index, gop.value_ptr.*); | | |
| 1787 | return sym_index; | | |
| 1788 | } | 1500 | } |
| 1789 | | 1501 | |
| 1790 | /// For a given decl, find the given symbol index's atom, and create a relocation for the type. | 1502 | /// For a given decl, find the given symbol index's atom, and create a relocation for the type. |
| ... | @@ -1794,42 +1506,9 @@ pub fn getDeclVAddr( | ... | @@ -1794,42 +1506,9 @@ pub fn getDeclVAddr( |
| 1794 | decl_index: InternPool.DeclIndex, | 1506 | decl_index: InternPool.DeclIndex, |
| 1795 | reloc_info: link.File.RelocInfo, | 1507 | reloc_info: link.File.RelocInfo, |
| 1796 | ) !u64 { | 1508 | ) !u64 { |
| 1797 | const target = wasm.base.comp.root_mod.resolved_target.result; | 1509 | _ = wasm; |
| 1798 | const gpa = wasm.base.comp.gpa; | 1510 | _ = decl_index; |
| 1799 | const mod = wasm.base.comp.module.?; | 1511 | _ = reloc_info; |
| 1800 | const decl = mod.declPtr(decl_index); | | |
| 1801 | | | |
| 1802 | const target_atom_index = try wasm.getOrCreateAtomForDecl(decl_index); | | |
| 1803 | const target_symbol_index = wasm.getAtom(target_atom_index).sym_index; | | |
| 1804 | | | |
| 1805 | assert(reloc_info.parent_atom_index != 0); | | |
| 1806 | const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; | | |
| 1807 | const atom = wasm.getAtomPtr(atom_index); | | |
| 1808 | const is_wasm32 = target.cpu.arch == .wasm32; | | |
| 1809 | if (decl.ty.zigTypeTag(mod) == .Fn) { | | |
| 1810 | assert(reloc_info.addend == 0); // addend not allowed for function relocations | | |
| 1811 | // We found a function pointer, so add it to our table, | | |
| 1812 | // as function pointers are not allowed to be stored inside the data section. | | |
| 1813 | // They are instead stored in a function table which are called by index. | | |
| 1814 | try wasm.addTableFunction(target_symbol_index); | | |
| 1815 | try atom.relocs.append(gpa, .{ | | |
| 1816 | .index = target_symbol_index, | | |
| 1817 | .offset = @intCast(reloc_info.offset), | | |
| 1818 | .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64, | | |
| 1819 | }); | | |
| 1820 | } else { | | |
| 1821 | try atom.relocs.append(gpa, .{ | | |
| 1822 | .index = target_symbol_index, | | |
| 1823 | .offset = @intCast(reloc_info.offset), | | |
| 1824 | .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64, | | |
| 1825 | .addend = @intCast(reloc_info.addend), | | |
| 1826 | }); | | |
| 1827 | } | | |
| 1828 | // we do not know the final address at this point, | | |
| 1829 | // as atom allocation will determine the address and relocations | | |
| 1830 | // will calculate and rewrite this. Therefore, we simply return the symbol index | | |
| 1831 | // that was targeted. | | |
| 1832 | return target_symbol_index; | | |
| 1833 | } | 1512 | } |
| 1834 | | 1513 | |
| 1835 | pub fn lowerAnonDecl( | 1514 | pub fn lowerAnonDecl( |
| ... | @@ -1838,70 +1517,16 @@ pub fn lowerAnonDecl( | ... | @@ -1838,70 +1517,16 @@ pub fn lowerAnonDecl( |
| 1838 | explicit_alignment: Alignment, | 1517 | explicit_alignment: Alignment, |
| 1839 | src_loc: Module.SrcLoc, | 1518 | src_loc: Module.SrcLoc, |
| 1840 | ) !codegen.Result { | 1519 | ) !codegen.Result { |
| 1841 | const gpa = wasm.base.comp.gpa; | 1520 | _ = wasm; |
| 1842 | const gop = try wasm.anon_decls.getOrPut(gpa, decl_val); | 1521 | _ = decl_val; |
| 1843 | if (!gop.found_existing) { | 1522 | _ = explicit_alignment; |
| 1844 | const mod = wasm.base.comp.module.?; | 1523 | _ = src_loc; |
| 1845 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | | |
| 1846 | const tv: TypedValue = .{ .ty = ty, .val = Value.fromInterned(decl_val) }; | | |
| 1847 | var name_buf: [32]u8 = undefined; | | |
| 1848 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ | | |
| 1849 | @intFromEnum(decl_val), | | |
| 1850 | }) catch unreachable; | | |
| 1851 | | | |
| 1852 | switch (try wasm.lowerConst(name, tv, src_loc)) { | | |
| 1853 | .ok => |atom_index| wasm.anon_decls.values()[gop.index] = atom_index, | | |
| 1854 | .fail => |em| return .{ .fail = em }, | | |
| 1855 | } | | |
| 1856 | } | | |
| 1857 | | | |
| 1858 | const atom = wasm.getAtomPtr(wasm.anon_decls.values()[gop.index]); | | |
| 1859 | atom.alignment = switch (atom.alignment) { | | |
| 1860 | .none => explicit_alignment, | | |
| 1861 | else => switch (explicit_alignment) { | | |
| 1862 | .none => atom.alignment, | | |
| 1863 | else => atom.alignment.maxStrict(explicit_alignment), | | |
| 1864 | }, | | |
| 1865 | }; | | |
| 1866 | return .ok; | | |
| 1867 | } | 1524 | } |
| 1868 | | 1525 | |
| 1869 | pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | 1526 | pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 1870 | const gpa = wasm.base.comp.gpa; | 1527 | _ = wasm; |
| 1871 | const target = wasm.base.comp.root_mod.resolved_target.result; | 1528 | _ = decl_val; |
| 1872 | const atom_index = wasm.anon_decls.get(decl_val).?; | 1529 | _ = reloc_info; |
| 1873 | const target_symbol_index = wasm.getAtom(atom_index).getSymbolIndex().?; | | |
| 1874 | | | |
| 1875 | const parent_atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; | | |
| 1876 | const parent_atom = wasm.getAtomPtr(parent_atom_index); | | |
| 1877 | const is_wasm32 = target.cpu.arch == .wasm32; | | |
| 1878 | const mod = wasm.base.comp.module.?; | | |
| 1879 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | | |
| 1880 | if (ty.zigTypeTag(mod) == .Fn) { | | |
| 1881 | assert(reloc_info.addend == 0); // addend not allowed for function relocations | | |
| 1882 | // We found a function pointer, so add it to our table, | | |
| 1883 | // as function pointers are not allowed to be stored inside the data section. | | |
| 1884 | // They are instead stored in a function table which are called by index. | | |
| 1885 | try wasm.addTableFunction(target_symbol_index); | | |
| 1886 | try parent_atom.relocs.append(gpa, .{ | | |
| 1887 | .index = target_symbol_index, | | |
| 1888 | .offset = @intCast(reloc_info.offset), | | |
| 1889 | .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64, | | |
| 1890 | }); | | |
| 1891 | } else { | | |
| 1892 | try parent_atom.relocs.append(gpa, .{ | | |
| 1893 | .index = target_symbol_index, | | |
| 1894 | .offset = @intCast(reloc_info.offset), | | |
| 1895 | .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64, | | |
| 1896 | .addend = @intCast(reloc_info.addend), | | |
| 1897 | }); | | |
| 1898 | } | | |
| 1899 | | | |
| 1900 | // we do not know the final address at this point, | | |
| 1901 | // as atom allocation will determine the address and relocations | | |
| 1902 | // will calculate and rewrite this. Therefore, we simply return the symbol index | | |
| 1903 | // that was targeted. | | |
| 1904 | return target_symbol_index; | | |
| 1905 | } | 1530 | } |
| 1906 | | 1531 | |
| 1907 | pub fn deleteDeclExport( | 1532 | pub fn deleteDeclExport( |
| ... | @@ -1909,19 +1534,9 @@ pub fn deleteDeclExport( | ... | @@ -1909,19 +1534,9 @@ pub fn deleteDeclExport( |
| 1909 | decl_index: InternPool.DeclIndex, | 1534 | decl_index: InternPool.DeclIndex, |
| 1910 | name: InternPool.NullTerminatedString, | 1535 | name: InternPool.NullTerminatedString, |
| 1911 | ) void { | 1536 | ) void { |
| 1912 | _ = name; | | |
| 1913 | if (wasm.llvm_object) |_| return; | 1537 | if (wasm.llvm_object) |_| return; |
| 1914 | const atom_index = wasm.decls.get(decl_index) orelse return; | 1538 | _ = name; |
| 1915 | const sym_index = wasm.getAtom(atom_index).sym_index; | 1539 | _ = decl_index; |
| 1916 | const loc: SymbolLoc = .{ .file = null, .index = sym_index }; | | |
| 1917 | const symbol = loc.getSymbol(wasm); | | |
| 1918 | const symbol_name = wasm.string_table.get(symbol.name); | | |
| 1919 | log.debug("Deleting export for decl '{s}'", .{symbol_name}); | | |
| 1920 | if (wasm.export_names.fetchRemove(loc)) |kv| { | | |
| 1921 | assert(wasm.globals.remove(kv.value)); | | |
| 1922 | } else { | | |
| 1923 | assert(wasm.globals.remove(symbol.name)); | | |
| 1924 | } | | |
| 1925 | } | 1540 | } |
| 1926 | | 1541 | |
| 1927 | pub fn updateExports( | 1542 | pub fn updateExports( |
| ... | @@ -1934,159 +1549,10 @@ pub fn updateExports( | ... | @@ -1934,159 +1549,10 @@ pub fn updateExports( |
| 1934 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 1549 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1935 | } | 1550 | } |
| 1936 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); | 1551 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); |
| 1937 | | | |
| 1938 | const decl_index = switch (exported) { | | |
| 1939 | .decl_index => |i| i, | | |
| 1940 | .value => |val| { | | |
| 1941 | _ = val; | | |
| 1942 | @panic("TODO: implement Wasm linker code for exporting a constant value"); | | |
| 1943 | }, | | |
| 1944 | }; | | |
| 1945 | const decl = mod.declPtr(decl_index); | | |
| 1946 | const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); | | |
| 1947 | const atom = wasm.getAtom(atom_index); | | |
| 1948 | const atom_sym = atom.symbolLoc().getSymbol(wasm).*; | | |
| 1949 | const gpa = mod.gpa; | | |
| 1950 | | | |
| 1951 | for (exports) |exp| { | | |
| 1952 | if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section| { | | |
| 1953 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | | |
| 1954 | gpa, | | |
| 1955 | decl.srcLoc(mod), | | |
| 1956 | "Unimplemented: ExportOptions.section '{s}'", | | |
| 1957 | .{section}, | | |
| 1958 | )); | | |
| 1959 | continue; | | |
| 1960 | } | | |
| 1961 | | | |
| 1962 | const exported_decl_index = switch (exp.exported) { | | |
| 1963 | .value => { | | |
| 1964 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | | |
| 1965 | gpa, | | |
| 1966 | decl.srcLoc(mod), | | |
| 1967 | "Unimplemented: exporting a named constant value", | | |
| 1968 | .{}, | | |
| 1969 | )); | | |
| 1970 | continue; | | |
| 1971 | }, | | |
| 1972 | .decl_index => |i| i, | | |
| 1973 | }; | | |
| 1974 | const exported_atom_index = try wasm.getOrCreateAtomForDecl(exported_decl_index); | | |
| 1975 | const exported_atom = wasm.getAtom(exported_atom_index); | | |
| 1976 | const export_name = try wasm.string_table.put(gpa, mod.intern_pool.stringToSlice(exp.opts.name)); | | |
| 1977 | const sym_loc = exported_atom.symbolLoc(); | | |
| 1978 | const symbol = sym_loc.getSymbol(wasm); | | |
| 1979 | symbol.setGlobal(true); | | |
| 1980 | symbol.setUndefined(false); | | |
| 1981 | symbol.index = atom_sym.index; | | |
| 1982 | symbol.tag = atom_sym.tag; | | |
| 1983 | symbol.name = atom_sym.name; | | |
| 1984 | | | |
| 1985 | switch (exp.opts.linkage) { | | |
| 1986 | .Internal => { | | |
| 1987 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | | |
| 1988 | symbol.setFlag(.WASM_SYM_BINDING_WEAK); | | |
| 1989 | }, | | |
| 1990 | .Weak => { | | |
| 1991 | symbol.setFlag(.WASM_SYM_BINDING_WEAK); | | |
| 1992 | }, | | |
| 1993 | .Strong => {}, // symbols are strong by default | | |
| 1994 | .LinkOnce => { | | |
| 1995 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | | |
| 1996 | gpa, | | |
| 1997 | decl.srcLoc(mod), | | |
| 1998 | "Unimplemented: LinkOnce", | | |
| 1999 | .{}, | | |
| 2000 | )); | | |
| 2001 | continue; | | |
| 2002 | }, | | |
| 2003 | } | | |
| 2004 | | | |
| 2005 | if (wasm.globals.get(export_name)) |existing_loc| { | | |
| 2006 | if (existing_loc.index == atom.sym_index) continue; | | |
| 2007 | const existing_sym: Symbol = existing_loc.getSymbol(wasm).*; | | |
| 2008 | | | |
| 2009 | if (!existing_sym.isUndefined()) blk: { | | |
| 2010 | if (symbol.isWeak()) { | | |
| 2011 | try wasm.discarded.put(gpa, existing_loc, sym_loc); | | |
| 2012 | continue; // to-be-exported symbol is weak, so we keep the existing symbol | | |
| 2013 | } | | |
| 2014 | | | |
| 2015 | // new symbol is not weak while existing is, replace existing symbol | | |
| 2016 | if (existing_sym.isWeak()) { | | |
| 2017 | break :blk; | | |
| 2018 | } | | |
| 2019 | // When both the to-be-exported symbol and the already existing symbol | | |
| 2020 | // are strong symbols, we have a linker error. | | |
| 2021 | // In the other case we replace one with the other. | | |
| 2022 | try mod.failed_exports.put(gpa, exp, try Module.ErrorMsg.create( | | |
| 2023 | gpa, | | |
| 2024 | decl.srcLoc(mod), | | |
| 2025 | \\LinkError: symbol '{}' defined multiple times | | |
| 2026 | \\ first definition in '{s}' | | |
| 2027 | \\ next definition in '{s}' | | |
| 2028 | , | | |
| 2029 | .{ exp.opts.name.fmt(&mod.intern_pool), wasm.name, wasm.name }, | | |
| 2030 | )); | | |
| 2031 | continue; | | |
| 2032 | } | | |
| 2033 | | | |
| 2034 | // in this case the existing symbol must be replaced either because it's weak or undefined. | | |
| 2035 | try wasm.discarded.put(gpa, existing_loc, sym_loc); | | |
| 2036 | _ = wasm.imports.remove(existing_loc); | | |
| 2037 | _ = wasm.undefs.swapRemove(existing_sym.name); | | |
| 2038 | } | | |
| 2039 | | | |
| 2040 | // Ensure the symbol will be exported using the given name | | |
| 2041 | if (!mod.intern_pool.stringEqlSlice(exp.opts.name, sym_loc.getName(wasm))) { | | |
| 2042 | try wasm.export_names.put(gpa, sym_loc, export_name); | | |
| 2043 | } | | |
| 2044 | | | |
| 2045 | try wasm.globals.put( | | |
| 2046 | gpa, | | |
| 2047 | export_name, | | |
| 2048 | sym_loc, | | |
| 2049 | ); | | |
| 2050 | } | | |
| 2051 | } | 1552 | } |
| 2052 | | 1553 | |
| 2053 | pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { | 1554 | pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { |
| 2054 | if (wasm.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | 1555 | if (wasm.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); |
| 2055 | const gpa = wasm.base.comp.gpa; | | |
| 2056 | const mod = wasm.base.comp.module.?; | | |
| 2057 | const decl = mod.declPtr(decl_index); | | |
| 2058 | const atom_index = wasm.decls.get(decl_index).?; | | |
| 2059 | const atom = wasm.getAtomPtr(atom_index); | | |
| 2060 | atom.prev = null; | | |
| 2061 | wasm.symbols_free_list.append(gpa, atom.sym_index) catch {}; | | |
| 2062 | _ = wasm.decls.remove(decl_index); | | |
| 2063 | wasm.symbols.items[atom.sym_index].tag = .dead; | | |
| 2064 | for (atom.locals.items) |local_atom_index| { | | |
| 2065 | const local_atom = wasm.getAtom(local_atom_index); | | |
| 2066 | const local_symbol = &wasm.symbols.items[local_atom.sym_index]; | | |
| 2067 | local_symbol.tag = .dead; // also for any local symbol | | |
| 2068 | wasm.symbols_free_list.append(gpa, local_atom.sym_index) catch {}; | | |
| 2069 | assert(wasm.resolved_symbols.swapRemove(local_atom.symbolLoc())); | | |
| 2070 | assert(wasm.symbol_atom.remove(local_atom.symbolLoc())); | | |
| 2071 | } | | |
| 2072 | | | |
| 2073 | if (decl.isExtern(mod)) { | | |
| 2074 | _ = wasm.imports.remove(atom.symbolLoc()); | | |
| 2075 | } | | |
| 2076 | _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc()); | | |
| 2077 | _ = wasm.symbol_atom.remove(atom.symbolLoc()); | | |
| 2078 | | | |
| 2079 | // if (wasm.dwarf) |*dwarf| { | | |
| 2080 | // dwarf.freeDecl(decl_index); | | |
| 2081 | // } | | |
| 2082 | | | |
| 2083 | } | | |
| 2084 | | | |
| 2085 | /// Appends a new entry to the indirect function table | | |
| 2086 | pub fn addTableFunction(wasm: *Wasm, symbol_index: u32) !void { | | |
| 2087 | const gpa = wasm.base.comp.gpa; | | |
| 2088 | const index: u32 = @intCast(wasm.function_table.count()); | | |
| 2089 | try wasm.function_table.put(gpa, .{ .file = null, .index = symbol_index }, index); | | |
| 2090 | } | 1556 | } |
| 2091 | | 1557 | |
| 2092 | /// Assigns indexes to all indirect functions. | 1558 | /// Assigns indexes to all indirect functions. |
| ... | @@ -2118,203 +1584,6 @@ fn mapFunctionTable(wasm: *Wasm) void { | ... | @@ -2118,203 +1584,6 @@ fn mapFunctionTable(wasm: *Wasm) void { |
| 2118 | } | 1584 | } |
| 2119 | } | 1585 | } |
| 2120 | | 1586 | |
| 2121 | /// Either creates a new import, or updates one if existing. | | |
| 2122 | /// When `type_index` is non-null, we assume an external function. | | |
| 2123 | /// In all other cases, a data-symbol will be created instead. | | |
| 2124 | pub fn addOrUpdateImport( | | |
| 2125 | wasm: *Wasm, | | |
| 2126 | /// Name of the import | | |
| 2127 | name: []const u8, | | |
| 2128 | /// Symbol index that is external | | |
| 2129 | symbol_index: u32, | | |
| 2130 | /// Optional library name (i.e. `extern "c" fn foo() void` | | |
| 2131 | lib_name: ?[:0]const u8, | | |
| 2132 | /// The index of the type that represents the function signature | | |
| 2133 | /// when the extern is a function. When this is null, a data-symbol | | |
| 2134 | /// is asserted instead. | | |
| 2135 | type_index: ?u32, | | |
| 2136 | ) !void { | | |
| 2137 | const gpa = wasm.base.comp.gpa; | | |
| 2138 | assert(symbol_index != 0); | | |
| 2139 | // For the import name, we use the decl's name, rather than the fully qualified name | | |
| 2140 | // Also mangle the name when the lib name is set and not equal to "C" so imports with the same | | |
| 2141 | // name but different module can be resolved correctly. | | |
| 2142 | const mangle_name = lib_name != null and | | |
| 2143 | !std.mem.eql(u8, lib_name.?, "c"); | | |
| 2144 | const full_name = if (mangle_name) full_name: { | | |
| 2145 | break :full_name try std.fmt.allocPrint(gpa, "{s}|{s}", .{ name, lib_name.? }); | | |
| 2146 | } else name; | | |
| 2147 | defer if (mangle_name) gpa.free(full_name); | | |
| 2148 | | | |
| 2149 | const decl_name_index = try wasm.string_table.put(gpa, full_name); | | |
| 2150 | const symbol: *Symbol = &wasm.symbols.items[symbol_index]; | | |
| 2151 | symbol.setUndefined(true); | | |
| 2152 | symbol.setGlobal(true); | | |
| 2153 | symbol.name = decl_name_index; | | |
| 2154 | if (mangle_name) { | | |
| 2155 | // we specified a specific name for the symbol that does not match the import name | | |
| 2156 | symbol.setFlag(.WASM_SYM_EXPLICIT_NAME); | | |
| 2157 | } | | |
| 2158 | const global_gop = try wasm.globals.getOrPut(gpa, decl_name_index); | | |
| 2159 | if (!global_gop.found_existing) { | | |
| 2160 | const loc: SymbolLoc = .{ .file = null, .index = symbol_index }; | | |
| 2161 | global_gop.value_ptr.* = loc; | | |
| 2162 | try wasm.resolved_symbols.put(gpa, loc, {}); | | |
| 2163 | try wasm.undefs.putNoClobber(gpa, decl_name_index, loc); | | |
| 2164 | } else if (global_gop.value_ptr.*.index != symbol_index) { | | |
| 2165 | // We are not updating a symbol, but found an existing global | | |
| 2166 | // symbol with the same name. This means we always favor the | | |
| 2167 | // existing symbol, regardless whether it's defined or not. | | |
| 2168 | // We can also skip storing the import as we will not output | | |
| 2169 | // this symbol. | | |
| 2170 | return wasm.discarded.put( | | |
| 2171 | gpa, | | |
| 2172 | .{ .file = null, .index = symbol_index }, | | |
| 2173 | global_gop.value_ptr.*, | | |
| 2174 | ); | | |
| 2175 | } | | |
| 2176 | | | |
| 2177 | if (type_index) |ty_index| { | | |
| 2178 | const gop = try wasm.imports.getOrPut(gpa, .{ .index = symbol_index, .file = null }); | | |
| 2179 | const module_name = if (lib_name) |l_name| blk: { | | |
| 2180 | break :blk l_name; | | |
| 2181 | } else wasm.host_name; | | |
| 2182 | if (!gop.found_existing) { | | |
| 2183 | gop.value_ptr.* = .{ | | |
| 2184 | .module_name = try wasm.string_table.put(gpa, module_name), | | |
| 2185 | .name = try wasm.string_table.put(gpa, name), | | |
| 2186 | .kind = .{ .function = ty_index }, | | |
| 2187 | }; | | |
| 2188 | } | | |
| 2189 | } else { | | |
| 2190 | // non-functions will not be imported from the runtime, but only resolved during link-time | | |
| 2191 | symbol.tag = .data; | | |
| 2192 | } | | |
| 2193 | } | | |
| 2194 | | | |
| 2195 | /// Kind represents the type of an Atom, which is only | | |
| 2196 | /// used to parse a decl into an Atom to define in which section | | |
| 2197 | /// or segment it should be placed. | | |
| 2198 | const Kind = union(enum) { | | |
| 2199 | /// Represents the segment the data symbol should | | |
| 2200 | /// be inserted into. | | |
| 2201 | /// TODO: Add TLS segments | | |
| 2202 | data: enum { | | |
| 2203 | read_only, | | |
| 2204 | uninitialized, | | |
| 2205 | initialized, | | |
| 2206 | }, | | |
| 2207 | function: void, | | |
| 2208 | | | |
| 2209 | /// Returns the segment name the data kind represents. | | |
| 2210 | /// Asserts `kind` has its active tag set to `data`. | | |
| 2211 | fn segmentName(kind: Kind) []const u8 { | | |
| 2212 | switch (kind.data) { | | |
| 2213 | .read_only => return ".rodata.", | | |
| 2214 | .uninitialized => return ".bss.", | | |
| 2215 | .initialized => return ".data.", | | |
| 2216 | } | | |
| 2217 | } | | |
| 2218 | }; | | |
| 2219 | | | |
| 2220 | /// Parses an Atom and inserts its metadata into the corresponding sections. | | |
| 2221 | fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { | | |
| 2222 | const comp = wasm.base.comp; | | |
| 2223 | const gpa = comp.gpa; | | |
| 2224 | const shared_memory = comp.config.shared_memory; | | |
| 2225 | const import_memory = comp.config.import_memory; | | |
| 2226 | const atom = wasm.getAtomPtr(atom_index); | | |
| 2227 | const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); | | |
| 2228 | const do_garbage_collect = wasm.base.gc_sections; | | |
| 2229 | | | |
| 2230 | if (symbol.isDead() and do_garbage_collect) { | | |
| 2231 | // Prevent unreferenced symbols from being parsed. | | |
| 2232 | return; | | |
| 2233 | } | | |
| 2234 | | | |
| 2235 | const final_index: u32 = switch (kind) { | | |
| 2236 | .function => result: { | | |
| 2237 | const index: u32 = @intCast(wasm.functions.count() + wasm.imported_functions_count); | | |
| 2238 | const type_index = wasm.atom_types.get(atom_index).?; | | |
| 2239 | try wasm.functions.putNoClobber( | | |
| 2240 | gpa, | | |
| 2241 | .{ .file = null, .index = index }, | | |
| 2242 | .{ .func = .{ .type_index = type_index }, .sym_index = atom.sym_index }, | | |
| 2243 | ); | | |
| 2244 | symbol.tag = .function; | | |
| 2245 | symbol.index = index; | | |
| 2246 | | | |
| 2247 | if (wasm.code_section_index == null) { | | |
| 2248 | wasm.code_section_index = @intCast(wasm.segments.items.len); | | |
| 2249 | try wasm.segments.append(gpa, .{ | | |
| 2250 | .alignment = atom.alignment, | | |
| 2251 | .size = atom.size, | | |
| 2252 | .offset = 0, | | |
| 2253 | .flags = 0, | | |
| 2254 | }); | | |
| 2255 | } | | |
| 2256 | | | |
| 2257 | break :result wasm.code_section_index.?; | | |
| 2258 | }, | | |
| 2259 | .data => result: { | | |
| 2260 | const segment_name = try std.mem.concat(gpa, u8, &.{ | | |
| 2261 | kind.segmentName(), | | |
| 2262 | wasm.string_table.get(symbol.name), | | |
| 2263 | }); | | |
| 2264 | errdefer gpa.free(segment_name); | | |
| 2265 | const segment_info: types.Segment = .{ | | |
| 2266 | .name = segment_name, | | |
| 2267 | .alignment = atom.alignment, | | |
| 2268 | .flags = 0, | | |
| 2269 | }; | | |
| 2270 | symbol.tag = .data; | | |
| 2271 | | | |
| 2272 | // when creating an object file, or importing memory and the data belongs in the .bss segment | | |
| 2273 | // we set the entire region of it to zeroes. | | |
| 2274 | // We do not have to do this when exporting the memory (the default) because the runtime | | |
| 2275 | // will do it for us, and we do not emit the bss segment at all. | | |
| 2276 | if ((wasm.base.comp.config.output_mode == .Obj or import_memory) and kind.data == .uninitialized) { | | |
| 2277 | @memset(atom.code.items, 0); | | |
| 2278 | } | | |
| 2279 | | | |
| 2280 | const should_merge = wasm.base.comp.config.output_mode != .Obj; | | |
| 2281 | const gop = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(should_merge)); | | |
| 2282 | if (gop.found_existing) { | | |
| 2283 | const index = gop.value_ptr.*; | | |
| 2284 | wasm.segments.items[index].size += atom.size; | | |
| 2285 | | | |
| 2286 | symbol.index = @intCast(wasm.segment_info.getIndex(index).?); | | |
| 2287 | // segment info already exists, so free its memory | | |
| 2288 | gpa.free(segment_name); | | |
| 2289 | break :result index; | | |
| 2290 | } else { | | |
| 2291 | const index: u32 = @intCast(wasm.segments.items.len); | | |
| 2292 | var flags: u32 = 0; | | |
| 2293 | if (shared_memory) { | | |
| 2294 | flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); | | |
| 2295 | } | | |
| 2296 | try wasm.segments.append(gpa, .{ | | |
| 2297 | .alignment = atom.alignment, | | |
| 2298 | .size = 0, | | |
| 2299 | .offset = 0, | | |
| 2300 | .flags = flags, | | |
| 2301 | }); | | |
| 2302 | gop.value_ptr.* = index; | | |
| 2303 | | | |
| 2304 | const info_index: u32 = @intCast(wasm.segment_info.count()); | | |
| 2305 | try wasm.segment_info.put(gpa, index, segment_info); | | |
| 2306 | symbol.index = info_index; | | |
| 2307 | break :result index; | | |
| 2308 | } | | |
| 2309 | }, | | |
| 2310 | }; | | |
| 2311 | | | |
| 2312 | const segment: *Segment = &wasm.segments.items[final_index]; | | |
| 2313 | segment.alignment = segment.alignment.max(atom.alignment); | | |
| 2314 | | | |
| 2315 | try wasm.appendAtomAtIndex(final_index, atom_index); | | |
| 2316 | } | | |
| 2317 | | | |
| 2318 | /// From a given index, append the given `Atom` at the back of the linked list. | 1587 | /// From a given index, append the given `Atom` at the back of the linked list. |
| 2319 | /// Simply inserts it into the map of atoms when it doesn't exist yet. | 1588 | /// Simply inserts it into the map of atoms when it doesn't exist yet. |
| 2320 | pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void { | 1589 | pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void { |
| ... | @@ -2328,40 +1597,9 @@ pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void | ... | @@ -2328,40 +1597,9 @@ pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void |
| 2328 | } | 1597 | } |
| 2329 | } | 1598 | } |
| 2330 | | 1599 | |
| 2331 | /// Allocates debug atoms into their respective debug sections | | |
| 2332 | /// to merge them with maybe-existing debug atoms from object files. | | |
| 2333 | fn allocateDebugAtoms(wasm: *Wasm) !void { | | |
| 2334 | if (wasm.dwarf == null) return; | | |
| 2335 | | | |
| 2336 | const allocAtom = struct { | | |
| 2337 | fn f(bin: *Wasm, maybe_index: *?u32, atom_index: Atom.Index) !void { | | |
| 2338 | const index = maybe_index.* orelse idx: { | | |
| 2339 | const index = @as(u32, @intCast(bin.segments.items.len)); | | |
| 2340 | try bin.appendDummySegment(); | | |
| 2341 | maybe_index.* = index; | | |
| 2342 | break :idx index; | | |
| 2343 | }; | | |
| 2344 | const atom = bin.getAtomPtr(atom_index); | | |
| 2345 | atom.size = @as(u32, @intCast(atom.code.items.len)); | | |
| 2346 | bin.symbols.items[atom.sym_index].index = index; | | |
| 2347 | try bin.appendAtomAtIndex(index, atom_index); | | |
| 2348 | } | | |
| 2349 | }.f; | | |
| 2350 | | | |
| 2351 | try allocAtom(wasm, &wasm.debug_info_index, wasm.debug_info_atom.?); | | |
| 2352 | try allocAtom(wasm, &wasm.debug_line_index, wasm.debug_line_atom.?); | | |
| 2353 | try allocAtom(wasm, &wasm.debug_loc_index, wasm.debug_loc_atom.?); | | |
| 2354 | try allocAtom(wasm, &wasm.debug_str_index, wasm.debug_str_atom.?); | | |
| 2355 | try allocAtom(wasm, &wasm.debug_ranges_index, wasm.debug_ranges_atom.?); | | |
| 2356 | try allocAtom(wasm, &wasm.debug_abbrev_index, wasm.debug_abbrev_atom.?); | | |
| 2357 | try allocAtom(wasm, &wasm.debug_pubnames_index, wasm.debug_pubnames_atom.?); | | |
| 2358 | try allocAtom(wasm, &wasm.debug_pubtypes_index, wasm.debug_pubtypes_atom.?); | | |
| 2359 | } | | |
| 2360 | | | |
| 2361 | fn allocateAtoms(wasm: *Wasm) !void { | 1600 | fn allocateAtoms(wasm: *Wasm) !void { |
| 2362 | // first sort the data segments | 1601 | // first sort the data segments |
| 2363 | try sortDataSegments(wasm); | 1602 | try sortDataSegments(wasm); |
| 2364 | try allocateDebugAtoms(wasm); | | |
| 2365 | | 1603 | |
| 2366 | var it = wasm.atoms.iterator(); | 1604 | var it = wasm.atoms.iterator(); |
| 2367 | while (it.next()) |entry| { | 1605 | while (it.next()) |entry| { |
| ... | @@ -2382,7 +1620,7 @@ fn allocateAtoms(wasm: *Wasm) !void { | ... | @@ -2382,7 +1620,7 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 2382 | const sym = if (symbol_loc.file) |object_index| sym: { | 1620 | const sym = if (symbol_loc.file) |object_index| sym: { |
| 2383 | const object = wasm.objects.items[object_index]; | 1621 | const object = wasm.objects.items[object_index]; |
| 2384 | break :sym object.symtable[symbol_loc.index]; | 1622 | break :sym object.symtable[symbol_loc.index]; |
| 2385 | } else wasm.symbols.items[symbol_loc.index]; | 1623 | } else wasm.synthetic_symbols.items[symbol_loc.index]; |
| 2386 | | 1624 | |
| 2387 | // Dead symbols must be unlinked from the linked-list to prevent them | 1625 | // Dead symbols must be unlinked from the linked-list to prevent them |
| 2388 | // from being emit into the binary. | 1626 | // from being emit into the binary. |
| ... | @@ -2521,34 +1759,6 @@ fn setupInitFunctions(wasm: *Wasm) !void { | ... | @@ -2521,34 +1759,6 @@ fn setupInitFunctions(wasm: *Wasm) !void { |
| 2521 | } | 1759 | } |
| 2522 | } | 1760 | } |
| 2523 | | 1761 | |
| 2524 | /// Generates an atom containing the global error set' size. | | |
| 2525 | /// This will only be generated if the symbol exists. | | |
| 2526 | fn setupErrorsLen(wasm: *Wasm) !void { | | |
| 2527 | const gpa = wasm.base.comp.gpa; | | |
| 2528 | const loc = wasm.findGlobalSymbol("__zig_errors_len") orelse return; | | |
| 2529 | | | |
| 2530 | const errors_len = wasm.base.comp.module.?.global_error_set.count(); | | |
| 2531 | // overwrite existing atom if it already exists (maybe the error set has increased) | | |
| 2532 | // if not, allcoate a new atom. | | |
| 2533 | const atom_index = if (wasm.symbol_atom.get(loc)) |index| blk: { | | |
| 2534 | const atom = wasm.getAtomPtr(index); | | |
| 2535 | atom.deinit(gpa); | | |
| 2536 | break :blk index; | | |
| 2537 | } else new_atom: { | | |
| 2538 | const atom_index: Atom.Index = @intCast(wasm.managed_atoms.items.len); | | |
| 2539 | try wasm.symbol_atom.put(gpa, loc, atom_index); | | |
| 2540 | try wasm.managed_atoms.append(gpa, undefined); | | |
| 2541 | break :new_atom atom_index; | | |
| 2542 | }; | | |
| 2543 | const atom = wasm.getAtomPtr(atom_index); | | |
| 2544 | atom.* = Atom.empty; | | |
| 2545 | atom.sym_index = loc.index; | | |
| 2546 | atom.size = 2; | | |
| 2547 | try atom.code.writer(gpa).writeInt(u16, @intCast(errors_len), .little); | | |
| 2548 | | | |
| 2549 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); | | |
| 2550 | } | | |
| 2551 | | | |
| 2552 | /// Creates a function body for the `__wasm_call_ctors` symbol. | 1762 | /// Creates a function body for the `__wasm_call_ctors` symbol. |
| 2553 | /// Loops over all constructors found in `init_funcs` and calls them | 1763 | /// Loops over all constructors found in `init_funcs` and calls them |
| 2554 | /// respectively based on their priority which was sorted by `setupInitFunctions`. | 1764 | /// respectively based on their priority which was sorted by `setupInitFunctions`. |
| ... | @@ -3278,139 +2488,6 @@ fn appendDummySegment(wasm: *Wasm) !void { | ... | @@ -3278,139 +2488,6 @@ fn appendDummySegment(wasm: *Wasm) !void { |
| 3278 | }); | 2488 | }); |
| 3279 | } | 2489 | } |
| 3280 | | 2490 | |
| 3281 | /// Returns the symbol index of the error name table. | | |
| 3282 | /// | | |
| 3283 | /// When the symbol does not yet exist, it will create a new one instead. | | |
| 3284 | pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { | | |
| 3285 | if (wasm.error_table_symbol) |symbol| { | | |
| 3286 | return symbol; | | |
| 3287 | } | | |
| 3288 | | | |
| 3289 | // no error was referenced yet, so create a new symbol and atom for it | | |
| 3290 | // and then return said symbol's index. The final table will be populated | | |
| 3291 | // during `flush` when we know all possible error names. | | |
| 3292 | | | |
| 3293 | const gpa = wasm.base.comp.gpa; | | |
| 3294 | const atom_index = try wasm.createAtom(); | | |
| 3295 | const atom = wasm.getAtomPtr(atom_index); | | |
| 3296 | const slice_ty = Type.slice_const_u8_sentinel_0; | | |
| 3297 | const mod = wasm.base.comp.module.?; | | |
| 3298 | atom.alignment = slice_ty.abiAlignment(mod); | | |
| 3299 | const sym_index = atom.sym_index; | | |
| 3300 | | | |
| 3301 | const sym_name = try wasm.string_table.put(gpa, "__zig_err_name_table"); | | |
| 3302 | const symbol = &wasm.symbols.items[sym_index]; | | |
| 3303 | symbol.* = .{ | | |
| 3304 | .name = sym_name, | | |
| 3305 | .tag = .data, | | |
| 3306 | .flags = 0, | | |
| 3307 | .index = 0, | | |
| 3308 | .virtual_address = undefined, | | |
| 3309 | }; | | |
| 3310 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | | |
| 3311 | symbol.mark(); | | |
| 3312 | | | |
| 3313 | try wasm.resolved_symbols.put(gpa, atom.symbolLoc(), {}); | | |
| 3314 | | | |
| 3315 | log.debug("Error name table was created with symbol index: ({d})", .{sym_index}); | | |
| 3316 | wasm.error_table_symbol = sym_index; | | |
| 3317 | return sym_index; | | |
| 3318 | } | | |
| 3319 | | | |
| 3320 | /// Populates the error name table, when `error_table_symbol` is not null. | | |
| 3321 | /// | | |
| 3322 | /// This creates a table that consists of pointers and length to each error name. | | |
| 3323 | /// The table is what is being pointed to within the runtime bodies that are generated. | | |
| 3324 | fn populateErrorNameTable(wasm: *Wasm) !void { | | |
| 3325 | const gpa = wasm.base.comp.gpa; | | |
| 3326 | const symbol_index = wasm.error_table_symbol orelse return; | | |
| 3327 | const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = symbol_index }).?; | | |
| 3328 | | | |
| 3329 | // Rather than creating a symbol for each individual error name, | | |
| 3330 | // we create a symbol for the entire region of error names. We then calculate | | |
| 3331 | // the pointers into the list using addends which are appended to the relocation. | | |
| 3332 | const names_atom_index = try wasm.createAtom(); | | |
| 3333 | const names_atom = wasm.getAtomPtr(names_atom_index); | | |
| 3334 | names_atom.alignment = .@"1"; | | |
| 3335 | const sym_name = try wasm.string_table.put(gpa, "__zig_err_names"); | | |
| 3336 | const names_symbol = &wasm.symbols.items[names_atom.sym_index]; | | |
| 3337 | names_symbol.* = .{ | | |
| 3338 | .name = sym_name, | | |
| 3339 | .tag = .data, | | |
| 3340 | .flags = 0, | | |
| 3341 | .index = 0, | | |
| 3342 | .virtual_address = undefined, | | |
| 3343 | }; | | |
| 3344 | names_symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | | |
| 3345 | names_symbol.mark(); | | |
| 3346 | | | |
| 3347 | log.debug("Populating error names", .{}); | | |
| 3348 | | | |
| 3349 | // Addend for each relocation to the table | | |
| 3350 | var addend: u32 = 0; | | |
| 3351 | const mod = wasm.base.comp.module.?; | | |
| 3352 | for (mod.global_error_set.keys()) |error_name_nts| { | | |
| 3353 | const atom = wasm.getAtomPtr(atom_index); | | |
| 3354 | | | |
| 3355 | const error_name = mod.intern_pool.stringToSlice(error_name_nts); | | |
| 3356 | const len = @as(u32, @intCast(error_name.len + 1)); // names are 0-termianted | | |
| 3357 | | | |
| 3358 | const slice_ty = Type.slice_const_u8_sentinel_0; | | |
| 3359 | const offset = @as(u32, @intCast(atom.code.items.len)); | | |
| 3360 | // first we create the data for the slice of the name | | |
| 3361 | try atom.code.appendNTimes(gpa, 0, 4); // ptr to name, will be relocated | | |
| 3362 | try atom.code.writer(gpa).writeInt(u32, len - 1, .little); | | |
| 3363 | // create relocation to the error name | | |
| 3364 | try atom.relocs.append(gpa, .{ | | |
| 3365 | .index = names_atom.sym_index, | | |
| 3366 | .relocation_type = .R_WASM_MEMORY_ADDR_I32, | | |
| 3367 | .offset = offset, | | |
| 3368 | .addend = @as(i32, @intCast(addend)), | | |
| 3369 | }); | | |
| 3370 | atom.size += @as(u32, @intCast(slice_ty.abiSize(mod))); | | |
| 3371 | addend += len; | | |
| 3372 | | | |
| 3373 | // as we updated the error name table, we now store the actual name within the names atom | | |
| 3374 | try names_atom.code.ensureUnusedCapacity(gpa, len); | | |
| 3375 | names_atom.code.appendSliceAssumeCapacity(error_name); | | |
| 3376 | names_atom.code.appendAssumeCapacity(0); | | |
| 3377 | | | |
| 3378 | log.debug("Populated error name: '{s}'", .{error_name}); | | |
| 3379 | } | | |
| 3380 | names_atom.size = addend; | | |
| 3381 | | | |
| 3382 | const name_loc = names_atom.symbolLoc(); | | |
| 3383 | try wasm.resolved_symbols.put(gpa, name_loc, {}); | | |
| 3384 | try wasm.symbol_atom.put(gpa, name_loc, names_atom_index); | | |
| 3385 | | | |
| 3386 | // link the atoms with the rest of the binary so they can be allocated | | |
| 3387 | // and relocations will be performed. | | |
| 3388 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); | | |
| 3389 | try wasm.parseAtom(names_atom_index, .{ .data = .read_only }); | | |
| 3390 | } | | |
| 3391 | | | |
| 3392 | /// From a given index variable, creates a new debug section. | | |
| 3393 | /// This initializes the index, appends a new segment, | | |
| 3394 | /// and finally, creates a managed `Atom`. | | |
| 3395 | pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !Atom.Index { | | |
| 3396 | const gpa = wasm.base.comp.gpa; | | |
| 3397 | const new_index: u32 = @intCast(wasm.segments.items.len); | | |
| 3398 | index.* = new_index; | | |
| 3399 | try wasm.appendDummySegment(); | | |
| 3400 | | | |
| 3401 | const atom_index = try wasm.createAtom(); | | |
| 3402 | const atom = wasm.getAtomPtr(atom_index); | | |
| 3403 | wasm.symbols.items[atom.sym_index] = .{ | | |
| 3404 | .tag = .section, | | |
| 3405 | .name = try wasm.string_table.put(gpa, name), | | |
| 3406 | .index = 0, | | |
| 3407 | .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | | |
| 3408 | }; | | |
| 3409 | | | |
| 3410 | atom.alignment = .@"1"; // debug sections are always 1-byte-aligned | | |
| 3411 | return atom_index; | | |
| 3412 | } | | |
| 3413 | | | |
| 3414 | fn resetState(wasm: *Wasm) void { | 2491 | fn resetState(wasm: *Wasm) void { |
| 3415 | const gpa = wasm.base.comp.gpa; | 2492 | const gpa = wasm.base.comp.gpa; |
| 3416 | | 2493 | |
| ... | @@ -3418,16 +2495,19 @@ fn resetState(wasm: *Wasm) void { | ... | @@ -3418,16 +2495,19 @@ fn resetState(wasm: *Wasm) void { |
| 3418 | gpa.free(segment_info.name); | 2495 | gpa.free(segment_info.name); |
| 3419 | } | 2496 | } |
| 3420 | | 2497 | |
| 3421 | var atom_it = wasm.decls.valueIterator(); | 2498 | // TODO: Revisit |
| 3422 | while (atom_it.next()) |atom_index| { | 2499 | // var atom_it = wasm.decls.valueIterator(); |
| 3423 | const atom = wasm.getAtomPtr(atom_index.*); | 2500 | // while (atom_it.next()) |atom_index| { |
| 3424 | atom.prev = null; | 2501 | // const atom = wasm.getAtomPtr(atom_index.*); |
| | 2502 | // atom.next = null; |
| | 2503 | // atom.prev = null; |
| 3425 | | 2504 | |
| 3426 | for (atom.locals.items) |local_atom_index| { | 2505 | // for (atom.locals.items) |local_atom_index| { |
| 3427 | const local_atom = wasm.getAtomPtr(local_atom_index); | 2506 | // const local_atom = wasm.getAtomPtr(local_atom_index); |
| 3428 | local_atom.prev = null; | 2507 | // local_atom.next = null; |
| 3429 | } | 2508 | // local_atom.prev = null; |
| 3430 | } | 2509 | // } |
| | 2510 | // } |
| 3431 | | 2511 | |
| 3432 | wasm.functions.clearRetainingCapacity(); | 2512 | wasm.functions.clearRetainingCapacity(); |
| 3433 | wasm.exports.clearRetainingCapacity(); | 2513 | wasm.exports.clearRetainingCapacity(); |
| ... | @@ -3684,7 +2764,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -3684,7 +2764,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) |
| 3684 | defer sub_prog_node.end(); | 2764 | defer sub_prog_node.end(); |
| 3685 | | 2765 | |
| 3686 | // ensure the error names table is populated when an error name is referenced | 2766 | // ensure the error names table is populated when an error name is referenced |
| 3687 | try wasm.populateErrorNameTable(); | 2767 | // try wasm.populateErrorNameTable(); |
| 3688 | | 2768 | |
| 3689 | const objects = comp.objects; | 2769 | const objects = comp.objects; |
| 3690 | | 2770 | |
| ... | @@ -3722,66 +2802,66 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -3722,66 +2802,66 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) |
| 3722 | try wasm.setupInitFunctions(); | 2802 | try wasm.setupInitFunctions(); |
| 3723 | try wasm.setupStart(); | 2803 | try wasm.setupStart(); |
| 3724 | try wasm.markReferences(); | 2804 | try wasm.markReferences(); |
| 3725 | try wasm.setupErrorsLen(); | 2805 | // try wasm.setupErrorsLen(); |
| 3726 | try wasm.setupImports(); | 2806 | try wasm.setupImports(); |
| 3727 | if (comp.module) |mod| { | 2807 | // if (comp.module) |mod| { |
| 3728 | var decl_it = wasm.decls.iterator(); | 2808 | // var decl_it = wasm.decls.iterator(); |
| 3729 | while (decl_it.next()) |entry| { | 2809 | // while (decl_it.next()) |entry| { |
| 3730 | const decl = mod.declPtr(entry.key_ptr.*); | 2810 | // const decl = mod.declPtr(entry.key_ptr.*); |
| 3731 | if (decl.isExtern(mod)) continue; | 2811 | // if (decl.isExtern(mod)) continue; |
| 3732 | const atom_index = entry.value_ptr.*; | 2812 | // const atom_index = entry.value_ptr.*; |
| 3733 | const atom = wasm.getAtomPtr(atom_index); | 2813 | // const atom = wasm.getAtomPtr(atom_index); |
| 3734 | if (decl.ty.zigTypeTag(mod) == .Fn) { | 2814 | // if (decl.ty.zigTypeTag(mod) == .Fn) { |
| 3735 | try wasm.parseAtom(atom_index, .function); | 2815 | // try wasm.parseAtom(atom_index, .function); |
| 3736 | } else if (decl.getOwnedVariable(mod)) |variable| { | 2816 | // } else if (decl.getOwnedVariable(mod)) |variable| { |
| 3737 | if (variable.is_const) { | 2817 | // if (variable.is_const) { |
| 3738 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); | 2818 | // try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 3739 | } else if (Value.fromInterned(variable.init).isUndefDeep(mod)) { | 2819 | // } else if (Value.fromInterned(variable.init).isUndefDeep(mod)) { |
| 3740 | // for safe build modes, we store the atom in the data segment, | 2820 | // // for safe build modes, we store the atom in the data segment, |
| 3741 | // whereas for unsafe build modes we store it in bss. | 2821 | // // whereas for unsafe build modes we store it in bss. |
| 3742 | const decl_namespace = mod.namespacePtr(decl.src_namespace); | 2822 | // const decl_namespace = mod.namespacePtr(decl.src_namespace); |
| 3743 | const optimize_mode = decl_namespace.file_scope.mod.optimize_mode; | 2823 | // const optimize_mode = decl_namespace.file_scope.mod.optimize_mode; |
| 3744 | const is_initialized = switch (optimize_mode) { | 2824 | // const is_initialized = switch (optimize_mode) { |
| 3745 | .Debug, .ReleaseSafe => true, | 2825 | // .Debug, .ReleaseSafe => true, |
| 3746 | .ReleaseFast, .ReleaseSmall => false, | 2826 | // .ReleaseFast, .ReleaseSmall => false, |
| 3747 | }; | 2827 | // }; |
| 3748 | try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized }); | 2828 | // try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized }); |
| 3749 | } else { | 2829 | // } else { |
| 3750 | // when the decl is all zeroes, we store the atom in the bss segment, | 2830 | // // when the decl is all zeroes, we store the atom in the bss segment, |
| 3751 | // in all other cases it will be in the data segment. | 2831 | // // in all other cases it will be in the data segment. |
| 3752 | const is_zeroes = for (atom.code.items) |byte| { | 2832 | // const is_zeroes = for (atom.code.items) |byte| { |
| 3753 | if (byte != 0) break false; | 2833 | // if (byte != 0) break false; |
| 3754 | } else true; | 2834 | // } else true; |
| 3755 | try wasm.parseAtom(atom_index, .{ .data = if (is_zeroes) .uninitialized else .initialized }); | 2835 | // try wasm.parseAtom(atom_index, .{ .data = if (is_zeroes) .uninitialized else .initialized }); |
| 3756 | } | 2836 | // } |
| 3757 | } else { | 2837 | // } else { |
| 3758 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); | 2838 | // try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 3759 | } | 2839 | // } |
| 3760 | | 2840 | |
| 3761 | // also parse atoms for a decl's locals | 2841 | // // also parse atoms for a decl's locals |
| 3762 | for (atom.locals.items) |local_atom_index| { | 2842 | // for (atom.locals.items) |local_atom_index| { |
| 3763 | try wasm.parseAtom(local_atom_index, .{ .data = .read_only }); | 2843 | // try wasm.parseAtom(local_atom_index, .{ .data = .read_only }); |
| 3764 | } | 2844 | // } |
| 3765 | } | 2845 | // } |
| 3766 | // parse anonymous declarations | 2846 | // // parse anonymous declarations |
| 3767 | for (wasm.anon_decls.keys(), wasm.anon_decls.values()) |decl_val, atom_index| { | 2847 | // for (wasm.anon_decls.keys(), wasm.anon_decls.values()) |decl_val, atom_index| { |
| 3768 | const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); | 2848 | // const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); |
| 3769 | if (ty.zigTypeTag(mod) == .Fn) { | 2849 | // if (ty.zigTypeTag(mod) == .Fn) { |
| 3770 | try wasm.parseAtom(atom_index, .function); | 2850 | // try wasm.parseAtom(atom_index, .function); |
| 3771 | } else { | 2851 | // } else { |
| 3772 | try wasm.parseAtom(atom_index, .{ .data = .read_only }); | 2852 | // try wasm.parseAtom(atom_index, .{ .data = .read_only }); |
| 3773 | } | 2853 | // } |
| 3774 | } | 2854 | // } |
| 3775 | | 2855 | |
| 3776 | // also parse any backend-generated functions | 2856 | // // also parse any backend-generated functions |
| 3777 | for (wasm.synthetic_functions.items) |atom_index| { | 2857 | // for (wasm.synthetic_functions.items) |atom_index| { |
| 3778 | try wasm.parseAtom(atom_index, .function); | 2858 | // try wasm.parseAtom(atom_index, .function); |
| 3779 | } | 2859 | // } |
| 3780 | | 2860 | |
| 3781 | if (wasm.dwarf) |*dwarf| { | 2861 | // if (wasm.dwarf) |*dwarf| { |
| 3782 | try dwarf.flushModule(comp.module.?); | 2862 | // try dwarf.flushModule(comp.module.?); |
| 3783 | } | 2863 | // } |
| 3784 | } | 2864 | // } |
| 3785 | | 2865 | |
| 3786 | try wasm.mergeSections(); | 2866 | try wasm.mergeSections(); |
| 3787 | try wasm.mergeTypes(); | 2867 | try wasm.mergeTypes(); |
| ... | @@ -4194,16 +3274,6 @@ fn writeToFile( | ... | @@ -4194,16 +3274,6 @@ fn writeToFile( |
| 4194 | else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}), | 3274 | else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}), |
| 4195 | } | 3275 | } |
| 4196 | | 3276 | |
| 4197 | // if (wasm.dwarf) |*dwarf| { | | |
| 4198 | // const mod = comp.module.?; | | |
| 4199 | // try dwarf.writeDbgAbbrev(); | | |
| 4200 | // // for debug info and ranges, the address is always 0, | | |
| 4201 | // // as locations are always offsets relative to 'code' section. | | |
| 4202 | // try dwarf.writeDbgInfoHeader(mod, 0, code_section_size); | | |
| 4203 | // try dwarf.writeDbgAranges(0, code_section_size); | | |
| 4204 | // try dwarf.writeDbgLineHeader(); | | |
| 4205 | // } | | |
| 4206 | | | |
| 4207 | var debug_bytes = std.ArrayList(u8).init(gpa); | 3277 | var debug_bytes = std.ArrayList(u8).init(gpa); |
| 4208 | defer debug_bytes.deinit(); | 3278 | defer debug_bytes.deinit(); |
| 4209 | | 3279 | |
| ... | @@ -5185,44 +4255,25 @@ fn hasPassiveInitializationSegments(wasm: *const Wasm) bool { | ... | @@ -5185,44 +4255,25 @@ fn hasPassiveInitializationSegments(wasm: *const Wasm) bool { |
| 5185 | return false; | 4255 | return false; |
| 5186 | } | 4256 | } |
| 5187 | | 4257 | |
| 5188 | pub fn getTypeIndex(wasm: *const Wasm, func_type: std.wasm.Type) ?u32 { | | |
| 5189 | var index: u32 = 0; | | |
| 5190 | while (index < wasm.func_types.items.len) : (index += 1) { | | |
| 5191 | if (wasm.func_types.items[index].eql(func_type)) return index; | | |
| 5192 | } | | |
| 5193 | return null; | | |
| 5194 | } | | |
| 5195 | | | |
| 5196 | /// Searches for a matching function signature. When no matching signature is found, | 4258 | /// Searches for a matching function signature. When no matching signature is found, |
| 5197 | /// a new entry will be made. The value returned is the index of the type within `wasm.func_types`. | 4259 | /// a new entry will be made. The value returned is the index of the type within `wasm.func_types`. |
| 5198 | pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { | 4260 | pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { |
| 5199 | if (wasm.getTypeIndex(func_type)) |index| { | 4261 | _ = wasm; |
| 5200 | return index; | 4262 | _ = func_type; |
| 5201 | } | | |
| 5202 | const gpa = wasm.base.comp.gpa; | | |
| 5203 | | | |
| 5204 | // functype does not exist. | | |
| 5205 | const index: u32 = @intCast(wasm.func_types.items.len); | | |
| 5206 | const params = try gpa.dupe(std.wasm.Valtype, func_type.params); | | |
| 5207 | errdefer gpa.free(params); | | |
| 5208 | const returns = try gpa.dupe(std.wasm.Valtype, func_type.returns); | | |
| 5209 | errdefer gpa.free(returns); | | |
| 5210 | try wasm.func_types.append(gpa, .{ | | |
| 5211 | .params = params, | | |
| 5212 | .returns = returns, | | |
| 5213 | }); | | |
| 5214 | return index; | | |
| 5215 | } | 4263 | } |
| 5216 | | 4264 | |
| 5217 | /// For the given `decl_index`, stores the corresponding type representing the function signature. | 4265 | /// For the given `decl_index`, stores the corresponding type representing the function signature. |
| 5218 | /// Asserts declaration has an associated `Atom`. | 4266 | /// Asserts declaration has an associated `Atom`. |
| 5219 | /// Returns the index into the list of types. | 4267 | /// Returns the index into the list of types. |
| 5220 | pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { | 4268 | pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { |
| 5221 | const gpa = wasm.base.comp.gpa; | 4269 | _ = wasm; |
| 5222 | const atom_index = wasm.decls.get(decl_index).?; | 4270 | _ = decl_index; |
| 5223 | const index = try wasm.putOrGetFuncType(func_type); | 4271 | _ = func_type; |
| 5224 | try wasm.atom_types.put(gpa, atom_index, index); | 4272 | // const gpa = wasm.base.comp.gpa; |
| 5225 | return index; | 4273 | // const atom_index = wasm.decls.get(decl_index).?; |
| | 4274 | // const index = try wasm.putOrGetFuncType(func_type); |
| | 4275 | // try wasm.atom_types.put(gpa, atom_index, index); |
| | 4276 | // return index; |
| 5226 | } | 4277 | } |
| 5227 | | 4278 | |
| 5228 | /// Verifies all resolved symbols and checks whether itself needs to be marked alive, | 4279 | /// Verifies all resolved symbols and checks whether itself needs to be marked alive, |