diff options
| author | Luuk de Gram <luuk@degram.dev> | 2021-07-30 20:35:30 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2021-08-01 11:07:23 +0200 |
| commit | 5667ab7dcd2e367f3e1ac337eabadd64d9d850ad (patch) | |
| tree | 18a3a3a7e1c78b8db6da109718d60e6cf01a66cd /src/codegen/wasm.zig | |
| parent | 5589edf45ce20b5b6d893b1a5488007981322550 (diff) | |
| download | zig-5667ab7dcd2e367f3e1ac337eabadd64d9d850ad.tar.gz zig-5667ab7dcd2e367f3e1ac337eabadd64d9d850ad.zip | |
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.
Diffstat (limited to 'src/codegen/wasm.zig')
| -rw-r--r-- | src/codegen/wasm.zig | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig index 2f1632e0fc..1a23a8fa35 100644 --- a/src/codegen/wasm.zig +++ b/src/codegen/wasm.zig @@ -591,7 +591,7 @@ pub const Context = struct { .ErrorSet, => wasm.Valtype.i32, .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually. - else => self.fail("TODO - Wasm valtype for type '{s}'", .{ty.zigTypeTag()}), + else => |tag| self.fail("TODO - Wasm valtype for type '{s}'", .{tag}), }; } @@ -800,8 +800,11 @@ pub const Context = struct { const air_tags = self.air.instructions.items(.tag); return switch (air_tags[inst]) { .add => self.airBinOp(inst, .add), + .addwrap => self.airBinOp(inst, .add), .sub => self.airBinOp(inst, .sub), + .subwrap => self.airBinOp(inst, .sub), .mul => self.airBinOp(inst, .mul), + .mulwrap => self.airBinOp(inst, .mul), .div => self.airBinOp(inst, .div), .bit_and => self.airBinOp(inst, .@"and"), .bit_or => self.airBinOp(inst, .@"or"), @@ -826,6 +829,7 @@ pub const Context = struct { .cond_br => self.airCondBr(inst), .constant => unreachable, .dbg_stmt => WValue.none, + .intcast => self.airIntcast(inst), .is_err => self.airIsErr(inst, .i32_ne), .is_non_err => self.airIsErr(inst, .i32_eq), .load => self.airLoad(inst), @@ -1494,4 +1498,27 @@ pub const Context = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; return self.resolveInst(ty_op.operand); } + + fn airIntcast(self: *Context, inst: Air.Inst.Index) InnerError!WValue { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const ty = self.air.getRefType(ty_op.ty); + const operand = self.resolveInst(ty_op.operand); + const ref_ty = self.air.typeOf(ty_op.operand); + const ref_info = ref_ty.intInfo(self.target); + const op_bits = ref_info.bits; + const wanted_bits = ty.intInfo(self.target).bits; + + try self.emitWValue(operand); + if (op_bits > 32 and wanted_bits <= 32) { + try self.code.append(wasm.opcode(.i32_wrap_i64)); + } else if (op_bits <= 32 and wanted_bits > 32) { + try self.code.append(wasm.opcode(switch (ref_info.signedness) { + .signed => .i64_extend_i32_s, + .unsigned => .i64_extend_i32_u, + })); + } + + // other cases are no-op + return .none; + } }; |
