authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-05-16 16:15:11+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-05-19 10:37:44+02:00
logac5fd47e2ee7c43a3ad7e5d0275d4e745152a9a3
treeb1b9f2d0f88d29b5b8ac4d12c6ffce84645a9a8c
parent141a0cbb5a1ffd9e6c47bf859064139143ed8c51
signaturelock-open Commit is signed but in an unrecognized format.

Initial support for structs in wasm backend

- Creates a 'local' for the struct itself and each field - The index of the local is calculated from the struct's local index + field index

1 files changed, 31 insertions(+), 4 deletions(-)

src/codegen/wasm.zig+31-4
...@@ -556,7 +556,7 @@ pub const Context = struct {...@@ -556,7 +556,7 @@ pub const Context = struct {
556 if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64;556 if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64;
557 return self.fail(src, "Integer bit size not supported by wasm: '{d}'", .{info.bits});557 return self.fail(src, "Integer bit size not supported by wasm: '{d}'", .{info.bits});
558 },558 },
559 .Bool, .Pointer => wasm.Valtype.i32,559 .Bool, .Pointer, .Struct => wasm.Valtype.i32,
560 .Enum => switch (ty.tag()) {560 .Enum => switch (ty.tag()) {
561 .enum_simple => wasm.Valtype.i32,561 .enum_simple => wasm.Valtype.i32,
562 else => self.typeToValtype(562 else => self.typeToValtype(
...@@ -714,8 +714,8 @@ pub const Context = struct {...@@ -714,8 +714,8 @@ pub const Context = struct {
714 .add => self.genBinOp(inst.castTag(.add).?, .add),714 .add => self.genBinOp(inst.castTag(.add).?, .add),
715 .alloc => self.genAlloc(inst.castTag(.alloc).?),715 .alloc => self.genAlloc(inst.castTag(.alloc).?),
716 .arg => self.genArg(inst.castTag(.arg).?),716 .arg => self.genArg(inst.castTag(.arg).?),
717 .bitcast => self.genBitcast(inst.castTag(.bitcast).?),
718 .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"),717 .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"),
718 .bitcast => self.genBitcast(inst.castTag(.bitcast).?),
719 .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"),719 .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"),
720 .block => self.genBlock(inst.castTag(.block).?),720 .block => self.genBlock(inst.castTag(.block).?),
721 .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"),721 .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"),
...@@ -740,6 +740,7 @@ pub const Context = struct {...@@ -740,6 +740,7 @@ pub const Context = struct {
740 .ret => self.genRet(inst.castTag(.ret).?),740 .ret => self.genRet(inst.castTag(.ret).?),
741 .retvoid => WValue.none,741 .retvoid => WValue.none,
742 .store => self.genStore(inst.castTag(.store).?),742 .store => self.genStore(inst.castTag(.store).?),
743 .struct_field_ptr => self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?),
743 .sub => self.genBinOp(inst.castTag(.sub).?, .sub),744 .sub => self.genBinOp(inst.castTag(.sub).?, .sub),
744 .unreach => self.genUnreachable(inst.castTag(.unreach).?),745 .unreach => self.genUnreachable(inst.castTag(.unreach).?),
745 .xor => self.genBinOp(inst.castTag(.xor).?, .xor),746 .xor => self.genBinOp(inst.castTag(.xor).?, .xor),
...@@ -797,8 +798,28 @@ pub const Context = struct {...@@ -797,8 +798,28 @@ pub const Context = struct {
797 const valtype = try self.genValtype(inst.base.src, elem_type);798 const valtype = try self.genValtype(inst.base.src, elem_type);
798 try self.locals.append(self.gpa, valtype);799 try self.locals.append(self.gpa, valtype);
799800
800 defer self.local_index += 1;801 const local_value = WValue{ .local = self.local_index };
801 return WValue{ .local = self.local_index };802 self.local_index += 1;
803
804 switch (elem_type.zigTypeTag()) {
805 .Struct => {
806 // for each struct field, generate a local
807 const struct_data: *Module.Struct = elem_type.castTag(.@"struct").?.data;
808 try self.locals.ensureCapacity(self.gpa, self.locals.items.len + struct_data.fields.count());
809 for (struct_data.fields.items()) |entry| {
810 const val_type = try self.genValtype(
811 .{ .node_offset = struct_data.node_offset },
812 entry.value.ty,
813 );
814 self.locals.appendAssumeCapacity(val_type);
815 self.local_index += 1;
816 }
817 },
818 // TODO: Add more types that require extra locals such as optionals
819 else => {},
820 }
821
822 return local_value;
802 }823 }
803824
804 fn genStore(self: *Context, inst: *Inst.BinOp) InnerError!WValue {825 fn genStore(self: *Context, inst: *Inst.BinOp) InnerError!WValue {
...@@ -1090,4 +1111,10 @@ pub const Context = struct {...@@ -1090,4 +1111,10 @@ pub const Context = struct {
1090 fn genBitcast(self: *Context, bitcast: *Inst.UnOp) InnerError!WValue {1111 fn genBitcast(self: *Context, bitcast: *Inst.UnOp) InnerError!WValue {
1091 return self.resolveInst(bitcast.operand);1112 return self.resolveInst(bitcast.operand);
1092 }1113 }
1114
1115 fn genStructFieldPtr(self: *Context, inst: *Inst.StructFieldPtr) InnerError!WValue {
1116 const struct_ptr = self.resolveInst(inst.struct_ptr);
1117
1118 return WValue{ .local = struct_ptr.local + @intCast(u32, inst.field_index) + 1 };
1119 }
1093};1120};