diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-03-06 20:44:51 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-06 20:44:51 +0100 |
| commit | 27c084065abcc404b7f58562f802999ae3ebce10 (patch) | |
| tree | 3979a57d5ed16c8dc76534e43fbcddf373c4e2db /src/link | |
| parent | 9154a8606996ce34e5f1d805672c83e2b733f5a7 (diff) | |
| parent | 13fca53b925e7de00b63efbf6ac3723a4df732a8 (diff) | |
| download | zig-27c084065abcc404b7f58562f802999ae3ebce10.tar.gz zig-27c084065abcc404b7f58562f802999ae3ebce10.zip | |
Merge pull request #11070 from Luukdegram/wasm-unify
stage2: wasm - unify codegen with other backends
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Wasm.zig | 168 | ||||
| -rw-r--r-- | src/link/Wasm/Atom.zig | 7 | ||||
| -rw-r--r-- | src/link/Wasm/Object.zig | 1 |
3 files changed, 90 insertions, 86 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index c1ff64965f..ca9d06e0ec 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -14,6 +14,7 @@ const Atom = @import("Wasm/Atom.zig"); const Module = @import("../Module.zig"); const Compilation = @import("../Compilation.zig"); const CodeGen = @import("../arch/wasm/CodeGen.zig"); +const codegen = @import("../codegen.zig"); const link = @import("../link.zig"); const lldMain = @import("../main.zig").lldMain; const trace = @import("../tracy.zig").trace; @@ -489,10 +490,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void { self.symbols.appendAssumeCapacity(symbol); } - try self.resolved_symbols.putNoClobber(self.base.allocator, .{ - .index = atom.sym_index, - .file = null, - }, {}); + try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {}); + try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom); } pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { @@ -505,33 +504,30 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live const decl = func.owner_decl; assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() - decl.link.wasm.clear(); - - var codegen: CodeGen = .{ - .gpa = self.base.allocator, - .air = air, - .liveness = liveness, - .values = .{}, - .code = std.ArrayList(u8).init(self.base.allocator), - .decl = decl, - .err_msg = undefined, - .locals = .{}, - .target = self.base.options.target, - .bin_file = self, - .module = module, - }; - defer codegen.deinit(); + decl.link.wasm.clear(self.base.allocator); + + var code_writer = std.ArrayList(u8).init(self.base.allocator); + defer code_writer.deinit(); + const result = try codegen.generateFunction( + &self.base, + decl.srcLoc(), + func, + air, + liveness, + &code_writer, + .none, + ); - // generate the 'code' section for the function declaration - codegen.genFunc() catch |err| switch (err) { - error.CodegenFail => { + const code = switch (result) { + .appended => code_writer.items, + .fail => |em| { decl.analysis = .codegen_failure; - try module.failed_decls.put(module.gpa, decl, codegen.err_msg); + try module.failed_decls.put(module.gpa, decl, em); return; }, - else => |e| return e, }; - return self.finishUpdateDecl(decl, codegen.code.items); + + return self.finishUpdateDecl(decl, code); } // Generate code for the Decl, storing it in memory to be later written to @@ -546,33 +542,39 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() - decl.link.wasm.clear(); + decl.link.wasm.clear(self.base.allocator); + + if (decl.isExtern()) { + return self.addOrUpdateImport(decl); + } + + if (decl.val.castTag(.function)) |_| { + return; + } else if (decl.val.castTag(.extern_fn)) |_| { + return; + } + const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; var code_writer = std.ArrayList(u8).init(self.base.allocator); defer code_writer.deinit(); - var decl_gen: CodeGen.DeclGen = .{ - .gpa = self.base.allocator, - .decl = decl, - .symbol_index = decl.link.wasm.sym_index, - .bin_file = self, - .err_msg = undefined, - .code = &code_writer, - .module = module, - }; - // generate the 'code' section for the function declaration - const result = decl_gen.genDecl() catch |err| switch (err) { - error.CodegenFail => { + const res = try codegen.generateSymbol( + &self.base, + decl.srcLoc(), + .{ .ty = decl.ty, .val = val }, + &code_writer, + .none, + .{ .parent_atom_index = decl.link.wasm.sym_index }, + ); + + const code = switch (res) { + .externally_managed => |x| x, + .appended => code_writer.items, + .fail => |em| { decl.analysis = .codegen_failure; - try module.failed_decls.put(module.gpa, decl, decl_gen.err_msg); + try module.failed_decls.put(module.gpa, decl, em); return; }, - else => |e| return e, - }; - - const code = switch (result) { - .externally_managed => |data| data, - .appended => code_writer.items, }; return self.finishUpdateDecl(decl, code); @@ -603,7 +605,9 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { // Create and initialize a new local symbol and atom const local_index = decl.link.wasm.locals.items.len; - const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ decl.name, local_index }); + const fqdn = try decl.getFullyQualifiedName(self.base.allocator); + defer self.base.allocator.free(fqdn); + const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index }); defer self.base.allocator.free(name); var symbol: Symbol = .{ .name = try self.string_table.put(self.base.allocator, name), @@ -625,36 +629,32 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { atom.sym_index = @intCast(u32, self.symbols.items.len); self.symbols.appendAssumeCapacity(symbol); } - try self.resolved_symbols.putNoClobber(self.base.allocator, .{ - .file = null, - .index = atom.sym_index, - }, {}); + try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {}); + try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom); var value_bytes = std.ArrayList(u8).init(self.base.allocator); defer value_bytes.deinit(); const module = self.base.options.module.?; - var decl_gen: CodeGen.DeclGen = .{ - .bin_file = self, - .decl = decl, - .err_msg = undefined, - .gpa = self.base.allocator, - .module = module, - .code = &value_bytes, - .symbol_index = atom.sym_index, - }; - - const result = decl_gen.genTypedValue(tv.ty, tv.val) catch |err| switch (err) { - error.CodegenFail => { - decl.analysis = .codegen_failure; - try module.failed_decls.put(module.gpa, decl, decl_gen.err_msg); - return error.AnalysisFail; + const result = try codegen.generateSymbol( + &self.base, + decl.srcLoc(), + tv, + &value_bytes, + .none, + .{ + .parent_atom_index = atom.sym_index, + .addend = null, }, - else => |e| return e, - }; + ); const code = switch (result) { + .externally_managed => |x| x, .appended => value_bytes.items, - .externally_managed => |data| data, + .fail => |em| { + decl.analysis = .codegen_failure; + try module.failed_decls.put(module.gpa, decl, em); + return error.AnalysisFail; + }, }; atom.size = @intCast(u32, code.len); @@ -666,35 +666,31 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { /// Returns the given pointer address pub fn getDeclVAddr( self: *Wasm, - decl: *Module.Decl, - symbol_index: u32, - target_decl: *Module.Decl, - offset: u32, - addend: u32, -) !u32 { - const target_symbol_index = target_decl.link.wasm.sym_index; + decl: *const Module.Decl, + reloc_info: link.File.RelocInfo, +) !u64 { + const target_symbol_index = decl.link.wasm.sym_index; assert(target_symbol_index != 0); - assert(symbol_index != 0); - - const atom = decl.link.wasm.symbolAtom(symbol_index); + assert(reloc_info.parent_atom_index != 0); + const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; const is_wasm32 = self.base.options.target.cpu.arch == .wasm32; - if (target_decl.ty.zigTypeTag() == .Fn) { - assert(addend == 0); // addend not allowed for function relocations + if (decl.ty.zigTypeTag() == .Fn) { + assert(reloc_info.addend == 0); // addend not allowed for function relocations // We found a function pointer, so add it to our table, // as function pointers are not allowed to be stored inside the data section. // They are instead stored in a function table which are called by index. try self.addTableFunction(target_symbol_index); try atom.relocs.append(self.base.allocator, .{ .index = target_symbol_index, - .offset = offset, + .offset = @intCast(u32, reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64, }); } else { try atom.relocs.append(self.base.allocator, .{ .index = target_symbol_index, - .offset = offset, + .offset = @intCast(u32, reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64, - .addend = addend, + .addend = reloc_info.addend, }); } // we do not know the final address at this point, @@ -824,12 +820,14 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { local_symbol.tag = .dead; // also for any local symbol self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {}; assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc())); + assert(self.symbol_atom.remove(local_atom.symbolLoc())); } if (decl.isExtern()) { assert(self.imports.remove(atom.symbolLoc())); } assert(self.resolved_symbols.swapRemove(atom.symbolLoc())); + assert(self.symbol_atom.remove(atom.symbolLoc())); atom.deinit(self.base.allocator); } @@ -989,7 +987,7 @@ fn allocateAtoms(self: *Wasm) !void { atom.size, }); offset += atom.size; - try self.symbol_atom.putNoClobber(self.base.allocator, symbol_loc, atom); + self.symbol_atom.putAssumeCapacity(atom.symbolLoc(), atom); // Update atom pointers atom = atom.next orelse break; } } diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig index a3e1c25190..e89ed37123 100644 --- a/src/link/Wasm/Atom.zig +++ b/src/link/Wasm/Atom.zig @@ -62,9 +62,14 @@ pub fn deinit(self: *Atom, gpa: Allocator) void { /// Sets the length of relocations and code to '0', /// effectively resetting them and allowing them to be re-populated. -pub fn clear(self: *Atom) void { +pub fn clear(self: *Atom, gpa: Allocator) void { self.relocs.clearRetainingCapacity(); self.code.clearRetainingCapacity(); + + // locals will be re-generated + for (self.locals.items) |*local| { + local.deinit(gpa); + } } pub fn format(self: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index b0ec835a86..011ec2e9e4 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -861,6 +861,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin } try atom.code.appendSlice(gpa, relocatable_data.data[0..relocatable_data.size]); + try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom); const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index]; segment.alignment = std.math.max(segment.alignment, atom.alignment); |
