diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 45 | ||||
| -rw-r--r-- | src/link/Wasm/Atom.zig | 14 | ||||
| -rw-r--r-- | src/link/Wasm/Symbol.zig | 2 |
4 files changed, 41 insertions, 22 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 95a0a8e4aa..b9637bf8e3 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -2394,9 +2394,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { const decl_index = decl_ref_mut.data.decl_index; return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index); } - const target = self.target; - switch (ty.zigTypeTag()) { .Void => return WValue{ .none = {} }, .Int => { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index e20703cb2b..050d9287a5 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -607,6 +607,24 @@ fn resolveSymbolsInArchives(self: *Wasm) !void { } } +fn checkUndefinedSymbols(self: *const Wasm) !void { + var found_undefined_symbols = false; + for (self.undefs.values()) |undef| { + const symbol = undef.getSymbol(self); + if (symbol.tag == .data) { + found_undefined_symbols = true; + const file_name = if (undef.file) |file_index| name: { + break :name self.objects.items[file_index].name; + } else self.name; + log.err("could not resolve undefined symbol '{s}'", .{undef.getName(self)}); + log.err(" defined in '{s}'", .{file_name}); + } + } + if (found_undefined_symbols) { + return error.UndefinedSymbol; + } +} + pub fn deinit(self: *Wasm) void { const gpa = self.base.allocator; if (build_options.have_llvm) { @@ -783,15 +801,17 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi decl.link.wasm.clear(); - if (decl.isExtern()) { - return; - } - if (decl.val.castTag(.function)) |_| { return; } else if (decl.val.castTag(.extern_fn)) |_| { return; } + + if (decl.isExtern()) { + const variable = decl.getVariable().?; + const name = mem.sliceTo(decl.name, 0); + return self.addOrUpdateImport(name, decl.link.wasm.sym_index, variable.lib_name, null); + } const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; var code_writer = std.ArrayList(u8).init(self.base.allocator); @@ -834,19 +854,18 @@ pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) } fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { - if (code.len == 0) return; const mod = self.base.options.module.?; const atom: *Atom = &decl.link.wasm; - atom.size = @intCast(u32, code.len); - atom.alignment = decl.ty.abiAlignment(self.base.options.target); const symbol = &self.symbols.items[atom.sym_index]; - const full_name = try decl.getFullyQualifiedName(mod); defer self.base.allocator.free(full_name); symbol.name = try self.string_table.put(self.base.allocator, full_name); try atom.code.appendSlice(self.base.allocator, code); - try self.resolved_symbols.put(self.base.allocator, atom.symbolLoc(), {}); + + if (code.len == 0) return; + atom.size = @intCast(u32, code.len); + atom.alignment = decl.ty.abiAlignment(self.base.options.target); } /// From a given symbol location, returns its `wasm.GlobalType`. @@ -1235,7 +1254,10 @@ pub fn addOrUpdateImport( .kind = .{ .function = ty_index }, }; } - } else @panic("TODO: Implement undefined symbols for non-function declarations"); + } else { + symbol.tag = .data; + return; // non-functions will not be imported from the runtime, but only resolved during link-time + } } /// Kind represents the type of an Atom, which is only @@ -1438,7 +1460,7 @@ fn setupImports(self: *Wasm) !void { if (std.mem.eql(u8, symbol_loc.getName(self), "__indirect_function_table")) { continue; } - if (symbol.tag == .data or !symbol.requiresImport()) { + if (!symbol.requiresImport()) { continue; } @@ -2007,6 +2029,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } try self.resolveSymbolsInArchives(); + try self.checkUndefinedSymbols(); // When we finish/error we reset the state of the linker // So we can rebuild the binary file on each incremental update diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig index d5bb4509f6..9e7f7a5a76 100644 --- a/src/link/Wasm/Atom.zig +++ b/src/link/Wasm/Atom.zig @@ -172,18 +172,16 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa .R_WASM_MEMORY_ADDR_SLEB, .R_WASM_MEMORY_ADDR_SLEB64, => { - if (symbol.isUndefined() and symbol.isWeak()) { - return 0; - } - std.debug.assert(symbol.tag == .data); + std.debug.assert(symbol.tag == .data and !symbol.isUndefined()); const merge_segment = wasm_bin.base.options.output_mode != .Obj; - const segment_info = if (self.file) |object_index| blk: { + const target_atom_loc = wasm_bin.discarded.get(target_loc) orelse target_loc; + const target_atom = wasm_bin.symbol_atom.get(target_atom_loc).?; + const segment_info = if (target_atom.file) |object_index| blk: { break :blk wasm_bin.objects.items[object_index].segment_info; } else wasm_bin.segment_info.items; const segment_name = segment_info[symbol.index].outputName(merge_segment); - const atom_index = wasm_bin.data_segments.get(segment_name).?; - const target_atom = wasm_bin.symbol_atom.get(target_loc).?; - const segment = wasm_bin.segments.items[atom_index]; + const segment_index = wasm_bin.data_segments.get(segment_name).?; + const segment = wasm_bin.segments.items[segment_index]; return target_atom.offset + segment.offset + (relocation.addend orelse 0); }, .R_WASM_EVENT_INDEX_LEB => return symbol.index, diff --git a/src/link/Wasm/Symbol.zig b/src/link/Wasm/Symbol.zig index fa6ea89d69..5e13456605 100644 --- a/src/link/Wasm/Symbol.zig +++ b/src/link/Wasm/Symbol.zig @@ -79,9 +79,9 @@ pub const Flag = enum(u32) { /// Verifies if the given symbol should be imported from the /// host environment or not pub fn requiresImport(self: Symbol) bool { + if (self.tag == .data) return false; if (!self.isUndefined()) return false; if (self.isWeak()) return false; - if (self.tag == .data) return false; // if (self.isDefined() and self.isWeak()) return true; //TODO: Only when building shared lib return true; |
