diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index a13c61f367..314518caef 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -2239,7 +2239,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif } if (callee) |direct| { - const atom_index = func.bin_file.decls.get(direct).?; + const atom_index = func.bin_file.zigObjectPtr().?.decls.get(direct).?; try func.addLabel(.call, func.bin_file.getAtom(atom_index).sym_index); } else { // in this case we call a function pointer @@ -2251,7 +2251,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), mod); defer fn_type.deinit(func.gpa); - const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type); + const fn_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, fn_type); try func.addLabel(.call_indirect, fn_type_index); } @@ -3157,7 +3157,7 @@ fn lowerAnonDeclRef( return error.CodegenFail; }, } - const target_atom_index = func.bin_file.anon_decls.get(decl_val).?; + const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?; const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?; if (is_fn_body) { return WValue{ .function_index = target_sym_index }; @@ -7161,7 +7161,7 @@ fn callIntrinsic( const mod = func.bin_file.base.comp.module.?; var func_type = try genFunctype(func.gpa, .C, param_types, return_type, mod); defer func_type.deinit(func.gpa); - const func_type_index = try func.bin_file.putOrGetFuncType(func_type); + const func_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, func_type); try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index); const want_sret_param = firstParamSRet(.C, return_type, mod); diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index 7e67a98285..3d495dcff6 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -310,7 +310,7 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { const global_offset = emit.offset(); try emit.code.appendSlice(&buf); - const atom_index = emit.bin_file.decls.get(emit.decl_index).?; + const atom_index = emit.bin_file.zigObjectPtr().?.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); try atom.relocs.append(gpa, .{ .index = label, @@ -370,7 +370,7 @@ fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void { try emit.code.appendSlice(&buf); if (label != 0) { - const atom_index = emit.bin_file.decls.get(emit.decl_index).?; + const atom_index = emit.bin_file.zigObjectPtr().?.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); try atom.relocs.append(gpa, .{ .offset = call_offset, @@ -400,7 +400,7 @@ fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void { try emit.code.appendSlice(&buf); if (symbol_index != 0) { - const atom_index = emit.bin_file.decls.get(emit.decl_index).?; + const atom_index = emit.bin_file.zigObjectPtr().?.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); try atom.relocs.append(gpa, .{ .offset = index_offset, @@ -431,7 +431,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { } if (mem.pointer != 0) { - const atom_index = emit.bin_file.decls.get(emit.decl_index).?; + const atom_index = emit.bin_file.zigObjectPtr().?.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); try atom.relocs.append(gpa, .{ .offset = mem_offset, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index d9e1432b63..fb808d79fc 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -581,11 +581,38 @@ pub fn createEmpty( return wasm; } -fn zigObjectPtr(wasm: *Wasm) ?*ZigObject { +pub fn zigObjectPtr(wasm: *Wasm) ?*ZigObject { if (wasm.zig_object_index == .null) return null; return &wasm.files.items(.data)[@intFromEnum(wasm.zig_object_index)].zig_object; } +pub fn getTypeIndex(wasm: *const Wasm, func_type: std.wasm.Type) ?u32 { + var index: u32 = 0; + while (index < wasm.func_types.items.len) : (index += 1) { + if (wasm.func_types.items[index].eql(func_type)) return index; + } + return null; +} + +/// Either creates a new import, or updates one if existing. +/// When `type_index` is non-null, we assume an external function. +/// In all other cases, a data-symbol will be created instead. +pub fn addOrUpdateImport( + wasm: *Wasm, + /// Name of the import + name: []const u8, + /// Symbol index that is external + symbol_index: u32, + /// Optional library name (i.e. `extern "c" fn foo() void` + lib_name: ?[:0]const u8, + /// The index of the type that represents the function signature + /// when the extern is a function. When this is null, a data-symbol + /// is asserted instead. + type_index: ?u32, +) !void { + return wasm.zigObjectPtr().?.addOrUpdateImport(wasm, name, symbol_index, lib_name, type_index); +} + /// For a given name, creates a new global synthetic symbol. /// Leaves index undefined and the default flags (0). fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc { @@ -1389,64 +1416,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: @panic("Attempted to compile for object format that was disabled by build configuration"); } if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness); - - const tracy = trace(@src()); - defer tracy.end(); - - const gpa = wasm.base.comp.gpa; - const func = mod.funcInfo(func_index); - const decl_index = func.owner_decl; - const decl = mod.declPtr(decl_index); - const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); - const atom = wasm.getAtomPtr(atom_index); - atom.clear(); - - // var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl_index) else null; - // defer if (decl_state) |*ds| ds.deinit(); - - var code_writer = std.ArrayList(u8).init(gpa); - defer code_writer.deinit(); - // const result = try codegen.generateFunction( - // &wasm.base, - // decl.srcLoc(mod), - // func, - // air, - // liveness, - // &code_writer, - // if (decl_state) |*ds| .{ .dwarf = ds } else .none, - // ); - const result = try codegen.generateFunction( - &wasm.base, - decl.srcLoc(mod), - func_index, - air, - liveness, - &code_writer, - .none, - ); - - const code = switch (result) { - .ok => code_writer.items, - .fail => |em| { - func.analysis(&mod.intern_pool).state = .codegen_failure; - try mod.failed_decls.put(mod.gpa, decl_index, em); - return; - }, - }; - - // if (wasm.dwarf) |*dwarf| { - // try dwarf.commitDeclState( - // mod, - // decl_index, - // // Actual value will be written after relocation. - // // For Wasm, this is the offset relative to the code section - // // which isn't known until flush(). - // 0, - // code.len, - // &decl_state.?, - // ); - // } - return wasm.finishUpdateDecl(decl_index, code, .function); + try wasm.zigObjectPtr().?.updateFunc(wasm, mod, func_index, air, liveness); } // Generate code for the Decl, storing it in memory to be later written to @@ -1456,12 +1426,12 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) ! @panic("Attempted to compile for object format that was disabled by build configuration"); } if (wasm.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index); + try wasm.zigObjectPtr().?.updateDecl(wasm, mod, decl_index); } pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) !void { if (wasm.llvm_object) |_| return; - _ = mod; - _ = decl_index; + try wasm.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index); } /// From a given symbol location, returns its `wasm.GlobalType`. @@ -1511,9 +1481,7 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { /// Returns the symbol index of the local /// The given `decl` is the parent decl whom owns the constant. pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { - _ = wasm; - _ = tv; - _ = decl_index; + return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, tv, decl_index); } /// Returns the symbol index from a symbol of which its flag is set global, @@ -1522,8 +1490,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.Dec /// and then returns the index to it. pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u32 { _ = lib_name; - _ = name; - _ = wasm; + return wasm.zigObjectPtr().?.getGlobalSymbol(wasm.base.comp.gpa, name); } /// For a given decl, find the given symbol index's atom, and create a relocation for the type. @@ -1533,9 +1500,7 @@ pub fn getDeclVAddr( decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo, ) !u64 { - _ = wasm; - _ = decl_index; - _ = reloc_info; + return wasm.zigObjectPtr().?.getDeclVAddr(wasm, decl_index, reloc_info); } pub fn lowerAnonDecl( @@ -1544,16 +1509,11 @@ pub fn lowerAnonDecl( explicit_alignment: Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - _ = wasm; - _ = decl_val; - _ = explicit_alignment; - _ = src_loc; + return wasm.zigObjectPtr().?.lowerAnonDecl(wasm, decl_val, explicit_alignment, src_loc); } pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { - _ = wasm; - _ = decl_val; - _ = reloc_info; + return wasm.zigObjectPtr().?.getAnonDeclVAddr(wasm, decl_val, reloc_info); } pub fn deleteDeclExport( @@ -1561,9 +1521,9 @@ pub fn deleteDeclExport( decl_index: InternPool.DeclIndex, name: InternPool.NullTerminatedString, ) void { - if (wasm.llvm_object) |_| return; _ = name; - _ = decl_index; + if (wasm.llvm_object) |_| return; + return wasm.zigObjectPtr().?.deleteDeclExport(wasm, decl_index); } pub fn updateExports( @@ -1576,10 +1536,12 @@ pub fn updateExports( @panic("Attempted to compile for object format that was disabled by build configuration"); } if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); + return wasm.zigObjectPtr().?.updateExports(wasm, mod, exported, exports); } pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { if (wasm.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); + return wasm.zigObjectPtr().?.freeDecl(wasm, decl_index); } /// Assigns indexes to all indirect functions. @@ -1917,7 +1879,11 @@ pub fn createFunction( }; try wasm.appendAtomAtIndex(section_index, atom_index); try wasm.symbol_atom.putNoClobber(gpa, loc, atom_index); - try wasm.atom_types.put(gpa, atom_index, try wasm.putOrGetFuncType(func_ty)); + try wasm.zigObjectPtr().?.atom_types.put( + gpa, + atom_index, + try wasm.zigObjectPtr().?.putOrGetFuncType(gpa, func_ty), + ); try wasm.synthetic_functions.append(gpa, atom_index); return loc.index; @@ -4285,22 +4251,43 @@ fn hasPassiveInitializationSegments(wasm: *const Wasm) bool { /// Searches for a matching function signature. When no matching signature is found, /// a new entry will be made. The value returned is the index of the type within `wasm.func_types`. pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { - _ = wasm; - _ = func_type; + if (wasm.getTypeIndex(func_type)) |index| { + return index; + } + + // functype does not exist. + const gpa = wasm.base.comp.gpa; + const index: u32 = @intCast(wasm.func_types.items.len); + const params = try gpa.dupe(std.wasm.Valtype, func_type.params); + errdefer gpa.free(params); + const returns = try gpa.dupe(std.wasm.Valtype, func_type.returns); + errdefer gpa.free(returns); + try wasm.func_types.append(gpa, .{ + .params = params, + .returns = returns, + }); + return index; } /// For the given `decl_index`, stores the corresponding type representing the function signature. /// Asserts declaration has an associated `Atom`. /// Returns the index into the list of types. pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { - _ = wasm; - _ = decl_index; - _ = func_type; - // const gpa = wasm.base.comp.gpa; - // const atom_index = wasm.decls.get(decl_index).?; - // const index = try wasm.putOrGetFuncType(func_type); - // try wasm.atom_types.put(gpa, atom_index, index); - // return index; + return wasm.zigObjectPtr().?.storeDeclType(wasm.base.comp.gpa, decl_index, func_type); +} + +/// Returns the symbol index of the error name table. +/// +/// When the symbol does not yet exist, it will create a new one instead. +pub fn getErrorTableSymbol(wasm_file: *Wasm) !u32 { + return wasm_file.zigObjectPtr().?.getErrorTableSymbol(wasm_file); +} + +/// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`. +/// When the index was not found, a new `Atom` will be created, and its index will be returned. +/// The newly created Atom is empty with default fields as specified by `Atom.empty`. +pub fn getOrCreateAtomForDecl(wasm_file: *Wasm, decl_index: InternPool.DeclIndex) !Atom.Index { + return wasm_file.zigObjectPtr().?.getOrCreateAtomForDecl(wasm_file, decl_index); } /// Verifies all resolved symbols and checks whether itself needs to be marked alive, diff --git a/src/link/Wasm/ZigObject.zig b/src/link/Wasm/ZigObject.zig index 4f32f6891e..8b4d703a34 100644 --- a/src/link/Wasm/ZigObject.zig +++ b/src/link/Wasm/ZigObject.zig @@ -85,11 +85,13 @@ pub fn init(zig_object: *ZigObject, wasm_file: *Wasm) !void { fn createStackPointer(zig_object: *ZigObject, wasm_file: *Wasm) !void { const gpa = wasm_file.base.comp.gpa; - const sym_index = try zig_object.getGlobalSymbol(gpa, "__stack_pointer", .global); - zig_object.symbols.items[sym_index].index = zig_object.imported_globals_count; + const sym_index = try zig_object.getGlobalSymbol(gpa, "__stack_pointer"); + const sym = zig_object.symbol(sym_index); + sym.index = zig_object.imported_globals_count; + sym.tag = .global; const is_wasm32 = wasm_file.base.comp.root_mod.resolved_target.result.cpu.arch == .wasm32; try zig_object.imports.putNoClobber(gpa, sym_index, .{ - .name = zig_object.symbols.items[sym_index].name, + .name = sym.name, .module_name = try zig_object.string_table.insert(gpa, wasm_file.host_name), .kind = .{ .global = .{ .valtype = if (is_wasm32) .i32 else .i64, .mutable = true } }, }); @@ -97,6 +99,10 @@ fn createStackPointer(zig_object: *ZigObject, wasm_file: *Wasm) !void { zig_object.stack_pointer_sym = sym_index; } +fn symbol(zig_object: *const ZigObject, index: u32) *Symbol { + return &zig_object.symbols.items[index]; +} + /// Frees and invalidates all memory of the incrementally compiled Zig module. /// It is illegal behavior to access the `ZigObject` after calling `deinit`. pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void { @@ -146,7 +152,7 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void { /// Will re-use slots when a symbol was freed at an earlier stage. pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !u32 { try zig_object.symbols.ensureUnusedCapacity(gpa, 1); - const symbol: Symbol = .{ + const sym: Symbol = .{ .name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), .tag = .undefined, // will be set after updateDecl @@ -154,17 +160,22 @@ pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !u32 { .virtual_address = std.math.maxInt(u32), // will be set during atom allocation }; if (zig_object.symbols_free_list.popOrNull()) |index| { - zig_object.symbols.items[index] = symbol; + zig_object.symbols.items[index] = sym; return index; } const index = @as(u32, @intCast(zig_object.symbols.items.len)); - zig_object.symbols.appendAssumeCapacity(symbol); + zig_object.symbols.appendAssumeCapacity(sym); return index; } // Generate code for the Decl, storing it in memory to be later written to // the file on flush(). -pub fn updateDecl(zig_object: *ZigObject, wasm_file: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) !void { +pub fn updateDecl( + zig_object: *ZigObject, + wasm_file: *Wasm, + mod: *Module, + decl_index: InternPool.DeclIndex, +) !void { const decl = mod.declPtr(decl_index); if (decl.val.getFunction(mod)) |_| { return; @@ -173,7 +184,7 @@ pub fn updateDecl(zig_object: *ZigObject, wasm_file: *Wasm, mod: *Module, decl_i } const gpa = wasm_file.base.comp.gpa; - const atom_index = try zig_object.getOrCreateAtomForDecl(decl_index); + const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); const atom = wasm_file.getAtomPtr(atom_index); atom.clear(); @@ -181,7 +192,7 @@ pub fn updateDecl(zig_object: *ZigObject, wasm_file: *Wasm, mod: *Module, decl_i const variable = decl.getOwnedVariable(mod).?; const name = mod.intern_pool.stringToSlice(decl.name); const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); - return wasm_file.addOrUpdateImport(name, atom.sym_index, lib_name, null); + return zig_object.addOrUpdateImport(wasm_file, name, atom.sym_index, lib_name, null); } const val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; @@ -206,15 +217,22 @@ pub fn updateDecl(zig_object: *ZigObject, wasm_file: *Wasm, mod: *Module, decl_i }, }; - return wasm_file.finishUpdateDecl(decl_index, code, .data); + return zig_object.finishUpdateDecl(wasm_file, decl_index, code, .data); } -pub fn updateFunc(zig_object: *ZigObject, wasm_file: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { +pub fn updateFunc( + zig_object: *ZigObject, + wasm_file: *Wasm, + mod: *Module, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, +) !void { const gpa = wasm_file.base.comp.gpa; const func = mod.funcInfo(func_index); const decl_index = func.owner_decl; const decl = mod.declPtr(decl_index); - const atom_index = try zig_object.getOrCreateAtomForDecl(decl_index); + const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); const atom = wasm_file.getAtomPtr(atom_index); atom.clear(); @@ -242,16 +260,22 @@ pub fn updateFunc(zig_object: *ZigObject, wasm_file: *Wasm, mod: *Module, func_i return zig_object.finishUpdateDecl(wasm_file, decl_index, code, .function); } -fn finishUpdateDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool.DeclIndex, code: []const u8, symbol_tag: Symbol.Tag) !void { +fn finishUpdateDecl( + zig_object: *ZigObject, + wasm_file: *Wasm, + decl_index: InternPool.DeclIndex, + code: []const u8, + symbol_tag: Symbol.Tag, +) !void { const gpa = wasm_file.base.comp.gpa; const mod = wasm_file.base.comp.module.?; const decl = mod.declPtr(decl_index); const atom_index = zig_object.decls.get(decl_index).?; const atom = wasm_file.getAtomPtr(atom_index); - const symbol = &zig_object.symbols.items[atom.sym_index]; + const sym = zig_object.symbol(atom.getSymbolIndex().?); const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); - symbol.name = try zig_object.string_table.insert(gpa, full_name); - symbol.tag = symbol_tag; + sym.name = try zig_object.string_table.insert(gpa, full_name); + sym.tag = symbol_tag; try atom.code.appendSlice(gpa, code); try wasm_file.resolved_symbols.put(gpa, atom.symbolLoc(), {}); @@ -267,14 +291,13 @@ pub fn getOrCreateAtomForDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_ind const gpa = wasm_file.base.comp.gpa; const gop = try zig_object.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { - const atom_index = try wasm_file.createAtom(); - gop.value_ptr.* = atom_index; - const atom = wasm_file.getAtom(atom_index); - const symbol = atom.symbolLoc().getSymbol(wasm_file); + const sym_index = try zig_object.allocateSymbol(gpa); + gop.value_ptr.* = try wasm_file.createAtom(sym_index); const mod = wasm_file.base.comp.module.?; const decl = mod.declPtr(decl_index); const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); - symbol.name = try wasm_file.string_table.insert(gpa, full_name); + const sym = zig_object.symbol(sym_index); + sym.name = try zig_object.string_table.insert(gpa, full_name); } return gop.value_ptr.*; } @@ -297,7 +320,7 @@ pub fn lowerAnonDecl( @intFromEnum(decl_val), }) catch unreachable; - switch (try zig_object.lowerConst(name, tv, src_loc)) { + switch (try zig_object.lowerConst(wasm_file, name, tv, src_loc)) { .ok => |atom_index| zig_object.anon_decls.values()[gop.index] = atom_index, .fail => |em| return .{ .fail = em }, } @@ -323,7 +346,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu std.debug.assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions const decl = mod.declPtr(decl_index); - const parent_atom_index = try zig_object.getOrCreateAtomForDecl(decl_index); + const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); const parent_atom = wasm_file.getAtom(parent_atom_index); const local_index = parent_atom.locals.items.len; const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); @@ -332,7 +355,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu }); defer gpa.free(name); - switch (try zig_object.lowerConst(name, tv, decl.srcLoc(mod))) { + switch (try zig_object.lowerConst(wasm_file, name, tv, decl.srcLoc(mod))) { .ok => |atom_index| { try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); return wasm_file.getAtom(atom_index).getSymbolIndex().?; @@ -355,14 +378,15 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty const mod = wasm_file.base.comp.module.?; // Create and initialize a new local symbol and atom - const atom_index = try wasm_file.createAtom(); + const sym_index = try zig_object.allocateSymbol(gpa); + const atom_index = try wasm_file.createAtom(sym_index); var value_bytes = std.ArrayList(u8).init(gpa); defer value_bytes.deinit(); const code = code: { const atom = wasm_file.getAtomPtr(atom_index); atom.alignment = tv.ty.abiAlignment(mod); - zig_object.symbols.items[atom.sym_index] = .{ + zig_object.symbols.items[sym_index] = .{ .name = try zig_object.string_table.insert(gpa, name), .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), .tag = .data, @@ -399,14 +423,14 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty /// /// When the symbol does not yet exist, it will create a new one instead. pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 { - if (zig_object.error_table_symbol) |symbol| { - return symbol; + if (zig_object.error_table_symbol) |sym| { + return sym; } // no error was referenced yet, so create a new symbol and atom for it // and then return said symbol's index. The final table will be populated // during `flush` when we know all possible error names. - const gpa = wasm_file.base.gpa; + const gpa = wasm_file.base.comp.gpa; const sym_index = try zig_object.allocateSymbol(gpa); const atom_index = try wasm_file.createAtom(sym_index); const atom = wasm_file.getAtomPtr(atom_index); @@ -415,15 +439,16 @@ pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 { atom.alignment = slice_ty.abiAlignment(mod); const sym_name = try zig_object.string_table.insert(gpa, "__zig_err_name_table"); - const symbol = &zig_object.symbols.items[sym_index]; - symbol.* = .{ + const sym = zig_object.symbol(sym_index); + sym.* = .{ .name = sym_name, .tag = .data, .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), .index = 0, .virtual_address = undefined, }; - symbol.mark(); + // TODO: can we remove this? + // sym.mark(); log.debug("Error name table was created with symbol index: ({d})", .{sym_index}); zig_object.error_table_symbol = sym_index; @@ -528,13 +553,13 @@ pub fn addOrUpdateImport( defer if (mangle_name) gpa.free(full_name); const decl_name_index = try zig_object.string_table.insert(gpa, full_name); - const symbol: *Symbol = &zig_object.symbols.items[symbol_index]; - symbol.setUndefined(true); - symbol.setGlobal(true); - symbol.name = decl_name_index; + const sym: *Symbol = &zig_object.symbols.items[symbol_index]; + sym.setUndefined(true); + sym.setGlobal(true); + sym.name = decl_name_index; if (mangle_name) { // we specified a specific name for the symbol that does not match the import name - symbol.setFlag(.WASM_SYM_EXPLICIT_NAME); + sym.setFlag(.WASM_SYM_EXPLICIT_NAME); } if (type_index) |ty_index| { @@ -557,22 +582,22 @@ pub fn addOrUpdateImport( /// such as an exported or imported symbol. /// If the symbol does not yet exist, creates a new one symbol instead /// and then returns the index to it. -pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8, tag: Symbol.Tag) !u32 { +pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8) !u32 { const name_index = try zig_object.string_table.insert(gpa, name); const gop = try zig_object.global_syms.getOrPut(gpa, name_index); if (gop.found_existing) { return gop.value_ptr.*; } - var symbol: Symbol = .{ + var sym: Symbol = .{ .name = name_index, .flags = 0, .index = undefined, // index to type will be set after merging symbols - .tag = tag, + .tag = .function, .virtual_address = std.math.maxInt(u32), }; - symbol.setGlobal(true); - symbol.setUndefined(true); + sym.setGlobal(true); + sym.setUndefined(true); const sym_index = if (zig_object.symbols_free_list.popOrNull()) |index| index else blk: { const index: u32 = @intCast(zig_object.symbols.items.len); @@ -580,7 +605,7 @@ pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []c zig_object.symbols.items.len += 1; break :blk index; }; - zig_object.symbols.items[sym_index] = symbol; + zig_object.symbols.items[sym_index] = sym; gop.value_ptr.* = sym_index; return sym_index; } @@ -675,8 +700,8 @@ pub fn deleteDeclExport( const atom_index = zig_object.decls.get(decl_index) orelse return; const sym_index = wasm_file.getAtom(atom_index).sym_index; const loc: Wasm.SymbolLoc = .{ .file = null, .index = sym_index }; - const symbol = loc.getSymbol(wasm_file); - std.debug.assert(zig_object.global_syms.remove(symbol.name)); + const sym = loc.getSymbol(wasm_file); + std.debug.assert(zig_object.global_syms.remove(sym.name)); } pub fn updateExports( @@ -694,7 +719,7 @@ pub fn updateExports( }, }; const decl = mod.declPtr(decl_index); - const atom_index = try zig_object.getOrCreateAtomForDecl(decl_index); + const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); const atom = wasm_file.getAtom(atom_index); const atom_sym = atom.symbolLoc().getSymbol(wasm_file).*; const gpa = mod.gpa; @@ -722,24 +747,24 @@ pub fn updateExports( }, .decl_index => |i| i, }; - const exported_atom_index = try zig_object.getOrCreateAtomForDecl(exported_decl_index); + const exported_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, exported_decl_index); const exported_atom = wasm_file.getAtom(exported_atom_index); // const export_name = try zig_object.string_table.put(gpa, mod.intern_pool.stringToSlice(exp.opts.name)); const sym_loc = exported_atom.symbolLoc(); - const symbol = sym_loc.getSymbol(wasm_file); - symbol.setGlobal(true); - symbol.setUndefined(false); - symbol.index = atom_sym.index; - symbol.tag = atom_sym.tag; - symbol.name = atom_sym.name; + const sym = sym_loc.getSymbol(wasm_file); + sym.setGlobal(true); + sym.setUndefined(false); + sym.index = atom_sym.index; + sym.tag = atom_sym.tag; + sym.name = atom_sym.name; switch (exp.opts.linkage) { .Internal => { - symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); - symbol.setFlag(.WASM_SYM_BINDING_WEAK); + sym.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); + sym.setFlag(.WASM_SYM_BINDING_WEAK); }, .Weak => { - symbol.setFlag(.WASM_SYM_BINDING_WEAK); + sym.setFlag(.WASM_SYM_BINDING_WEAK); }, .Strong => {}, // symbols are strong by default .LinkOnce => { @@ -840,7 +865,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool } } -pub fn getTypeIndex(zig_object: *const ZigObject, func_type: std.wasm.Type) ?u32 { +fn getTypeIndex(zig_object: *const ZigObject, func_type: std.wasm.Type) ?u32 { var index: u32 = 0; while (index < zig_object.func_types.items.len) : (index += 1) { if (zig_object.func_types.items[index].eql(func_type)) return index; @@ -1115,6 +1140,16 @@ fn allocateDebugAtoms(zig_object: *ZigObject) !void { try allocAtom(zig_object, &zig_object.debug_pubtypes_index, zig_object.debug_pubtypes_atom.?); } +/// For the given `decl_index`, stores the corresponding type representing the function signature. +/// Asserts declaration has an associated `Atom`. +/// Returns the index into the list of types. +pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { + const atom_index = zig_object.decls.get(decl_index).?; + const index = try zig_object.putOrGetFuncType(gpa, func_type); + try zig_object.atom_types.put(gpa, atom_index, index); + return index; +} + const build_options = @import("build_options"); const builtin = @import("builtin"); const codegen = @import("../../codegen.zig");