authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-06 17:54:26+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-06 19:38:53+01:00
log13fca53b925e7de00b63efbf6ac3723a4df732a8
treee54f74a9042fd245f43be0ef8640d2a10708e9ce
parent2faba4092a3c730c4062e0e82b967daa9638b129
signaturelock-open Commit is signed but in an unrecognized format.

wasm: Unify function generation

Like decl code generation, also unify the wasm backend and the wasm linker to call into the general purpose `codegen.zig` to generate the code for a function.

3 files changed, 59 insertions(+), 31 deletions(-)

src/arch/wasm/CodeGen.zig+39-9
......@@ -8,6 +8,7 @@ const mem = std.mem;
88const wasm = std.wasm;
99const log = std.log.scoped(.codegen);
1010
11const codegen = @import("../../codegen.zig");
1112const Module = @import("../../Module.zig");
1213const Decl = Module.Decl;
1314const Type = @import("../../type.zig").Type;
......@@ -546,7 +547,7 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {
546547 value: WValue,
547548}) = .{},
548549/// `bytes` contains the wasm bytecode belonging to the 'code' section.
549code: ArrayList(u8),
550code: *ArrayList(u8),
550551/// The index the next local generated will have
551552/// NOTE: arguments share the index with locals therefore the first variable
552553/// will have the index that comes after the last argument's index
......@@ -566,9 +567,6 @@ locals: std.ArrayListUnmanaged(u8),
566567target: std.Target,
567568/// Represents the wasm binary file that is being linked.
568569bin_file: *link.File.Wasm,
569/// Reference to the Module that this decl is part of.
570/// Used to find the error value.
571module: *Module,
572570/// List of MIR Instructions
573571mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
574572/// Contains extra data for MIR
......@@ -611,7 +609,6 @@ pub fn deinit(self: *Self) void {
611609 self.locals.deinit(self.gpa);
612610 self.mir_instructions.deinit(self.gpa);
613611 self.mir_extra.deinit(self.gpa);
614 self.code.deinit();
615612 self.* = undefined;
616613}
617614
......@@ -822,7 +819,40 @@ fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type {
822819 };
823820}
824821
825pub fn genFunc(self: *Self) InnerError!void {
822pub fn generate(
823 bin_file: *link.File,
824 src_loc: Module.SrcLoc,
825 func: *Module.Fn,
826 air: Air,
827 liveness: Liveness,
828 code: *std.ArrayList(u8),
829 debug_output: codegen.DebugInfoOutput,
830) codegen.GenerateSymbolError!codegen.FnResult {
831 _ = debug_output; // TODO
832 _ = src_loc;
833 var code_gen: Self = .{
834 .gpa = bin_file.allocator,
835 .air = air,
836 .liveness = liveness,
837 .values = .{},
838 .code = code,
839 .decl = func.owner_decl,
840 .err_msg = undefined,
841 .locals = .{},
842 .target = bin_file.options.target,
843 .bin_file = bin_file.cast(link.File.Wasm).?,
844 };
845 defer code_gen.deinit();
846
847 genFunc(&code_gen) catch |err| switch (err) {
848 error.CodegenFail => return codegen.FnResult{ .fail = code_gen.err_msg },
849 else => |e| return e,
850 };
851
852 return codegen.FnResult{ .appended = {} };
853}
854
855fn genFunc(self: *Self) InnerError!void {
826856 var func_type = try genFunctype(self.gpa, self.decl.ty, self.target);
827857 defer func_type.deinit(self.gpa);
828858 self.decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
......@@ -889,7 +919,7 @@ pub fn genFunc(self: *Self) InnerError!void {
889919 var emit: Emit = .{
890920 .mir = mir,
891921 .bin_file = &self.bin_file.base,
892 .code = &self.code,
922 .code = self.code,
893923 .locals = self.locals.items,
894924 .decl = self.decl,
895925 };
......@@ -1761,7 +1791,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
17611791 },
17621792 .ErrorSet => switch (val.tag()) {
17631793 .@"error" => {
1764 const kv = try self.module.getErrorValue(val.getError().?);
1794 const kv = try self.bin_file.base.options.module.?.getErrorValue(val.getError().?);
17651795 return WValue{ .imm32 = kv.value };
17661796 },
17671797 else => return WValue{ .imm32 = 0 },
......@@ -1852,7 +1882,7 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 {
18521882 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt())),
18531883 },
18541884 .ErrorSet => {
1855 const kv = self.module.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
1885 const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
18561886 return @bitCast(i32, kv.value);
18571887 },
18581888 else => unreachable, // Programmer called this function for an illegal type
src/codegen.zig+3-2
......@@ -83,8 +83,6 @@ pub fn generateFunction(
8383 debug_output: DebugInfoOutput,
8484) GenerateSymbolError!FnResult {
8585 switch (bin_file.options.target.cpu.arch) {
86 .wasm32 => unreachable, // has its own code path
87 .wasm64 => unreachable, // has its own code path
8886 .arm,
8987 .armeb,
9088 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
......@@ -136,6 +134,9 @@ pub fn generateFunction(
136134 //.renderscript32 => return Function(.renderscript32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
137135 //.renderscript64 => return Function(.renderscript64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
138136 //.ve => return Function(.ve).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
137 .wasm32,
138 .wasm64,
139 => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
139140 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
140141 }
141142}
src/link/Wasm.zig+17-20
......@@ -505,31 +505,28 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
505505
506506 decl.link.wasm.clear(self.base.allocator);
507507
508 var codegen_: CodeGen = .{
509 .gpa = self.base.allocator,
510 .air = air,
511 .liveness = liveness,
512 .values = .{},
513 .code = std.ArrayList(u8).init(self.base.allocator),
514 .decl = decl,
515 .err_msg = undefined,
516 .locals = .{},
517 .target = self.base.options.target,
518 .bin_file = self,
519 .module = module,
520 };
521 defer codegen_.deinit();
508 var code_writer = std.ArrayList(u8).init(self.base.allocator);
509 defer code_writer.deinit();
510 const result = try codegen.generateFunction(
511 &self.base,
512 decl.srcLoc(),
513 func,
514 air,
515 liveness,
516 &code_writer,
517 .none,
518 );
522519
523 // generate the 'code' section for the function declaration
524 codegen_.genFunc() catch |err| switch (err) {
525 error.CodegenFail => {
520 const code = switch (result) {
521 .appended => code_writer.items,
522 .fail => |em| {
526523 decl.analysis = .codegen_failure;
527 try module.failed_decls.put(module.gpa, decl, codegen_.err_msg);
524 try module.failed_decls.put(module.gpa, decl, em);
528525 return;
529526 },
530 else => |e| return e,
531527 };
532 return self.finishUpdateDecl(decl, codegen_.code.items);
528
529 return self.finishUpdateDecl(decl, code);
533530}
534531
535532// Generate code for the Decl, storing it in memory to be later written to