diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index b1214f3bd88274f72bba8a2b9afc3214cdc0fa17..b293d20db9d704fac8024ca2597d1b432b2e940d 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -8,6 +8,7 @@ const mem = std.mem; const wasm = std.wasm; const log = std.log.scoped(.codegen); +const codegen = @import("../../codegen.zig"); const Module = @import("../../Module.zig"); const Decl = Module.Decl; const Type = @import("../../type.zig").Type; @@ -546,7 +547,7 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct { value: WValue, }) = .{}, /// `bytes` contains the wasm bytecode belonging to the 'code' section. -code: ArrayList(u8), +code: *ArrayList(u8), /// The index the next local generated will have /// NOTE: arguments share the index with locals therefore the first variable /// will have the index that comes after the last argument's index @@ -566,9 +567,6 @@ locals: std.ArrayListUnmanaged(u8), target: std.Target, /// Represents the wasm binary file that is being linked. bin_file: *link.File.Wasm, -/// Reference to the Module that this decl is part of. -/// Used to find the error value. -module: *Module, /// List of MIR Instructions mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, /// Contains extra data for MIR @@ -611,7 +609,6 @@ pub fn deinit(self: *Self) void { self.locals.deinit(self.gpa); self.mir_instructions.deinit(self.gpa); self.mir_extra.deinit(self.gpa); - self.code.deinit(); self.* = undefined; } @@ -822,7 +819,40 @@ fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type { }; } -pub fn genFunc(self: *Self) InnerError!void { +pub fn generate( + bin_file: *link.File, + src_loc: Module.SrcLoc, + func: *Module.Fn, + air: Air, + liveness: Liveness, + code: *std.ArrayList(u8), + debug_output: codegen.DebugInfoOutput, +) codegen.GenerateSymbolError!codegen.FnResult { + _ = debug_output; // TODO + _ = src_loc; + var code_gen: Self = .{ + .gpa = bin_file.allocator, + .air = air, + .liveness = liveness, + .values = .{}, + .code = code, + .decl = func.owner_decl, + .err_msg = undefined, + .locals = .{}, + .target = bin_file.options.target, + .bin_file = bin_file.cast(link.File.Wasm).?, + }; + defer code_gen.deinit(); + + genFunc(&code_gen) catch |err| switch (err) { + error.CodegenFail => return codegen.FnResult{ .fail = code_gen.err_msg }, + else => |e| return e, + }; + + return codegen.FnResult{ .appended = {} }; +} + +fn genFunc(self: *Self) InnerError!void { var func_type = try genFunctype(self.gpa, self.decl.ty, self.target); defer func_type.deinit(self.gpa); 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 { var emit: Emit = .{ .mir = mir, .bin_file = &self.bin_file.base, - .code = &self.code, + .code = self.code, .locals = self.locals.items, .decl = self.decl, }; @@ -1761,7 +1791,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { }, .ErrorSet => switch (val.tag()) { .@"error" => { - const kv = try self.module.getErrorValue(val.getError().?); + const kv = try self.bin_file.base.options.module.?.getErrorValue(val.getError().?); return WValue{ .imm32 = kv.value }; }, else => return WValue{ .imm32 = 0 }, @@ -1852,7 +1882,7 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 { .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt())), }, .ErrorSet => { - const kv = self.module.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function + const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function return @bitCast(i32, kv.value); }, else => unreachable, // Programmer called this function for an illegal type diff --git a/src/codegen.zig b/src/codegen.zig index 27f1891caf2e7e28c42ed6c2be770c20aa97f4ad..20b2968c4882b5dbb515dfa00e79333c353cb549 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -83,8 +83,6 @@ pub fn generateFunction( debug_output: DebugInfoOutput, ) GenerateSymbolError!FnResult { switch (bin_file.options.target.cpu.arch) { - .wasm32 => unreachable, // has its own code path - .wasm64 => unreachable, // has its own code path .arm, .armeb, => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output), @@ -136,6 +134,9 @@ pub fn generateFunction( //.renderscript32 => return Function(.renderscript32).generate(bin_file, src_loc, func, air, liveness, code, debug_output), //.renderscript64 => return Function(.renderscript64).generate(bin_file, src_loc, func, air, liveness, code, debug_output), //.ve => return Function(.ve).generate(bin_file, src_loc, func, air, liveness, code, debug_output), + .wasm32, + .wasm64, + => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output), 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."), } } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 4a5d9323a1df49aad010c6ecafd1a65d47b4cbb3..41930cc8dbfe031c4bb986163f10bf8c696b3b11 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -505,31 +505,28 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live decl.link.wasm.clear(self.base.allocator); - 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(); + 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