authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-05 20:17:29+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-06 19:38:50+01:00
log5a45fe2dba12e1440fabe0b4b594d69703640e17
tree39e0e284945be031e6583da771f32520148604e6
parent12e636c24e92dbe02508b89c1363c357ccef2192
signaturelock-open Commit is signed but in an unrecognized format.

wasm: Call `generateSymbol` for updateDecl

To unify the wasm backend with the other backends, we will now call `generateSymbol` to lower a Decl into bytes. This means we also have to change some function signatures to comply with the linker interface. Since the general purpose generateSymbol is less featureful than wasm's, some tests are temporarily disabled.

7 files changed, 67 insertions(+), 58 deletions(-)

src/arch/wasm/CodeGen.zig+14-9
......@@ -1318,13 +1318,14 @@ pub const DeclGen = struct {
13181318 if (decl.link.wasm.sym_index == 0) {
13191319 try writer.writeIntLittle(u32, 0);
13201320 } else {
1321 try writer.writeIntLittle(u32, try self.bin_file.getDeclVAddr(
1322 self.decl, // parent decl that owns the atom of the symbol
1323 self.symbol_index, // source symbol index
1324 decl, // target decl that contains the target symbol
1325 @intCast(u32, self.code.items.len), // offset
1326 @intCast(u32, offset), // addend
1327 ));
1321 try writer.writeIntLittle(u32, @intCast(u32, try self.bin_file.getDeclVAddr(
1322 decl,
1323 .{
1324 .parent_atom_index = self.symbol_index,
1325 .offset = self.code.items.len,
1326 .addend = @intCast(u32, offset),
1327 },
1328 )));
13281329 }
13291330 return Result{ .appended = {} };
13301331 }
......@@ -1809,8 +1810,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
18091810
18101811 if (func_val.castTag(.function)) |func| {
18111812 break :blk func.data.owner_decl;
1812 } else if (func_val.castTag(.extern_fn)) |ext_fn| {
1813 break :blk ext_fn.data.owner_decl;
1813 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
1814 const ext_decl = extern_fn.data.owner_decl;
1815 var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target);
1816 defer func_type.deinit(self.gpa);
1817 ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
1818 break :blk ext_decl;
18141819 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
18151820 break :blk decl_ref.data;
18161821 }
src/link.zig+1-1
......@@ -702,7 +702,7 @@ pub const File = struct {
702702 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),
703703 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),
704704 .c => unreachable,
705 .wasm => unreachable,
705 .wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl, reloc_info),
706706 .spirv => unreachable,
707707 .nvptx => unreachable,
708708 }
src/link/Wasm.zig+48-48
......@@ -14,6 +14,7 @@ const Atom = @import("Wasm/Atom.zig");
1414const Module = @import("../Module.zig");
1515const Compilation = @import("../Compilation.zig");
1616const CodeGen = @import("../arch/wasm/CodeGen.zig");
17const codegen = @import("../codegen.zig");
1718const link = @import("../link.zig");
1819const lldMain = @import("../main.zig").lldMain;
1920const trace = @import("../tracy.zig").trace;
......@@ -488,10 +489,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
488489 self.symbols.appendAssumeCapacity(symbol);
489490 }
490491
491 try self.resolved_symbols.putNoClobber(self.base.allocator, .{
492 .index = atom.sym_index,
493 .file = null,
494 }, {});
492 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
493 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
495494}
496495
497496pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
......@@ -506,7 +505,7 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
506505
507506 decl.link.wasm.clear();
508507
509 var codegen: CodeGen = .{
508 var codegen_: CodeGen = .{
510509 .gpa = self.base.allocator,
511510 .air = air,
512511 .liveness = liveness,
......@@ -519,18 +518,18 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
519518 .bin_file = self,
520519 .module = module,
521520 };
522 defer codegen.deinit();
521 defer codegen_.deinit();
523522
524523 // generate the 'code' section for the function declaration
525 codegen.genFunc() catch |err| switch (err) {
524 codegen_.genFunc() catch |err| switch (err) {
526525 error.CodegenFail => {
527526 decl.analysis = .codegen_failure;
528 try module.failed_decls.put(module.gpa, decl, codegen.err_msg);
527 try module.failed_decls.put(module.gpa, decl, codegen_.err_msg);
529528 return;
530529 },
531530 else => |e| return e,
532531 };
533 return self.finishUpdateDecl(decl, codegen.code.items);
532 return self.finishUpdateDecl(decl, codegen_.code.items);
534533}
535534
536535// Generate code for the Decl, storing it in memory to be later written to
......@@ -547,31 +546,37 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
547546
548547 decl.link.wasm.clear();
549548
549 if (decl.isExtern()) {
550 return self.addOrUpdateImport(decl);
551 }
552
553 if (decl.val.castTag(.function)) |_| {
554 return;
555 } else if (decl.val.castTag(.extern_fn)) |_| {
556 return;
557 }
558 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
559
550560 var code_writer = std.ArrayList(u8).init(self.base.allocator);
551561 defer code_writer.deinit();
552 var decl_gen: CodeGen.DeclGen = .{
553 .gpa = self.base.allocator,
554 .decl = decl,
555 .symbol_index = decl.link.wasm.sym_index,
556 .bin_file = self,
557 .err_msg = undefined,
558 .code = &code_writer,
559 .module = module,
560 };
561562
562 // generate the 'code' section for the function declaration
563 const result = decl_gen.genDecl() catch |err| switch (err) {
564 error.CodegenFail => {
563 const res = try codegen.generateSymbol(
564 &self.base,
565 decl.srcLoc(),
566 .{ .ty = decl.ty, .val = val },
567 &code_writer,
568 .none,
569 .{ .parent_atom_index = decl.link.wasm.sym_index },
570 );
571
572 const code = switch (res) {
573 .externally_managed => |x| x,
574 .appended => code_writer.items,
575 .fail => |em| {
565576 decl.analysis = .codegen_failure;
566 try module.failed_decls.put(module.gpa, decl, decl_gen.err_msg);
577 try module.failed_decls.put(module.gpa, decl, em);
567578 return;
568579 },
569 else => |e| return e,
570 };
571
572 const code = switch (result) {
573 .externally_managed => |data| data,
574 .appended => code_writer.items,
575580 };
576581
577582 return self.finishUpdateDecl(decl, code);
......@@ -624,10 +629,8 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
624629 atom.sym_index = @intCast(u32, self.symbols.items.len);
625630 self.symbols.appendAssumeCapacity(symbol);
626631 }
627 try self.resolved_symbols.putNoClobber(self.base.allocator, .{
628 .file = null,
629 .index = atom.sym_index,
630 }, {});
632 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
633 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
631634
632635 var value_bytes = std.ArrayList(u8).init(self.base.allocator);
633636 defer value_bytes.deinit();
......@@ -665,35 +668,31 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
665668/// Returns the given pointer address
666669pub fn getDeclVAddr(
667670 self: *Wasm,
668 decl: *Module.Decl,
669 symbol_index: u32,
670 target_decl: *Module.Decl,
671 offset: u32,
672 addend: u32,
673) !u32 {
674 const target_symbol_index = target_decl.link.wasm.sym_index;
671 decl: *const Module.Decl,
672 reloc_info: link.File.RelocInfo,
673) !u64 {
674 const target_symbol_index = decl.link.wasm.sym_index;
675675 assert(target_symbol_index != 0);
676 assert(symbol_index != 0);
677
678 const atom = decl.link.wasm.symbolAtom(symbol_index);
676 assert(reloc_info.parent_atom_index != 0);
677 const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
679678 const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
680 if (target_decl.ty.zigTypeTag() == .Fn) {
681 assert(addend == 0); // addend not allowed for function relocations
679 if (decl.ty.zigTypeTag() == .Fn) {
680 assert(reloc_info.addend == 0); // addend not allowed for function relocations
682681 // We found a function pointer, so add it to our table,
683682 // as function pointers are not allowed to be stored inside the data section.
684683 // They are instead stored in a function table which are called by index.
685684 try self.addTableFunction(target_symbol_index);
686685 try atom.relocs.append(self.base.allocator, .{
687686 .index = target_symbol_index,
688 .offset = offset,
687 .offset = @intCast(u32, reloc_info.offset),
689688 .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,
690689 });
691690 } else {
692691 try atom.relocs.append(self.base.allocator, .{
693692 .index = target_symbol_index,
694 .offset = offset,
693 .offset = @intCast(u32, reloc_info.offset),
695694 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
696 .addend = addend,
695 .addend = reloc_info.addend,
697696 });
698697 }
699698 // we do not know the final address at this point,
......@@ -823,12 +822,14 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
823822 local_symbol.tag = .dead; // also for any local symbol
824823 self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};
825824 assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));
825 assert(self.symbol_atom.remove(local_atom.symbolLoc()));
826826 }
827827
828828 if (decl.isExtern()) {
829829 assert(self.imports.remove(atom.symbolLoc()));
830830 }
831831 assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));
832 assert(self.symbol_atom.remove(atom.symbolLoc()));
832833 atom.deinit(self.base.allocator);
833834}
834835
......@@ -988,7 +989,6 @@ fn allocateAtoms(self: *Wasm) !void {
988989 atom.size,
989990 });
990991 offset += atom.size;
991 try self.symbol_atom.putNoClobber(self.base.allocator, symbol_loc, atom);
992992 atom = atom.next orelse break;
993993 }
994994 }
src/link/Wasm/Object.zig+1
......@@ -861,6 +861,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
861861 }
862862
863863 try atom.code.appendSlice(gpa, relocatable_data.data[0..relocatable_data.size]);
864 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
864865
865866 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];
866867 segment.alignment = std.math.max(segment.alignment, atom.alignment);
test/behavior/bugs/7250.zig+1
......@@ -18,5 +18,6 @@ test "reference a global threadlocal variable" {
1818 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1919 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2020 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
2122 _ = nrfx_uart_rx(&g_uart0);
2223}
test/behavior/cast.zig+1
......@@ -1060,6 +1060,7 @@ test "compile time int to ptr of function" {
10601060 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10611061 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10621062 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1063 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10631064
10641065 try foobar(FUNCTION_CONSTANT);
10651066}
test/behavior/slice.zig+1
......@@ -209,6 +209,7 @@ test "compile time slice of pointer to hard coded address" {
209209 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
210210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
211211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
212213
213214 try expect(@ptrToInt(x) == 0x1000);
214215 try expect(x.len == 0x500);