| author | |
| committer | |
| log | 7fd32de0180c29dc4e3da72e9347f6f5ce167a38 |
| tree | 6c72da6895e5da86988f6ed606eb98eee85c39ab |
| parent | 21f0503c0137b7bb59edd87e17e1649152d342ba |
This implements the wasm builtins by lowering to builtins that are supported by c-compilers.
In this case: Clang.
This also simplifies the `AIR` instruction as it now uses the payload field of `ty_pl` and `pl_op`
directly to store the index argument rather than storing it inside Extra. This saves us 4 bytes
per builtin call.6 files changed, 54 insertions(+), 26 deletions(-)
src/Air.zig+2-8| ... | @@ -584,11 +584,11 @@ pub const Inst = struct { | ... | @@ -584,11 +584,11 @@ pub const Inst = struct { |
| 584 | field_parent_ptr, | 584 | field_parent_ptr, |
| 585 | 585 | ||
| 586 | /// Implements @wasmMemorySize builtin. | 586 | /// Implements @wasmMemorySize builtin. |
| 587 | /// Uses the `ty_pl` field, payload is `WasmMemoryIndex`. | 587 | /// Uses the `ty_pl` field, payload represents the index of the target memory. |
| 588 | wasm_memory_size, | 588 | wasm_memory_size, |
| 589 | 589 | ||
| 590 | /// Implements @wasmMemoryGrow builtin. | 590 | /// Implements @wasmMemoryGrow builtin. |
| 591 | /// Uses the `pl_op` field, payload is `WasmMemoryIndex`. | 591 | /// Uses the `pl_op` field, payload represents the index of the target memory. |
| 592 | wasm_memory_grow, | 592 | wasm_memory_grow, |
| 593 | 593 | ||
| 594 | pub fn fromCmpOp(op: std.math.CompareOperator) Tag { | 594 | pub fn fromCmpOp(op: std.math.CompareOperator) Tag { |
| ... | @@ -725,12 +725,6 @@ pub const FieldParentPtr = struct { | ... | @@ -725,12 +725,6 @@ pub const FieldParentPtr = struct { |
| 725 | field_index: u32, | 725 | field_index: u32, |
| 726 | }; | 726 | }; |
| 727 | 727 | ||
| 728 | /// Wasm's memory instructions require a comptime-known index | ||
| 729 | /// which represents the memory it operates on. | ||
| 730 | pub const WasmMemoryIndex = struct { | ||
| 731 | index: u32, | ||
| 732 | }; | ||
| 733 | |||
| 734 | /// Trailing: | 728 | /// Trailing: |
| 735 | /// 0. `Inst.Ref` for every outputs_len | 729 | /// 0. `Inst.Ref` for every outputs_len |
| 736 | /// 1. `Inst.Ref` for every inputs_len | 730 | /// 1. `Inst.Ref` for every inputs_len |
src/Sema.zig+4-4| ... | @@ -14034,7 +14034,7 @@ fn zirWasmMemorySize( | ... | @@ -14034,7 +14034,7 @@ fn zirWasmMemorySize( |
| 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 src: LazySrcLoc = .{ .node_offset = extra.node }; |
| 14037 | if (!sema.mod.getTarget().isWasm()) { | 14037 | if (!sema.mod.getTarget().isWasm() and sema.mod.comp.bin_file.options.object_format != .c) { |
| 14038 | return sema.fail(block, src, "builtin '@wasmMemorySize' is a wasm feature only", .{}); | 14038 | return sema.fail(block, src, "builtin '@wasmMemorySize' is a wasm feature only", .{}); |
| 14039 | } | 14039 | } |
| 14040 | 14040 | ||
| ... | @@ -14045,7 +14045,7 @@ fn zirWasmMemorySize( | ... | @@ -14045,7 +14045,7 @@ fn zirWasmMemorySize( |
| 14045 | .tag = .wasm_memory_size, | 14045 | .tag = .wasm_memory_size, |
| 14046 | .data = .{ .ty_pl = .{ | 14046 | .data = .{ .ty_pl = .{ |
| 14047 | .ty = try sema.addType(Type.u32), | 14047 | .ty = try sema.addType(Type.u32), |
| 14048 | .payload = try sema.addExtra(Air.WasmMemoryIndex{ .index = index }), | 14048 | .payload = index, |
| 14049 | } }, | 14049 | } }, |
| 14050 | }); | 14050 | }); |
| 14051 | } | 14051 | } |
| ... | @@ -14057,7 +14057,7 @@ fn zirWasmMemoryGrow( | ... | @@ -14057,7 +14057,7 @@ fn zirWasmMemoryGrow( |
| 14057 | ) CompileError!Air.Inst.Ref { | 14057 | ) CompileError!Air.Inst.Ref { |
| 14058 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 14058 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 14059 | const src: LazySrcLoc = .{ .node_offset = extra.node }; | 14059 | const src: LazySrcLoc = .{ .node_offset = extra.node }; |
| 14060 | if (!sema.mod.getTarget().isWasm()) { | 14060 | if (!sema.mod.getTarget().isWasm() and sema.mod.comp.bin_file.options.object_format != .c) { |
| 14061 | return sema.fail(block, src, "builtin '@wasmMemoryGrow' is a wasm feature only", .{}); | 14061 | return sema.fail(block, src, "builtin '@wasmMemoryGrow' is a wasm feature only", .{}); |
| 14062 | } | 14062 | } |
| 14063 | 14063 | ||
| ... | @@ -14070,7 +14070,7 @@ fn zirWasmMemoryGrow( | ... | @@ -14070,7 +14070,7 @@ fn zirWasmMemoryGrow( |
| 14070 | .tag = .wasm_memory_grow, | 14070 | .tag = .wasm_memory_grow, |
| 14071 | .data = .{ .pl_op = .{ | 14071 | .data = .{ .pl_op = .{ |
| 14072 | .operand = delta_arg, | 14072 | .operand = delta_arg, |
| 14073 | .payload = try sema.addExtra(Air.WasmMemoryIndex{ .index = index }), | 14073 | .payload = index, |
| 14074 | } }, | 14074 | } }, |
| 14075 | }); | 14075 | }); |
| 14076 | } | 14076 | } |
src/arch/wasm/CodeGen.zig+4-6| ... | @@ -3431,22 +3431,20 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3431,22 +3431,20 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3431 | 3431 | ||
| 3432 | fn airWasmMemorySize(self: *Self, inst: Air.Inst.Index) !WValue { | 3432 | fn airWasmMemorySize(self: *Self, inst: Air.Inst.Index) !WValue { |
| 3433 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3433 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3434 | const extra = self.air.extraData(Air.WasmMemoryIndex, ty_pl.payload).data; | ||
| 3435 | 3434 | ||
| 3436 | const result = try self.allocLocal(Type.usize); | 3435 | const result = try self.allocLocal(self.air.typeOfIndex(inst)); |
| 3437 | try self.addLabel(.memory_size, extra.index); | 3436 | try self.addLabel(.memory_size, ty_pl.payload); |
| 3438 | try self.addLabel(.local_set, result.local); | 3437 | try self.addLabel(.local_set, result.local); |
| 3439 | return result; | 3438 | return result; |
| 3440 | } | 3439 | } |
| 3441 | 3440 | ||
| 3442 | fn airWasmMemoryGrow(self: *Self, inst: Air.Inst.Index) !WValue { | 3441 | fn airWasmMemoryGrow(self: *Self, inst: Air.Inst.Index) !WValue { |
| 3443 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 3442 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3444 | const extra = self.air.extraData(Air.WasmMemoryIndex, pl_op.payload).data; | ||
| 3445 | const operand = try self.resolveInst(pl_op.operand); | 3443 | const operand = try self.resolveInst(pl_op.operand); |
| 3446 | 3444 | ||
| 3447 | const result = try self.allocLocal(Type.usize); | 3445 | const result = try self.allocLocal(self.air.typeOfIndex(inst)); |
| 3448 | try self.emitWValue(operand); | 3446 | try self.emitWValue(operand); |
| 3449 | try self.addLabel(.memory_grow, extra.index); | 3447 | try self.addLabel(.memory_grow, pl_op.payload); |
| 3450 | try self.addLabel(.local_set, result.local); | 3448 | try self.addLabel(.local_set, result.local); |
| 3451 | return result; | 3449 | return result; |
| 3452 | } | 3450 | } |
src/codegen/c.zig+30-2| ... | @@ -1759,8 +1759,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1759,8 +1759,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 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 | 1761 | ||
| 1762 | .wasm_memory_size => unreachable, | 1762 | .wasm_memory_size => try airWasmMemorySize(f, inst), |
| 1763 | .wasm_memory_grow => unreachable, | 1763 | .wasm_memory_grow => try airWasmMemoryGrow(f, inst), |
| 1764 | // zig fmt: on | 1764 | // zig fmt: on |
| 1765 | }; | 1765 | }; |
| 1766 | switch (result_value) { | 1766 | switch (result_value) { |
| ... | @@ -3591,6 +3591,34 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3591,6 +3591,34 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3591 | return CValue.none; | 3591 | return CValue.none; |
| 3592 | } | 3592 | } |
| 3593 | 3593 | ||
| 3594 | fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { | ||
| 3595 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | ||
| 3596 | |||
| 3597 | const writer = f.object.writer(); | ||
| 3598 | const inst_ty = f.air.typeOfIndex(inst); | ||
| 3599 | const local = try f.allocLocal(inst_ty, .Const); | ||
| 3600 | |||
| 3601 | try writer.writeAll(" = "); | ||
| 3602 | try writer.print("zig_wasm_memory_size({d});\n", .{ty_pl.payload}); | ||
| 3603 | |||
| 3604 | return local; | ||
| 3605 | } | ||
| 3606 | |||
| 3607 | fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { | ||
| 3608 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | ||
| 3609 | |||
| 3610 | const writer = f.object.writer(); | ||
| 3611 | const inst_ty = f.air.typeOfIndex(inst); | ||
| 3612 | const operand = try f.resolveInst(pl_op.operand); | ||
| 3613 | const local = try f.allocLocal(inst_ty, .Const); | ||
| 3614 | |||
| 3615 | try writer.writeAll(" = "); | ||
| 3616 | try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload}); | ||
| 3617 | try f.writeCValue(writer, operand); | ||
| 3618 | try writer.writeAll(");\n"); | ||
| 3619 | return local; | ||
| 3620 | } | ||
| 3621 | |||
| 3594 | fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { | 3622 | fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { |
| 3595 | return switch (order) { | 3623 | return switch (order) { |
| 3596 | .Unordered => "memory_order_relaxed", | 3624 | .Unordered => "memory_order_relaxed", |
src/link/C/zig.h+12| ... | @@ -89,6 +89,18 @@ | ... | @@ -89,6 +89,18 @@ |
| 89 | #define zig_prefetch(addr, rw, locality) | 89 | #define zig_prefetch(addr, rw, locality) |
| 90 | #endif | 90 | #endif |
| 91 | 91 | ||
| 92 | #if defined(__clang__) | ||
| 93 | #define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index) | ||
| 94 | #else | ||
| 95 | #define zig_wasm_memory_size(index) 0 | ||
| 96 | #endif | ||
| 97 | |||
| 98 | #if defined(__clang__) | ||
| 99 | #define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta) | ||
| 100 | #else | ||
| 101 | #define zig_wasm_memory_grow(index, delta) 0 | ||
| 102 | #endif | ||
| 103 | |||
| 92 | #if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) | 104 | #if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) |
| 93 | #include <stdatomic.h> | 105 | #include <stdatomic.h> |
| 94 | #define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail) | 106 | #define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail) |
src/print_air.zig+2-6| ... | @@ -627,16 +627,12 @@ const Writer = struct { | ... | @@ -627,16 +627,12 @@ const Writer = struct { |
| 627 | 627 | ||
| 628 | fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 628 | fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 629 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | 629 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 630 | const extra = w.air.extraData(Air.WasmMemoryIndex, ty_pl.payload).data; | 630 | try s.print("{d}", .{ty_pl.payload}); |
| 631 | |||
| 632 | try s.print("{d}", .{extra.index}); | ||
| 633 | } | 631 | } |
| 634 | 632 | ||
| 635 | fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 633 | fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 636 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; | 634 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; |
| 637 | const extra = w.air.extraData(Air.WasmMemoryIndex, pl_op.payload).data; | 635 | try s.print("{d}, ", .{pl_op.payload}); |
| 638 | |||
| 639 | try s.print("{d}, ", .{extra.index}); | ||
| 640 | try w.writeOperand(s, inst, 0, pl_op.operand); | 636 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 641 | } | 637 | } |
| 642 | 638 |