| ... | @@ -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); |
| 799 | | 800 | |
| 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 | } |
| 803 | | 824 | |
| 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 | }; |