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 {...@@ -1318,13 +1318,14 @@ pub const DeclGen = struct {
1318 if (decl.link.wasm.sym_index == 0) {1318 if (decl.link.wasm.sym_index == 0) {
1319 try writer.writeIntLittle(u32, 0);1319 try writer.writeIntLittle(u32, 0);
1320 } else {1320 } else {
1321 try writer.writeIntLittle(u32, try self.bin_file.getDeclVAddr(1321 try writer.writeIntLittle(u32, @intCast(u32, try self.bin_file.getDeclVAddr(
1322 self.decl, // parent decl that owns the atom of the symbol1322 decl,
1323 self.symbol_index, // source symbol index1323 .{
1324 decl, // target decl that contains the target symbol1324 .parent_atom_index = self.symbol_index,
1325 @intCast(u32, self.code.items.len), // offset1325 .offset = self.code.items.len,
1326 @intCast(u32, offset), // addend1326 .addend = @intCast(u32, offset),
1327 ));1327 },
1328 )));
1328 }1329 }
1329 return Result{ .appended = {} };1330 return Result{ .appended = {} };
1330 }1331 }
...@@ -1809,8 +1810,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1809,8 +1810,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
18091810
1810 if (func_val.castTag(.function)) |func| {1811 if (func_val.castTag(.function)) |func| {
1811 break :blk func.data.owner_decl;1812 break :blk func.data.owner_decl;
1812 } else if (func_val.castTag(.extern_fn)) |ext_fn| {1813 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
1813 break :blk ext_fn.data.owner_decl;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;
1814 } else if (func_val.castTag(.decl_ref)) |decl_ref| {1819 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
1815 break :blk decl_ref.data;1820 break :blk decl_ref.data;
1816 }1821 }
src/link.zig+1-1
...@@ -702,7 +702,7 @@ pub const File = struct {...@@ -702,7 +702,7 @@ pub const File = struct {
702 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),702 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),
703 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),703 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),
704 .c => unreachable,704 .c => unreachable,
705 .wasm => unreachable,705 .wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl, reloc_info),
706 .spirv => unreachable,706 .spirv => unreachable,
707 .nvptx => unreachable,707 .nvptx => unreachable,
708 }708 }
src/link/Wasm.zig+48-48
...@@ -14,6 +14,7 @@ const Atom = @import("Wasm/Atom.zig");...@@ -14,6 +14,7 @@ const Atom = @import("Wasm/Atom.zig");
14const Module = @import("../Module.zig");14const Module = @import("../Module.zig");
15const Compilation = @import("../Compilation.zig");15const Compilation = @import("../Compilation.zig");
16const CodeGen = @import("../arch/wasm/CodeGen.zig");16const CodeGen = @import("../arch/wasm/CodeGen.zig");
17const codegen = @import("../codegen.zig");
17const link = @import("../link.zig");18const link = @import("../link.zig");
18const lldMain = @import("../main.zig").lldMain;19const lldMain = @import("../main.zig").lldMain;
19const trace = @import("../tracy.zig").trace;20const trace = @import("../tracy.zig").trace;
...@@ -488,10 +489,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -488,10 +489,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
488 self.symbols.appendAssumeCapacity(symbol);489 self.symbols.appendAssumeCapacity(symbol);
489 }490 }
490491
491 try self.resolved_symbols.putNoClobber(self.base.allocator, .{492 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
492 .index = atom.sym_index,493 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
493 .file = null,
494 }, {});
495}494}
496495
497pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {496pub 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...@@ -506,7 +505,7 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
506505
507 decl.link.wasm.clear();506 decl.link.wasm.clear();
508507
509 var codegen: CodeGen = .{508 var codegen_: CodeGen = .{
510 .gpa = self.base.allocator,509 .gpa = self.base.allocator,
511 .air = air,510 .air = air,
512 .liveness = liveness,511 .liveness = liveness,
...@@ -519,18 +518,18 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live...@@ -519,18 +518,18 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
519 .bin_file = self,518 .bin_file = self,
520 .module = module,519 .module = module,
521 };520 };
522 defer codegen.deinit();521 defer codegen_.deinit();
523522
524 // generate the 'code' section for the function declaration523 // generate the 'code' section for the function declaration
525 codegen.genFunc() catch |err| switch (err) {524 codegen_.genFunc() catch |err| switch (err) {
526 error.CodegenFail => {525 error.CodegenFail => {
527 decl.analysis = .codegen_failure;526 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);
529 return;528 return;
530 },529 },
531 else => |e| return e,530 else => |e| return e,
532 };531 };
533 return self.finishUpdateDecl(decl, codegen.code.items);532 return self.finishUpdateDecl(decl, codegen_.code.items);
534}533}
535534
536// Generate code for the Decl, storing it in memory to be later written to535// 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 {...@@ -547,31 +546,37 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
547546
548 decl.link.wasm.clear();547 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
550 var code_writer = std.ArrayList(u8).init(self.base.allocator);560 var code_writer = std.ArrayList(u8).init(self.base.allocator);
551 defer code_writer.deinit();561 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 declaration563 const res = try codegen.generateSymbol(
563 const result = decl_gen.genDecl() catch |err| switch (err) {564 &self.base,
564 error.CodegenFail => {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| {
565 decl.analysis = .codegen_failure;576 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);
567 return;578 return;
568 },579 },
569 else => |e| return e,
570 };
571
572 const code = switch (result) {
573 .externally_managed => |data| data,
574 .appended => code_writer.items,
575 };580 };
576581
577 return self.finishUpdateDecl(decl, code);582 return self.finishUpdateDecl(decl, code);
...@@ -624,10 +629,8 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {...@@ -624,10 +629,8 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
624 atom.sym_index = @intCast(u32, self.symbols.items.len);629 atom.sym_index = @intCast(u32, self.symbols.items.len);
625 self.symbols.appendAssumeCapacity(symbol);630 self.symbols.appendAssumeCapacity(symbol);
626 }631 }
627 try self.resolved_symbols.putNoClobber(self.base.allocator, .{632 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
628 .file = null,633 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
629 .index = atom.sym_index,
630 }, {});
631634
632 var value_bytes = std.ArrayList(u8).init(self.base.allocator);635 var value_bytes = std.ArrayList(u8).init(self.base.allocator);
633 defer value_bytes.deinit();636 defer value_bytes.deinit();
...@@ -665,35 +668,31 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {...@@ -665,35 +668,31 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
665/// Returns the given pointer address668/// Returns the given pointer address
666pub fn getDeclVAddr(669pub fn getDeclVAddr(
667 self: *Wasm,670 self: *Wasm,
668 decl: *Module.Decl,671 decl: *const Module.Decl,
669 symbol_index: u32,672 reloc_info: link.File.RelocInfo,
670 target_decl: *Module.Decl,673) !u64 {
671 offset: u32,674 const target_symbol_index = decl.link.wasm.sym_index;
672 addend: u32,
673) !u32 {
674 const target_symbol_index = target_decl.link.wasm.sym_index;
675 assert(target_symbol_index != 0);675 assert(target_symbol_index != 0);
676 assert(symbol_index != 0);676 assert(reloc_info.parent_atom_index != 0);
677677 const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
678 const atom = decl.link.wasm.symbolAtom(symbol_index);
679 const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;678 const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
680 if (target_decl.ty.zigTypeTag() == .Fn) {679 if (decl.ty.zigTypeTag() == .Fn) {
681 assert(addend == 0); // addend not allowed for function relocations680 assert(reloc_info.addend == 0); // addend not allowed for function relocations
682 // We found a function pointer, so add it to our table,681 // We found a function pointer, so add it to our table,
683 // as function pointers are not allowed to be stored inside the data section.682 // as function pointers are not allowed to be stored inside the data section.
684 // They are instead stored in a function table which are called by index.683 // They are instead stored in a function table which are called by index.
685 try self.addTableFunction(target_symbol_index);684 try self.addTableFunction(target_symbol_index);
686 try atom.relocs.append(self.base.allocator, .{685 try atom.relocs.append(self.base.allocator, .{
687 .index = target_symbol_index,686 .index = target_symbol_index,
688 .offset = offset,687 .offset = @intCast(u32, reloc_info.offset),
689 .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,688 .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,
690 });689 });
691 } else {690 } else {
692 try atom.relocs.append(self.base.allocator, .{691 try atom.relocs.append(self.base.allocator, .{
693 .index = target_symbol_index,692 .index = target_symbol_index,
694 .offset = offset,693 .offset = @intCast(u32, reloc_info.offset),
695 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,694 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
696 .addend = addend,695 .addend = reloc_info.addend,
697 });696 });
698 }697 }
699 // we do not know the final address at this point,698 // we do not know the final address at this point,
...@@ -823,12 +822,14 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {...@@ -823,12 +822,14 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
823 local_symbol.tag = .dead; // also for any local symbol822 local_symbol.tag = .dead; // also for any local symbol
824 self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};823 self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};
825 assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));824 assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));
825 assert(self.symbol_atom.remove(local_atom.symbolLoc()));
826 }826 }
827827
828 if (decl.isExtern()) {828 if (decl.isExtern()) {
829 assert(self.imports.remove(atom.symbolLoc()));829 assert(self.imports.remove(atom.symbolLoc()));
830 }830 }
831 assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));831 assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));
832 assert(self.symbol_atom.remove(atom.symbolLoc()));
832 atom.deinit(self.base.allocator);833 atom.deinit(self.base.allocator);
833}834}
834835
...@@ -988,7 +989,6 @@ fn allocateAtoms(self: *Wasm) !void {...@@ -988,7 +989,6 @@ fn allocateAtoms(self: *Wasm) !void {
988 atom.size,989 atom.size,
989 });990 });
990 offset += atom.size;991 offset += atom.size;
991 try self.symbol_atom.putNoClobber(self.base.allocator, symbol_loc, atom);
992 atom = atom.next orelse break;992 atom = atom.next orelse break;
993 }993 }
994 }994 }
src/link/Wasm/Object.zig+1
...@@ -861,6 +861,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin...@@ -861,6 +861,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
861 }861 }
862862
863 try atom.code.appendSlice(gpa, relocatable_data.data[0..relocatable_data.size]);863 try atom.code.appendSlice(gpa, relocatable_data.data[0..relocatable_data.size]);
864 try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
864865
865 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];866 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];
866 segment.alignment = std.math.max(segment.alignment, atom.alignment);867 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" {...@@ -18,5 +18,6 @@ test "reference a global threadlocal variable" {
18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
21 _ = nrfx_uart_rx(&g_uart0);22 _ = nrfx_uart_rx(&g_uart0);
22}23}
test/behavior/cast.zig+1
...@@ -1060,6 +1060,7 @@ test "compile time int to ptr of function" {...@@ -1060,6 +1060,7 @@ test "compile time int to ptr of function" {
1060 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1060 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1061 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1061 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1062 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1062 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1063 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10631064
1064 try foobar(FUNCTION_CONSTANT);1065 try foobar(FUNCTION_CONSTANT);
1065}1066}
test/behavior/slice.zig+1
...@@ -209,6 +209,7 @@ test "compile time slice of pointer to hard coded address" {...@@ -209,6 +209,7 @@ test "compile time slice of pointer to hard coded address" {
209 if (builtin.zig_backend == .stage1) return error.SkipZigTest;209 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
212213
213 try expect(@ptrToInt(x) == 0x1000);214 try expect(@ptrToInt(x) == 0x1000);
214 try expect(x.len == 0x500);215 try expect(x.len == 0x500);