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;...@@ -8,6 +8,7 @@ const mem = std.mem;
8const wasm = std.wasm;8const wasm = std.wasm;
9const log = std.log.scoped(.codegen);9const log = std.log.scoped(.codegen);
1010
11const codegen = @import("../../codegen.zig");
11const Module = @import("../../Module.zig");12const Module = @import("../../Module.zig");
12const Decl = Module.Decl;13const Decl = Module.Decl;
13const Type = @import("../../type.zig").Type;14const Type = @import("../../type.zig").Type;
...@@ -546,7 +547,7 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {...@@ -546,7 +547,7 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {
546 value: WValue,547 value: WValue,
547}) = .{},548}) = .{},
548/// `bytes` contains the wasm bytecode belonging to the 'code' section.549/// `bytes` contains the wasm bytecode belonging to the 'code' section.
549code: ArrayList(u8),550code: *ArrayList(u8),
550/// The index the next local generated will have551/// The index the next local generated will have
551/// NOTE: arguments share the index with locals therefore the first variable552/// NOTE: arguments share the index with locals therefore the first variable
552/// will have the index that comes after the last argument's index553/// will have the index that comes after the last argument's index
...@@ -566,9 +567,6 @@ locals: std.ArrayListUnmanaged(u8),...@@ -566,9 +567,6 @@ locals: std.ArrayListUnmanaged(u8),
566target: std.Target,567target: std.Target,
567/// Represents the wasm binary file that is being linked.568/// Represents the wasm binary file that is being linked.
568bin_file: *link.File.Wasm,569bin_file: *link.File.Wasm,
569/// Reference to the Module that this decl is part of.
570/// Used to find the error value.
571module: *Module,
572/// List of MIR Instructions570/// List of MIR Instructions
573mir_instructions: std.MultiArrayList(Mir.Inst) = .{},571mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
574/// Contains extra data for MIR572/// Contains extra data for MIR
...@@ -611,7 +609,6 @@ pub fn deinit(self: *Self) void {...@@ -611,7 +609,6 @@ pub fn deinit(self: *Self) void {
611 self.locals.deinit(self.gpa);609 self.locals.deinit(self.gpa);
612 self.mir_instructions.deinit(self.gpa);610 self.mir_instructions.deinit(self.gpa);
613 self.mir_extra.deinit(self.gpa);611 self.mir_extra.deinit(self.gpa);
614 self.code.deinit();
615 self.* = undefined;612 self.* = undefined;
616}613}
617614
...@@ -822,7 +819,40 @@ fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type {...@@ -822,7 +819,40 @@ fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type {
822 };819 };
823}820}
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 {
826 var func_type = try genFunctype(self.gpa, self.decl.ty, self.target);856 var func_type = try genFunctype(self.gpa, self.decl.ty, self.target);
827 defer func_type.deinit(self.gpa);857 defer func_type.deinit(self.gpa);
828 self.decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);858 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 {...@@ -889,7 +919,7 @@ pub fn genFunc(self: *Self) InnerError!void {
889 var emit: Emit = .{919 var emit: Emit = .{
890 .mir = mir,920 .mir = mir,
891 .bin_file = &self.bin_file.base,921 .bin_file = &self.bin_file.base,
892 .code = &self.code,922 .code = self.code,
893 .locals = self.locals.items,923 .locals = self.locals.items,
894 .decl = self.decl,924 .decl = self.decl,
895 };925 };
...@@ -1761,7 +1791,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {...@@ -1761,7 +1791,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
1761 },1791 },
1762 .ErrorSet => switch (val.tag()) {1792 .ErrorSet => switch (val.tag()) {
1763 .@"error" => {1793 .@"error" => {
1764 const kv = try self.module.getErrorValue(val.getError().?);1794 const kv = try self.bin_file.base.options.module.?.getErrorValue(val.getError().?);
1765 return WValue{ .imm32 = kv.value };1795 return WValue{ .imm32 = kv.value };
1766 },1796 },
1767 else => return WValue{ .imm32 = 0 },1797 else => return WValue{ .imm32 = 0 },
...@@ -1852,7 +1882,7 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 {...@@ -1852,7 +1882,7 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 {
1852 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt())),1882 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt())),
1853 },1883 },
1854 .ErrorSet => {1884 .ErrorSet => {
1855 const kv = self.module.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function1885 const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
1856 return @bitCast(i32, kv.value);1886 return @bitCast(i32, kv.value);
1857 },1887 },
1858 else => unreachable, // Programmer called this function for an illegal type1888 else => unreachable, // Programmer called this function for an illegal type
src/codegen.zig+3-2
...@@ -83,8 +83,6 @@ pub fn generateFunction(...@@ -83,8 +83,6 @@ pub fn generateFunction(
83 debug_output: DebugInfoOutput,83 debug_output: DebugInfoOutput,
84) GenerateSymbolError!FnResult {84) GenerateSymbolError!FnResult {
85 switch (bin_file.options.target.cpu.arch) {85 switch (bin_file.options.target.cpu.arch) {
86 .wasm32 => unreachable, // has its own code path
87 .wasm64 => unreachable, // has its own code path
88 .arm,86 .arm,
89 .armeb,87 .armeb,
90 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),88 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
...@@ -136,6 +134,9 @@ pub fn generateFunction(...@@ -136,6 +134,9 @@ pub fn generateFunction(
136 //.renderscript32 => return Function(.renderscript32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),134 //.renderscript32 => return Function(.renderscript32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
137 //.renderscript64 => return Function(.renderscript64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),135 //.renderscript64 => return Function(.renderscript64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
138 //.ve => return Function(.ve).generate(bin_file, src_loc, func, air, liveness, code, debug_output),136 //.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),
139 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."),140 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."),
140 }141 }
141}142}
src/link/Wasm.zig+17-20
...@@ -505,31 +505,28 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live...@@ -505,31 +505,28 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
505505
506 decl.link.wasm.clear(self.base.allocator);506 decl.link.wasm.clear(self.base.allocator);
507507
508 var codegen_: CodeGen = .{508 var code_writer = std.ArrayList(u8).init(self.base.allocator);
509 .gpa = self.base.allocator,509 defer code_writer.deinit();
510 .air = air,510 const result = try codegen.generateFunction(
511 .liveness = liveness,511 &self.base,
512 .values = .{},512 decl.srcLoc(),
513 .code = std.ArrayList(u8).init(self.base.allocator),513 func,
514 .decl = decl,514 air,
515 .err_msg = undefined,515 liveness,
516 .locals = .{},516 &code_writer,
517 .target = self.base.options.target,517 .none,
518 .bin_file = self,518 );
519 .module = module,
520 };
521 defer codegen_.deinit();
522519
523 // generate the 'code' section for the function declaration520 const code = switch (result) {
524 codegen_.genFunc() catch |err| switch (err) {521 .appended => code_writer.items,
525 error.CodegenFail => {522 .fail => |em| {
526 decl.analysis = .codegen_failure;523 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);
528 return;525 return;
529 },526 },
530 else => |e| return e,
531 };527 };
532 return self.finishUpdateDecl(decl, codegen_.code.items);528
529 return self.finishUpdateDecl(decl, code);
533}530}
534531
535// Generate code for the Decl, storing it in memory to be later written to532// Generate code for the Decl, storing it in memory to be later written to