aboutsummaryrefslogtreecommitdiff
path: root/src/arch/wasm/CodeGen.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2021-11-24 19:09:37 +0100
committerLuuk de Gram <luuk@degram.dev>2021-11-27 15:02:01 +0100
commitf56ae69edd8c96a5f6525f20bf0a22704a826f00 (patch)
tree84778ce7a9eba390227e043e99fb6663e940f946 /src/arch/wasm/CodeGen.zig
parent17f057c5568bda6b011a213c95aa9538f6fb6a78 (diff)
downloadzig-f56ae69edd8c96a5f6525f20bf0a22704a826f00.tar.gz
zig-f56ae69edd8c96a5f6525f20bf0a22704a826f00.zip
wasm-linker: Upstream zwld into stage2
- Converts previous `DeclBlock` into `Atom`'s to also make them compatible when the rest of zlwd gets upstreamed and we can link with other object files. - Resolves function signatures and removes any duplicates, saving us a lot of potential bytes for larger projects. - We now create symbols for each decl of the respective type - We can now (but not implemented yet) perform proper relocations. - Having symbols and segment_info allows us to create an object file for wasm.
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
-rw-r--r--src/arch/wasm/CodeGen.zig68
1 files changed, 35 insertions, 33 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 468ccbea51..5bf58cd34f 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -518,9 +518,6 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {
}) = .{},
/// `bytes` contains the wasm bytecode belonging to the 'code' section.
code: ArrayList(u8),
-/// Contains the generated function type bytecode for the current function
-/// found in `decl`
-func_type_data: 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
@@ -539,7 +536,7 @@ locals: std.ArrayListUnmanaged(u8),
/// The Target we're emitting (used to call intInfo)
target: std.Target,
/// Represents the wasm binary file that is being linked.
-bin_file: *link.File,
+bin_file: *link.File.Wasm,
/// Table with the global error set. Consists of every error found in
/// the compiled code. Each error name maps to a `Module.ErrorInt` which is emitted
/// during codegen to determine the error value.
@@ -577,6 +574,7 @@ 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;
}
@@ -734,43 +732,44 @@ fn allocLocal(self: *Self, ty: Type) InnerError!WValue {
return WValue{ .local = initial_index };
}
-fn genFunctype(self: *Self) InnerError!void {
- assert(self.decl.has_tv);
- const ty = self.decl.ty;
- const writer = self.func_type_data.writer();
-
- try writer.writeByte(wasm.function_type);
+/// Generates a `wasm.Type` from a given function type.
+/// Memory is owned by the caller.
+fn genFunctype(self: *Self, fn_ty: Type) !wasm.Type {
+ var params = std.ArrayList(wasm.Valtype).init(self.gpa);
+ defer params.deinit();
+ var returns = std.ArrayList(wasm.Valtype).init(self.gpa);
+ defer returns.deinit();
// param types
- try leb.writeULEB128(writer, @intCast(u32, ty.fnParamLen()));
- if (ty.fnParamLen() != 0) {
- const params = try self.gpa.alloc(Type, ty.fnParamLen());
- defer self.gpa.free(params);
- ty.fnParamTypes(params);
- for (params) |param_type| {
- // Can we maybe get the source index of each param?
- const val_type = try self.genValtype(param_type);
- try writer.writeByte(val_type);
+ if (fn_ty.fnParamLen() != 0) {
+ const fn_params = try self.gpa.alloc(Type, fn_ty.fnParamLen());
+ defer self.gpa.free(fn_params);
+ fn_ty.fnParamTypes(fn_params);
+ for (fn_params) |param_type| {
+ if (!param_type.hasCodeGenBits()) continue;
+ try params.append(try self.typeToValtype(param_type));
}
}
// return type
- const return_type = ty.fnReturnType();
+ const return_type = fn_ty.fnReturnType();
switch (return_type.zigTypeTag()) {
- .Void, .NoReturn => try leb.writeULEB128(writer, @as(u32, 0)),
+ .Void, .NoReturn => {},
.Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}),
.Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}),
- else => {
- try leb.writeULEB128(writer, @as(u32, 1));
- const val_type = try self.genValtype(return_type);
- try writer.writeByte(val_type);
- },
+ else => try returns.append(try self.typeToValtype(return_type)),
}
+
+ return wasm.Type{
+ .params = params.toOwnedSlice(),
+ .returns = returns.toOwnedSlice(),
+ };
}
pub fn genFunc(self: *Self) InnerError!Result {
- try self.genFunctype();
- // TODO: check for and handle death of instructions
+ var func_type = try self.genFunctype(self.decl.ty);
+ defer func_type.deinit(self.gpa);
+ self.decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
var cc_result = try self.resolveCallingConventionValues(self.decl.ty);
defer cc_result.deinit(self.gpa);
@@ -791,7 +790,7 @@ pub fn genFunc(self: *Self) InnerError!Result {
var emit: Emit = .{
.mir = mir,
- .bin_file = self.bin_file,
+ .bin_file = &self.bin_file.base,
.code = &self.code,
.locals = self.locals.items,
.decl = self.decl,
@@ -813,8 +812,10 @@ pub fn genFunc(self: *Self) InnerError!Result {
pub fn gen(self: *Self, ty: Type, val: Value) InnerError!Result {
switch (ty.zigTypeTag()) {
.Fn => {
- try self.genFunctype();
if (val.tag() == .extern_fn) {
+ var func_type = try self.genFunctype(self.decl.ty);
+ defer func_type.deinit(self.gpa);
+ self.decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
return Result.appended; // don't need code body for extern functions
}
return self.fail("TODO implement wasm codegen for function pointers", .{});
@@ -1079,7 +1080,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
try self.emitWValue(arg_val);
}
- try self.addLabel(.call, target.link.wasm.symbol_index);
+ try self.addLabel(.call, target.link.wasm.sym_index);
const ret_ty = target.ty.fnReturnType();
switch (ret_ty.zigTypeTag()) {
@@ -1364,13 +1365,14 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {
decl.alive = true;
// offset into the offset table within the 'data' section
- const ptr_width = self.target.cpu.arch.ptrBitWidth() / 8;
- try self.addImm32(@bitCast(i32, decl.link.wasm.offset_index * ptr_width));
+ // const ptr_width = self.target.cpu.arch.ptrBitWidth() / 8;
+ // try self.addImm32(@bitCast(i32, decl.link.wasm.offset_index * ptr_width));
// memory instruction followed by their memarg immediate
// memarg ::== x:u32, y:u32 => {align x, offset y}
const extra_index = try self.addExtra(Mir.MemArg{ .offset = 0, .alignment = 4 });
try self.addInst(.{ .tag = .i32_load, .data = .{ .payload = extra_index } });
+ @panic("REDO!\n");
} else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()});
},
.Void => {},