authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-03 20:39:10-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-03 20:39:10-05:00
logc9ee3c1e474a7b10fb806b60ef108057395a3cca
tree0a1e9b277c745518f2b64d8913fe5e065fe9cc1b
parent0ea51f7f494cd84a48fd997b60196d6c4254ccac
parente532b0c0b5d55d212d885c779ab9f2fa7443e56a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11048 from Luukdegram/wasm-builtins

stage2: Implement wasm builtins

18 files changed, 186 insertions(+), 13 deletions(-)

src/Air.zig+15
...@@ -583,6 +583,17 @@ pub const Inst = struct {...@@ -583,6 +583,17 @@ pub const Inst = struct {
583 /// Uses the `ty_pl` field.583 /// Uses the `ty_pl` field.
584 field_parent_ptr,584 field_parent_ptr,
585585
586 /// Implements @wasmMemorySize builtin.
587 /// Result type is always `u32`,
588 /// Uses the `pl_op` field, payload represents the index of the target memory.
589 /// The operand is unused and always set to `Ref.none`.
590 wasm_memory_size,
591
592 /// Implements @wasmMemoryGrow builtin.
593 /// Result type is always `i32`,
594 /// Uses the `pl_op` field, payload represents the index of the target memory.
595 wasm_memory_grow,
596
586 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {597 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
587 return switch (op) {598 return switch (op) {
588 .lt => .cmp_lt,599 .lt => .cmp_lt,
...@@ -618,6 +629,7 @@ pub const Inst = struct {...@@ -618,6 +629,7 @@ pub const Inst = struct {
618 pub const Data = union {629 pub const Data = union {
619 no_op: void,630 no_op: void,
620 un_op: Ref,631 un_op: Ref,
632
621 bin_op: struct {633 bin_op: struct {
622 lhs: Ref,634 lhs: Ref,
623 rhs: Ref,635 rhs: Ref,
...@@ -945,6 +957,9 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -945,6 +957,9 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
945 .frame_addr,957 .frame_addr,
946 => return Type.initTag(.usize),958 => return Type.initTag(.usize),
947959
960 .wasm_memory_grow => return Type.i32,
961 .wasm_memory_size => return Type.u32,
962
948 .bool_to_int => return Type.initTag(.u1),963 .bool_to_int => return Type.initTag(.u1),
949964
950 .tag_name, .error_name => return Type.initTag(.const_slice_u8_sentinel_0),965 .tag_name, .error_name => return Type.initTag(.const_slice_u8_sentinel_0),
src/AstGen.zig+3-3
...@@ -7140,7 +7140,7 @@ fn builtinCall(...@@ -7140,7 +7140,7 @@ fn builtinCall(
7140 // zig fmt: on7140 // zig fmt: on
71417141
7142 .wasm_memory_size => {7142 .wasm_memory_size => {
7143 const operand = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);7143 const operand = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);
7144 const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{7144 const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{
7145 .node = gz.nodeIndexToRelative(node),7145 .node = gz.nodeIndexToRelative(node),
7146 .operand = operand,7146 .operand = operand,
...@@ -7148,8 +7148,8 @@ fn builtinCall(...@@ -7148,8 +7148,8 @@ fn builtinCall(
7148 return rvalue(gz, rl, result, node);7148 return rvalue(gz, rl, result, node);
7149 },7149 },
7150 .wasm_memory_grow => {7150 .wasm_memory_grow => {
7151 const index_arg = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);7151 const index_arg = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]);
7152 const delta_arg = try expr(gz, scope, .{ .ty = .u32_type }, params[1]);7152 const delta_arg = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[1]);
7153 const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{7153 const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{
7154 .node = gz.nodeIndexToRelative(node),7154 .node = gz.nodeIndexToRelative(node),
7155 .lhs = index_arg,7155 .lhs = index_arg,
src/Liveness.zig+5
...@@ -318,6 +318,7 @@ fn analyzeInst(...@@ -318,6 +318,7 @@ fn analyzeInst(
318 .fence,318 .fence,
319 .ret_addr,319 .ret_addr,
320 .frame_addr,320 .frame_addr,
321 .wasm_memory_size,
321 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),322 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
322323
323 .not,324 .not,
...@@ -706,6 +707,10 @@ fn analyzeInst(...@@ -706,6 +707,10 @@ fn analyzeInst(
706707
707 return trackOperands(a, new_set, inst, main_tomb, .{ condition, .none, .none });708 return trackOperands(a, new_set, inst, main_tomb, .{ condition, .none, .none });
708 },709 },
710 .wasm_memory_grow => {
711 const pl_op = inst_datas[inst].pl_op;
712 return trackOperands(a, new_set, inst, main_tomb, .{ pl_op.operand, .none, .none });
713 },
709 }714 }
710}715}
711716
src/Sema.zig+35-4
...@@ -14033,8 +14033,22 @@ fn zirWasmMemorySize(...@@ -14033,8 +14033,22 @@ fn zirWasmMemorySize(
14033 extended: Zir.Inst.Extended.InstData,14033 extended: Zir.Inst.Extended.InstData,
14034) CompileError!Air.Inst.Ref {14034) CompileError!Air.Inst.Ref {
14035 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;14035 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
14036 const src: LazySrcLoc = .{ .node_offset = extra.node };14036 const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
14037 return sema.fail(block, src, "TODO: implement Sema.zirWasmMemorySize", .{});14037 const builtin_src: LazySrcLoc = .{ .node_offset = extra.node };
14038 const target = sema.mod.getTarget();
14039 if (!target.isWasm()) {
14040 return sema.fail(block, builtin_src, "builtin @wasmMemorySize is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)});
14041 }
14042
14043 const index = @intCast(u32, try sema.resolveInt(block, index_src, extra.operand, Type.u32));
14044 try sema.requireRuntimeBlock(block, builtin_src);
14045 return block.addInst(.{
14046 .tag = .wasm_memory_size,
14047 .data = .{ .pl_op = .{
14048 .operand = .none,
14049 .payload = index,
14050 } },
14051 });
14038}14052}
1403914053
14040fn zirWasmMemoryGrow(14054fn zirWasmMemoryGrow(
...@@ -14043,8 +14057,25 @@ fn zirWasmMemoryGrow(...@@ -14043,8 +14057,25 @@ fn zirWasmMemoryGrow(
14043 extended: Zir.Inst.Extended.InstData,14057 extended: Zir.Inst.Extended.InstData,
14044) CompileError!Air.Inst.Ref {14058) CompileError!Air.Inst.Ref {
14045 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;14059 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
14046 const src: LazySrcLoc = .{ .node_offset = extra.node };14060 const builtin_src: LazySrcLoc = .{ .node_offset = extra.node };
14047 return sema.fail(block, src, "TODO: implement Sema.zirWasmMemoryGrow", .{});14061 const index_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
14062 const delta_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
14063 const target = sema.mod.getTarget();
14064 if (!target.isWasm()) {
14065 return sema.fail(block, builtin_src, "builtin @wasmMemoryGrow is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)});
14066 }
14067
14068 const index = @intCast(u32, try sema.resolveInt(block, index_src, extra.lhs, Type.u32));
14069 const delta = try sema.coerce(block, Type.u32, sema.resolveInst(extra.rhs), delta_src);
14070
14071 try sema.requireRuntimeBlock(block, builtin_src);
14072 return block.addInst(.{
14073 .tag = .wasm_memory_grow,
14074 .data = .{ .pl_op = .{
14075 .operand = delta,
14076 .payload = index,
14077 } },
14078 });
14048}14079}
1404914080
14050fn zirPrefetch(14081fn zirPrefetch(
src/arch/aarch64/CodeGen.zig+3
...@@ -671,6 +671,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -671,6 +671,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
671 .wrap_optional => try self.airWrapOptional(inst),671 .wrap_optional => try self.airWrapOptional(inst),
672 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),672 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
673 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),673 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
674
675 .wasm_memory_size => unreachable,
676 .wasm_memory_grow => unreachable,
674 // zig fmt: on677 // zig fmt: on
675 }678 }
676679
src/arch/arm/CodeGen.zig+3
...@@ -669,6 +669,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -669,6 +669,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
669 .wrap_optional => try self.airWrapOptional(inst),669 .wrap_optional => try self.airWrapOptional(inst),
670 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),670 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
671 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),671 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
672
673 .wasm_memory_size => unreachable,
674 .wasm_memory_grow => unreachable,
672 // zig fmt: on675 // zig fmt: on
673 }676 }
674677
src/arch/riscv64/CodeGen.zig+3
...@@ -642,6 +642,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -642,6 +642,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
642 .wrap_optional => try self.airWrapOptional(inst),642 .wrap_optional => try self.airWrapOptional(inst),
643 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),643 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
644 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),644 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
645
646 .wasm_memory_size => unreachable,
647 .wasm_memory_grow => unreachable,
645 // zig fmt: on648 // zig fmt: on
646 }649 }
647 if (std.debug.runtime_safety) {650 if (std.debug.runtime_safety) {
src/arch/wasm/CodeGen.zig+25
...@@ -1671,6 +1671,9 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1671,6 +1671,9 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1671 .wrap_errunion_payload => self.airWrapErrUnionPayload(inst),1671 .wrap_errunion_payload => self.airWrapErrUnionPayload(inst),
1672 .wrap_errunion_err => self.airWrapErrUnionErr(inst),1672 .wrap_errunion_err => self.airWrapErrUnionErr(inst),
16731673
1674 .wasm_memory_size => self.airWasmMemorySize(inst),
1675 .wasm_memory_grow => self.airWasmMemoryGrow(inst),
1676
1674 .add_sat,1677 .add_sat,
1675 .sub_sat,1678 .sub_sat,
1676 .mul_sat,1679 .mul_sat,
...@@ -3426,6 +3429,28 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -3426,6 +3429,28 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3426 return WValue{ .none = {} };3429 return WValue{ .none = {} };
3427}3430}
34283431
3432fn airWasmMemorySize(self: *Self, inst: Air.Inst.Index) !WValue {
3433 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
3434
3435 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3436
3437 const result = try self.allocLocal(self.air.typeOfIndex(inst));
3438 try self.addLabel(.memory_size, pl_op.payload);
3439 try self.addLabel(.local_set, result.local);
3440 return result;
3441}
3442
3443fn airWasmMemoryGrow(self: *Self, inst: Air.Inst.Index) !WValue {
3444 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3445 const operand = try self.resolveInst(pl_op.operand);
3446
3447 const result = try self.allocLocal(self.air.typeOfIndex(inst));
3448 try self.emitWValue(operand);
3449 try self.addLabel(.memory_grow, pl_op.payload);
3450 try self.addLabel(.local_set, result.local);
3451 return result;
3452}
3453
3429fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {3454fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
3430 assert(operand_ty.hasRuntimeBits());3455 assert(operand_ty.hasRuntimeBits());
3431 assert(op == .eq or op == .neq);3456 assert(op == .eq or op == .neq);
src/arch/wasm/Emit.zig+1-1
...@@ -89,10 +89,10 @@ pub fn emitMir(emit: *Emit) InnerError!void {...@@ -89,10 +89,10 @@ pub fn emitMir(emit: *Emit) InnerError!void {
89 .local_set => try emit.emitLabel(tag, inst),89 .local_set => try emit.emitLabel(tag, inst),
90 .local_tee => try emit.emitLabel(tag, inst),90 .local_tee => try emit.emitLabel(tag, inst),
91 .memory_grow => try emit.emitLabel(tag, inst),91 .memory_grow => try emit.emitLabel(tag, inst),
92 .memory_size => try emit.emitLabel(tag, inst),
9293
93 // no-ops94 // no-ops
94 .end => try emit.emitTag(tag),95 .end => try emit.emitTag(tag),
95 .memory_size => try emit.emitTag(tag),
96 .@"return" => try emit.emitTag(tag),96 .@"return" => try emit.emitTag(tag),
97 .@"unreachable" => try emit.emitTag(tag),97 .@"unreachable" => try emit.emitTag(tag),
9898
src/arch/wasm/Mir.zig+2-2
...@@ -226,9 +226,9 @@ pub const Inst = struct {...@@ -226,9 +226,9 @@ pub const Inst = struct {
226 i64_store32 = 0x3E,226 i64_store32 = 0x3E,
227 /// Returns the memory size in amount of pages.227 /// Returns the memory size in amount of pages.
228 ///228 ///
229 /// Uses `nop`229 /// Uses `label`
230 memory_size = 0x3F,230 memory_size = 0x3F,
231 /// Increases the memory at by given number of pages.231 /// Increases the memory by given number of pages.
232 ///232 ///
233 /// Uses `label`233 /// Uses `label`
234 memory_grow = 0x40,234 memory_grow = 0x40,
src/arch/x86_64/CodeGen.zig+3
...@@ -759,6 +759,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -759,6 +759,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
759 .wrap_optional => try self.airWrapOptional(inst),759 .wrap_optional => try self.airWrapOptional(inst),
760 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),760 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
761 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),761 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
762
763 .wasm_memory_size => unreachable,
764 .wasm_memory_grow => unreachable,
762 // zig fmt: on765 // zig fmt: on
763 }766 }
764767
src/codegen/c.zig+33
...@@ -1758,6 +1758,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1758,6 +1758,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1758 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),1758 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
1759 .wrap_errunion_err => try airWrapErrUnionErr(f, inst),1759 .wrap_errunion_err => try airWrapErrUnionErr(f, inst),
1760 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),1760 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
1761
1762 .wasm_memory_size => try airWasmMemorySize(f, inst),
1763 .wasm_memory_grow => try airWasmMemoryGrow(f, inst),
1761 // zig fmt: on1764 // zig fmt: on
1762 };1765 };
1763 switch (result_value) {1766 switch (result_value) {
...@@ -3588,6 +3591,36 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3588,6 +3591,36 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
3588 return CValue.none;3591 return CValue.none;
3589}3592}
35903593
3594fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
3595 if (f.liveness.isUnused(inst)) return CValue.none;
3596
3597 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
3598
3599 const writer = f.object.writer();
3600 const inst_ty = f.air.typeOfIndex(inst);
3601 const local = try f.allocLocal(inst_ty, .Const);
3602
3603 try writer.writeAll(" = ");
3604 try writer.print("zig_wasm_memory_size({d});\n", .{pl_op.payload});
3605
3606 return local;
3607}
3608
3609fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
3610 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
3611
3612 const writer = f.object.writer();
3613 const inst_ty = f.air.typeOfIndex(inst);
3614 const operand = try f.resolveInst(pl_op.operand);
3615 const local = try f.allocLocal(inst_ty, .Const);
3616
3617 try writer.writeAll(" = ");
3618 try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
3619 try f.writeCValue(writer, operand);
3620 try writer.writeAll(");\n");
3621 return local;
3622}
3623
3591fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {3624fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
3592 return switch (order) {3625 return switch (order) {
3593 .Unordered => "memory_order_relaxed",3626 .Unordered => "memory_order_relaxed",
src/codegen/llvm.zig+27
...@@ -2314,6 +2314,9 @@ pub const FuncGen = struct {...@@ -2314,6 +2314,9 @@ pub const FuncGen = struct {
2314 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),2314 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
2315 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),2315 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
23162316
2317 .wasm_memory_size => try self.airWasmMemorySize(inst),
2318 .wasm_memory_grow => try self.airWasmMemoryGrow(inst),
2319
2317 .constant => unreachable,2320 .constant => unreachable,
2318 .const_ty => unreachable,2321 .const_ty => unreachable,
2319 .unreach => self.airUnreach(inst),2322 .unreach => self.airUnreach(inst),
...@@ -3474,6 +3477,30 @@ pub const FuncGen = struct {...@@ -3474,6 +3477,30 @@ pub const FuncGen = struct {
3474 return partial;3477 return partial;
3475 }3478 }
34763479
3480 fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
3481 if (self.liveness.isUnused(inst)) return null;
3482
3483 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3484 const index = pl_op.payload;
3485 const llvm_u32 = self.context.intType(32);
3486 const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size.i32", &.{llvm_u32});
3487 const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)};
3488 return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, "");
3489 }
3490
3491 fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
3492 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3493 const index = pl_op.payload;
3494 const operand = try self.resolveInst(pl_op.operand);
3495 const llvm_u32 = self.context.intType(32);
3496 const llvm_fn = self.getIntrinsic("llvm.wasm.memory.grow.i32", &.{ llvm_u32, llvm_u32 });
3497 const args: [2]*const llvm.Value = .{
3498 llvm_u32.constInt(index, .False),
3499 operand,
3500 };
3501 return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, "");
3502 }
3503
3477 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {3504 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
3478 if (self.liveness.isUnused(inst)) return null;3505 if (self.liveness.isUnused(inst)) return null;
34793506
src/link/C/zig.h+8
...@@ -89,6 +89,14 @@...@@ -89,6 +89,14 @@
89#define zig_prefetch(addr, rw, locality)89#define zig_prefetch(addr, rw, locality)
90#endif90#endif
9191
92#if defined(__clang__)
93#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
94#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
95#else
96#define zig_wasm_memory_size(index) zig_unimplemented()
97#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
98#endif
99
92#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)100#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
93#include <stdatomic.h>101#include <stdatomic.h>
94#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)102#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
src/print_air.zig+13
...@@ -250,6 +250,8 @@ const Writer = struct {...@@ -250,6 +250,8 @@ const Writer = struct {
250 .memcpy => try w.writeMemcpy(s, inst),250 .memcpy => try w.writeMemcpy(s, inst),
251 .memset => try w.writeMemset(s, inst),251 .memset => try w.writeMemset(s, inst),
252 .field_parent_ptr => try w.writeFieldParentPtr(s, inst),252 .field_parent_ptr => try w.writeFieldParentPtr(s, inst),
253 .wasm_memory_size => try w.writeWasmMemorySize(s, inst),
254 .wasm_memory_grow => try w.writeWasmMemoryGrow(s, inst),
253255
254 .add_with_overflow,256 .add_with_overflow,
255 .sub_with_overflow,257 .sub_with_overflow,
...@@ -623,6 +625,17 @@ const Writer = struct {...@@ -623,6 +625,17 @@ const Writer = struct {
623 try s.writeAll("}");625 try s.writeAll("}");
624 }626 }
625627
628 fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
629 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
630 try s.print("{d}", .{pl_op.payload});
631 }
632
633 fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
634 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
635 try s.print("{d}, ", .{pl_op.payload});
636 try w.writeOperand(s, inst, 0, pl_op.operand);
637 }
638
626 fn writeOperand(639 fn writeOperand(
627 w: *Writer,640 w: *Writer,
628 s: anytype,641 s: anytype,
src/type.zig+2
...@@ -5256,6 +5256,8 @@ pub const Type = extern union {...@@ -5256,6 +5256,8 @@ pub const Type = extern union {
5256 pub const @"u32" = initTag(.u32);5256 pub const @"u32" = initTag(.u32);
5257 pub const @"u64" = initTag(.u64);5257 pub const @"u64" = initTag(.u64);
52585258
5259 pub const @"i32" = initTag(.i32);
5260
5259 pub const @"f16" = initTag(.f16);5261 pub const @"f16" = initTag(.f16);
5260 pub const @"f32" = initTag(.f32);5262 pub const @"f32" = initTag(.f32);
5261 pub const @"f64" = initTag(.f64);5263 pub const @"f64" = initTag(.f64);
test/behavior.zig+4-3
...@@ -96,6 +96,10 @@ test {...@@ -96,6 +96,10 @@ test {
96 _ = @import("behavior/void.zig");96 _ = @import("behavior/void.zig");
97 _ = @import("behavior/while.zig");97 _ = @import("behavior/while.zig");
9898
99 if (builtin.stage2_arch == .wasm32) {
100 _ = @import("behavior/wasm.zig");
101 }
102
99 if (builtin.zig_backend != .stage1) {103 if (builtin.zig_backend != .stage1) {
100 _ = @import("behavior/decltest.zig");104 _ = @import("behavior/decltest.zig");
101 }105 }
...@@ -168,9 +172,6 @@ test {...@@ -168,9 +172,6 @@ test {
168 _ = @import("behavior/struct_contains_slice_of_itself.zig");172 _ = @import("behavior/struct_contains_slice_of_itself.zig");
169 _ = @import("behavior/typename.zig");173 _ = @import("behavior/typename.zig");
170 _ = @import("behavior/vector.zig");174 _ = @import("behavior/vector.zig");
171 if (builtin.target.cpu.arch == .wasm32) {
172 _ = @import("behavior/wasm.zig");
173 }
174 }175 }
175 }176 }
176 }177 }
test/behavior/wasm.zig+1
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const builtin = @import("builtin");
34
4test "memory size and grow" {5test "memory size and grow" {
5 var prev = @wasmMemorySize(0);6 var prev = @wasmMemorySize(0);