mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 07:03:11 +00:00
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.
This commit is contained in:
parent
2faba4092a
commit
13fca53b92
@ -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
|
||||
|
||||
@ -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."),
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user