authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-07-30 20:35:30+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-08-01 11:07:23+02:00
log5667ab7dcd2e367f3e1ac337eabadd64d9d850ad
tree18a3a3a7e1c78b8db6da109718d60e6cf01a66cd
parent5589edf45ce20b5b6d893b1a5488007981322550
signaturelock-open Commit is signed but in an unrecognized format.

wasm: Implement wrapping operands, add opcodes to wasm.zig

- Some opcodes have the incorrect value set in std. - Some opcodes were missing and have now been added to std. - Adding wrapping operands for add,sub and mul. - Implement intCast which either extends or shortens the type.

2 files changed, 36 insertions(+), 3 deletions(-)

lib/std/wasm.zig+8-2
...@@ -162,8 +162,14 @@ pub const Opcode = enum(u8) {...@@ -162,8 +162,14 @@ pub const Opcode = enum(u8) {
162 i32_wrap_i64 = 0xA7,162 i32_wrap_i64 = 0xA7,
163 i32_trunc_f32_s = 0xA8,163 i32_trunc_f32_s = 0xA8,
164 i32_trunc_f32_u = 0xA9,164 i32_trunc_f32_u = 0xA9,
165 i32_trunc_f64_s = 0xB0,165 i32_trunc_f64_s = 0xAA,
166 i32_trunc_f64_u = 0xB1,166 i32_trunc_f64_u = 0xAB,
167 i64_extend_i32_s = 0xAC,
168 i64_extend_i32_u = 0xAD,
169 i64_trunc_f32_s = 0xAE,
170 i64_trunc_f32_u = 0xAF,
171 i64_trunc_f64_s = 0xB0,
172 i64_trunc_f64_u = 0xB1,
167 f32_convert_i32_s = 0xB2,173 f32_convert_i32_s = 0xB2,
168 f32_convert_i32_u = 0xB3,174 f32_convert_i32_u = 0xB3,
169 f32_convert_i64_s = 0xB4,175 f32_convert_i64_s = 0xB4,
src/codegen/wasm.zig+28-1
...@@ -591,7 +591,7 @@ pub const Context = struct {...@@ -591,7 +591,7 @@ pub const Context = struct {
591 .ErrorSet,591 .ErrorSet,
592 => wasm.Valtype.i32,592 => wasm.Valtype.i32,
593 .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually.593 .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually.
594 else => self.fail("TODO - Wasm valtype for type '{s}'", .{ty.zigTypeTag()}),594 else => |tag| self.fail("TODO - Wasm valtype for type '{s}'", .{tag}),
595 };595 };
596 }596 }
597597
...@@ -800,8 +800,11 @@ pub const Context = struct {...@@ -800,8 +800,11 @@ pub const Context = struct {
800 const air_tags = self.air.instructions.items(.tag);800 const air_tags = self.air.instructions.items(.tag);
801 return switch (air_tags[inst]) {801 return switch (air_tags[inst]) {
802 .add => self.airBinOp(inst, .add),802 .add => self.airBinOp(inst, .add),
803 .addwrap => self.airBinOp(inst, .add),
803 .sub => self.airBinOp(inst, .sub),804 .sub => self.airBinOp(inst, .sub),
805 .subwrap => self.airBinOp(inst, .sub),
804 .mul => self.airBinOp(inst, .mul),806 .mul => self.airBinOp(inst, .mul),
807 .mulwrap => self.airBinOp(inst, .mul),
805 .div => self.airBinOp(inst, .div),808 .div => self.airBinOp(inst, .div),
806 .bit_and => self.airBinOp(inst, .@"and"),809 .bit_and => self.airBinOp(inst, .@"and"),
807 .bit_or => self.airBinOp(inst, .@"or"),810 .bit_or => self.airBinOp(inst, .@"or"),
...@@ -826,6 +829,7 @@ pub const Context = struct {...@@ -826,6 +829,7 @@ pub const Context = struct {
826 .cond_br => self.airCondBr(inst),829 .cond_br => self.airCondBr(inst),
827 .constant => unreachable,830 .constant => unreachable,
828 .dbg_stmt => WValue.none,831 .dbg_stmt => WValue.none,
832 .intcast => self.airIntcast(inst),
829 .is_err => self.airIsErr(inst, .i32_ne),833 .is_err => self.airIsErr(inst, .i32_ne),
830 .is_non_err => self.airIsErr(inst, .i32_eq),834 .is_non_err => self.airIsErr(inst, .i32_eq),
831 .load => self.airLoad(inst),835 .load => self.airLoad(inst),
...@@ -1494,4 +1498,27 @@ pub const Context = struct {...@@ -1494,4 +1498,27 @@ pub const Context = struct {
1494 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1498 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1495 return self.resolveInst(ty_op.operand);1499 return self.resolveInst(ty_op.operand);
1496 }1500 }
1501
1502 fn airIntcast(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
1503 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1504 const ty = self.air.getRefType(ty_op.ty);
1505 const operand = self.resolveInst(ty_op.operand);
1506 const ref_ty = self.air.typeOf(ty_op.operand);
1507 const ref_info = ref_ty.intInfo(self.target);
1508 const op_bits = ref_info.bits;
1509 const wanted_bits = ty.intInfo(self.target).bits;
1510
1511 try self.emitWValue(operand);
1512 if (op_bits > 32 and wanted_bits <= 32) {
1513 try self.code.append(wasm.opcode(.i32_wrap_i64));
1514 } else if (op_bits <= 32 and wanted_bits > 32) {
1515 try self.code.append(wasm.opcode(switch (ref_info.signedness) {
1516 .signed => .i64_extend_i32_s,
1517 .unsigned => .i64_extend_i32_u,
1518 }));
1519 }
1520
1521 // other cases are no-op
1522 return .none;
1523 }
1497};1524};