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) {
162162 i32_wrap_i64 = 0xA7,
163163 i32_trunc_f32_s = 0xA8,
164164 i32_trunc_f32_u = 0xA9,
165 i32_trunc_f64_s = 0xB0,
166 i32_trunc_f64_u = 0xB1,
165 i32_trunc_f64_s = 0xAA,
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,
167173 f32_convert_i32_s = 0xB2,
168174 f32_convert_i32_u = 0xB3,
169175 f32_convert_i64_s = 0xB4,
src/codegen/wasm.zig+28-1
......@@ -591,7 +591,7 @@ pub const Context = struct {
591591 .ErrorSet,
592592 => wasm.Valtype.i32,
593593 .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}),
595595 };
596596 }
597597
......@@ -800,8 +800,11 @@ pub const Context = struct {
800800 const air_tags = self.air.instructions.items(.tag);
801801 return switch (air_tags[inst]) {
802802 .add => self.airBinOp(inst, .add),
803 .addwrap => self.airBinOp(inst, .add),
803804 .sub => self.airBinOp(inst, .sub),
805 .subwrap => self.airBinOp(inst, .sub),
804806 .mul => self.airBinOp(inst, .mul),
807 .mulwrap => self.airBinOp(inst, .mul),
805808 .div => self.airBinOp(inst, .div),
806809 .bit_and => self.airBinOp(inst, .@"and"),
807810 .bit_or => self.airBinOp(inst, .@"or"),
......@@ -826,6 +829,7 @@ pub const Context = struct {
826829 .cond_br => self.airCondBr(inst),
827830 .constant => unreachable,
828831 .dbg_stmt => WValue.none,
832 .intcast => self.airIntcast(inst),
829833 .is_err => self.airIsErr(inst, .i32_ne),
830834 .is_non_err => self.airIsErr(inst, .i32_eq),
831835 .load => self.airLoad(inst),
......@@ -1494,4 +1498,27 @@ pub const Context = struct {
14941498 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
14951499 return self.resolveInst(ty_op.operand);
14961500 }
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 }
14971524};