aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/wasm.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2021-07-30 20:35:30 +0200
committerLuuk de Gram <luuk@degram.dev>2021-08-01 11:07:23 +0200
commit5667ab7dcd2e367f3e1ac337eabadd64d9d850ad (patch)
tree18a3a3a7e1c78b8db6da109718d60e6cf01a66cd /src/codegen/wasm.zig
parent5589edf45ce20b5b6d893b1a5488007981322550 (diff)
downloadzig-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.zig29
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;
+ }
};