| ... | ... | @@ -29,6 +29,8 @@ global_syms: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 29 | 29 | symbols_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 30 | 30 | /// Extra metadata about the linking section, such as alignment of segments and their name. |
| 31 | 31 | segment_info: std.ArrayListUnmanaged(types.Segment) = .{}, |
| 32 | /// List of indexes which contain a free slot in the `segment_info` list. |
| 33 | segment_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 32 | 34 | /// File encapsulated string table, used to deduplicate strings within the generated file. |
| 33 | 35 | string_table: StringTable = .{}, |
| 34 | 36 | /// Map for storing anonymous declarations. Each anonymous decl maps to its Atom's index. |
| ... | ... | @@ -145,6 +147,7 @@ pub fn deinit(zig_object: *ZigObject, wasm_file: *Wasm) void { |
| 145 | 147 | zig_object.symbols.deinit(gpa); |
| 146 | 148 | zig_object.symbols_free_list.deinit(gpa); |
| 147 | 149 | zig_object.segment_info.deinit(gpa); |
| 150 | zig_object.segment_free_list.deinit(gpa); |
| 148 | 151 | |
| 149 | 152 | zig_object.string_table.deinit(gpa); |
| 150 | 153 | if (zig_object.dwarf) |*dwarf| { |
| ... | ... | @@ -223,7 +226,7 @@ pub fn updateDecl( |
| 223 | 226 | }, |
| 224 | 227 | }; |
| 225 | 228 | |
| 226 | | return zig_object.finishUpdateDecl(wasm_file, decl_index, code, .data); |
| 229 | return zig_object.finishUpdateDecl(wasm_file, decl_index, code); |
| 227 | 230 | } |
| 228 | 231 | |
| 229 | 232 | pub fn updateFunc( |
| ... | ... | @@ -263,7 +266,7 @@ pub fn updateFunc( |
| 263 | 266 | }, |
| 264 | 267 | }; |
| 265 | 268 | |
| 266 | | return zig_object.finishUpdateDecl(wasm_file, decl_index, code, .function); |
| 269 | return zig_object.finishUpdateDecl(wasm_file, decl_index, code); |
| 267 | 270 | } |
| 268 | 271 | |
| 269 | 272 | fn finishUpdateDecl( |
| ... | ... | @@ -271,25 +274,89 @@ fn finishUpdateDecl( |
| 271 | 274 | wasm_file: *Wasm, |
| 272 | 275 | decl_index: InternPool.DeclIndex, |
| 273 | 276 | code: []const u8, |
| 274 | | symbol_tag: Symbol.Tag, |
| 275 | 277 | ) !void { |
| 276 | 278 | const gpa = wasm_file.base.comp.gpa; |
| 277 | 279 | const mod = wasm_file.base.comp.module.?; |
| 278 | 280 | const decl = mod.declPtr(decl_index); |
| 279 | 281 | const atom_index = zig_object.decls.get(decl_index).?; |
| 280 | 282 | const atom = wasm_file.getAtomPtr(atom_index); |
| 281 | | const sym = zig_object.symbol(atom.getSymbolIndex().?); |
| 283 | const sym = zig_object.symbol(atom.sym_index); |
| 282 | 284 | const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 283 | 285 | sym.name = try zig_object.string_table.insert(gpa, full_name); |
| 284 | | sym.tag = symbol_tag; |
| 285 | 286 | try atom.code.appendSlice(gpa, code); |
| 286 | | try wasm_file.resolved_symbols.put(gpa, atom.symbolLoc(), {}); |
| 287 | | |
| 288 | 287 | atom.size = @intCast(code.len); |
| 288 | |
| 289 | switch (decl.ty.zigTypeTag(mod)) { |
| 290 | .Fn => { |
| 291 | try zig_object.functions.put( |
| 292 | gpa, |
| 293 | atom.sym_index, |
| 294 | .{ .type_index = zig_object.atom_types.get(atom_index).? }, |
| 295 | ); |
| 296 | sym.tag = .function; |
| 297 | }, |
| 298 | else => { |
| 299 | const segment_name: []const u8 = if (decl.getOwnedVariable(mod)) |variable| name: { |
| 300 | if (variable.is_const) { |
| 301 | break :name ".rodata."; |
| 302 | } else if (Value.fromInterned(variable.init).isUndefDeep(mod)) { |
| 303 | const decl_namespace = mod.namespacePtr(decl.src_namespace); |
| 304 | const optimize_mode = decl_namespace.file_scope.mod.optimize_mode; |
| 305 | const is_initialized = switch (optimize_mode) { |
| 306 | .Debug, .ReleaseSafe => true, |
| 307 | .ReleaseFast, .ReleaseSmall => false, |
| 308 | }; |
| 309 | if (is_initialized) { |
| 310 | break :name ".data."; |
| 311 | } |
| 312 | break :name ".bss."; |
| 313 | } |
| 314 | // when the decl is all zeroes, we store the atom in the bss segment, |
| 315 | // in all other cases it will be in the data segment. |
| 316 | for (atom.code.items) |byte| { |
| 317 | if (byte != 0) break :name ".data."; |
| 318 | } |
| 319 | break :name ".bss."; |
| 320 | } else ".rodata."; |
| 321 | if ((wasm_file.base.isObject() or wasm_file.base.comp.config.import_memory) and |
| 322 | std.mem.startsWith(u8, segment_name, ".bss")) |
| 323 | { |
| 324 | @memset(atom.code.items, 0); |
| 325 | } |
| 326 | // Will be freed upon freeing of decl or after cleanup of Wasm binary. |
| 327 | const full_segment_name = try std.mem.concat(gpa, u8, &.{ |
| 328 | segment_name, |
| 329 | full_name, |
| 330 | }); |
| 331 | errdefer gpa.free(full_segment_name); |
| 332 | sym.tag = .data; |
| 333 | sym.index = try zig_object.createDataSegment(gpa, full_segment_name, decl.alignment); |
| 334 | }, |
| 335 | } |
| 289 | 336 | if (code.len == 0) return; |
| 290 | 337 | atom.alignment = decl.getAlignment(mod); |
| 291 | 338 | } |
| 292 | 339 | |
| 340 | fn createDataSegment( |
| 341 | zig_object: *ZigObject, |
| 342 | gpa: std.mem.Allocator, |
| 343 | name: []const u8, |
| 344 | alignment: InternPool.Alignment, |
| 345 | ) !u32 { |
| 346 | const segment_index: u32 = if (zig_object.segment_free_list.popOrNull()) |index| |
| 347 | index |
| 348 | else index: { |
| 349 | const idx: u32 = @intCast(zig_object.segment_info.items.len); |
| 350 | _ = try zig_object.segment_info.addOne(gpa); |
| 351 | break :index idx; |
| 352 | }; |
| 353 | zig_object.segment_info.items[segment_index] = .{ |
| 354 | .alignment = alignment, |
| 355 | .flags = 0, |
| 356 | .name = name, |
| 357 | }; |
| 358 | } |
| 359 | |
| 293 | 360 | /// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`. |
| 294 | 361 | /// When the index was not found, a new `Atom` will be created, and its index will be returned. |
| 295 | 362 | /// The newly created Atom is empty with default fields as specified by `Atom.empty`. |
| ... | ... | @@ -840,20 +907,24 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool |
| 840 | 907 | const atom_index = zig_object.decls.get(decl_index).?; |
| 841 | 908 | const atom = wasm_file.getAtomPtr(atom_index); |
| 842 | 909 | zig_object.symbols_free_list.append(gpa, atom.sym_index) catch {}; |
| 843 | | _ = zig_object.decls.remove(decl_index); |
| 844 | | zig_object.symbols.items[atom.sym_index].tag = .dead; |
| 910 | std.debug.assert(zig_object.decls.remove(decl_index)); |
| 911 | const sym = &zig_object.symbols.items[atom.sym_index]; |
| 845 | 912 | for (atom.locals.items) |local_atom_index| { |
| 846 | 913 | const local_atom = wasm_file.getAtom(local_atom_index); |
| 847 | 914 | const local_symbol = &zig_object.symbols.items[local_atom.sym_index]; |
| 848 | | local_symbol.tag = .dead; // also for any local symbol |
| 915 | std.debug.assert(local_symbol.tag == .data); |
| 849 | 916 | zig_object.symbols_free_list.append(gpa, local_atom.sym_index) catch {}; |
| 850 | | std.denug.assert(wasm_file.symbol_atom.remove(local_atom.symbolLoc())); |
| 917 | std.debug.assert(wasm_file.symbol_atom.remove(local_atom.symbolLoc())); |
| 918 | local_symbol.tag = .dead; // also for any local symbol |
| 919 | const segment = &zig_object.segment_info.items[local_atom.sym_index]; |
| 920 | gpa.free(segment.name); |
| 921 | segment.name = &.{}; // Ensure no accidental double free |
| 851 | 922 | } |
| 852 | 923 | |
| 853 | 924 | if (decl.isExtern(mod)) { |
| 854 | | _ = zig_object.imports.remove(atom.getSymbolIndex().?); |
| 925 | std.debug.assert(zig_object.imports.remove(atom.sym_index)); |
| 855 | 926 | } |
| 856 | | _ = wasm_file.symbol_atom.remove(atom.symbolLoc()); |
| 927 | std.debug.assert(wasm_file.symbol_atom.remove(atom.symbolLoc())); |
| 857 | 928 | |
| 858 | 929 | // if (wasm.dwarf) |*dwarf| { |
| 859 | 930 | // dwarf.freeDecl(decl_index); |
| ... | ... | @@ -869,6 +940,20 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool |
| 869 | 940 | prev_atom.next = atom.next; |
| 870 | 941 | atom.prev = null; |
| 871 | 942 | } |
| 943 | |
| 944 | sym.tag = .dead; |
| 945 | switch (decl.ty.zigTypeTag(mod)) { |
| 946 | .Fn => { |
| 947 | std.debug.assert(zig_object.functions.remove(atom.sym_index)); |
| 948 | std.debug.assert(zig_object.atom_types.remove(atom_index)); |
| 949 | }, |
| 950 | else => { |
| 951 | zig_object.segment_free_list.append(gpa, sym.index) catch {}; |
| 952 | const segment = &zig_object.segment_info.items[sym.index]; |
| 953 | gpa.free(segment.name); |
| 954 | segment.name = &.{}; // Prevent accidental double free |
| 955 | }, |
| 956 | } |
| 872 | 957 | } |
| 873 | 958 | |
| 874 | 959 | fn getTypeIndex(zig_object: *const ZigObject, func_type: std.wasm.Type) ?u32 { |