aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-03-03 22:12:53 +0100
committerAndrew Kelley <andrew@ziglang.org>2022-03-03 16:33:46 -0700
commit7fd32de0180c29dc4e3da72e9347f6f5ce167a38 (patch)
tree6c72da6895e5da86988f6ed606eb98eee85c39ab /src
parent21f0503c0137b7bb59edd87e17e1649152d342ba (diff)
downloadzig-7fd32de0180c29dc4e3da72e9347f6f5ce167a38.tar.gz
zig-7fd32de0180c29dc4e3da72e9347f6f5ce167a38.zip
cbe: Implement wasm builtins
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.
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig10
-rw-r--r--src/Sema.zig8
-rw-r--r--src/arch/wasm/CodeGen.zig10
-rw-r--r--src/codegen/c.zig32
-rw-r--r--src/link/C/zig.h12
-rw-r--r--src/print_air.zig8
6 files changed, 54 insertions, 26 deletions
diff --git a/src/Air.zig b/src/Air.zig
index e00720f534..874af09b71 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -584,11 +584,11 @@ pub const Inst = struct {
field_parent_ptr,
/// Implements @wasmMemorySize builtin.
- /// Uses the `ty_pl` field, payload is `WasmMemoryIndex`.
+ /// Uses the `ty_pl` field, payload represents the index of the target memory.
wasm_memory_size,
/// Implements @wasmMemoryGrow builtin.
- /// Uses the `pl_op` field, payload is `WasmMemoryIndex`.
+ /// Uses the `pl_op` field, payload represents the index of the target memory.
wasm_memory_grow,
pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
@@ -725,12 +725,6 @@ pub const FieldParentPtr = struct {
field_index: u32,
};
-/// Wasm's memory instructions require a comptime-known index
-/// which represents the memory it operates on.
-pub const WasmMemoryIndex = struct {
- index: u32,
-};
-
/// Trailing:
/// 0. `Inst.Ref` for every outputs_len
/// 1. `Inst.Ref` for every inputs_len
diff --git a/src/Sema.zig b/src/Sema.zig
index a8dc872a99..65536cdbde 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -14034,7 +14034,7 @@ fn zirWasmMemorySize(
) CompileError!Air.Inst.Ref {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
- if (!sema.mod.getTarget().isWasm()) {
+ if (!sema.mod.getTarget().isWasm() and sema.mod.comp.bin_file.options.object_format != .c) {
return sema.fail(block, src, "builtin '@wasmMemorySize' is a wasm feature only", .{});
}
@@ -14045,7 +14045,7 @@ fn zirWasmMemorySize(
.tag = .wasm_memory_size,
.data = .{ .ty_pl = .{
.ty = try sema.addType(Type.u32),
- .payload = try sema.addExtra(Air.WasmMemoryIndex{ .index = index }),
+ .payload = index,
} },
});
}
@@ -14057,7 +14057,7 @@ fn zirWasmMemoryGrow(
) CompileError!Air.Inst.Ref {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
- if (!sema.mod.getTarget().isWasm()) {
+ if (!sema.mod.getTarget().isWasm() and sema.mod.comp.bin_file.options.object_format != .c) {
return sema.fail(block, src, "builtin '@wasmMemoryGrow' is a wasm feature only", .{});
}
@@ -14070,7 +14070,7 @@ fn zirWasmMemoryGrow(
.tag = .wasm_memory_grow,
.data = .{ .pl_op = .{
.operand = delta_arg,
- .payload = try sema.addExtra(Air.WasmMemoryIndex{ .index = index }),
+ .payload = index,
} },
});
}
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index b4917738dd..b1c4be9fef 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -3431,22 +3431,20 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airWasmMemorySize(self: *Self, inst: Air.Inst.Index) !WValue {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
- const extra = self.air.extraData(Air.WasmMemoryIndex, ty_pl.payload).data;
- const result = try self.allocLocal(Type.usize);
- try self.addLabel(.memory_size, extra.index);
+ const result = try self.allocLocal(self.air.typeOfIndex(inst));
+ try self.addLabel(.memory_size, ty_pl.payload);
try self.addLabel(.local_set, result.local);
return result;
}
fn airWasmMemoryGrow(self: *Self, inst: Air.Inst.Index) !WValue {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
- const extra = self.air.extraData(Air.WasmMemoryIndex, pl_op.payload).data;
const operand = try self.resolveInst(pl_op.operand);
- const result = try self.allocLocal(Type.usize);
+ const result = try self.allocLocal(self.air.typeOfIndex(inst));
try self.emitWValue(operand);
- try self.addLabel(.memory_grow, extra.index);
+ try self.addLabel(.memory_grow, pl_op.payload);
try self.addLabel(.local_set, result.local);
return result;
}
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 988576a6f1..a36b58041c 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1759,8 +1759,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.wrap_errunion_err => try airWrapErrUnionErr(f, inst),
.errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
- .wasm_memory_size => unreachable,
- .wasm_memory_grow => unreachable,
+ .wasm_memory_size => try airWasmMemorySize(f, inst),
+ .wasm_memory_grow => try airWasmMemoryGrow(f, inst),
// zig fmt: on
};
switch (result_value) {
@@ -3591,6 +3591,34 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
return CValue.none;
}
+fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
+ const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
+
+ const writer = f.object.writer();
+ const inst_ty = f.air.typeOfIndex(inst);
+ const local = try f.allocLocal(inst_ty, .Const);
+
+ try writer.writeAll(" = ");
+ try writer.print("zig_wasm_memory_size({d});\n", .{ty_pl.payload});
+
+ return local;
+}
+
+fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
+ const pl_op = f.air.instructions.items(.data)[inst].pl_op;
+
+ const writer = f.object.writer();
+ const inst_ty = f.air.typeOfIndex(inst);
+ const operand = try f.resolveInst(pl_op.operand);
+ const local = try f.allocLocal(inst_ty, .Const);
+
+ try writer.writeAll(" = ");
+ try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
+ try f.writeCValue(writer, operand);
+ try writer.writeAll(");\n");
+ return local;
+}
+
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
.Unordered => "memory_order_relaxed",
diff --git a/src/link/C/zig.h b/src/link/C/zig.h
index 4a725ca678..bf94f44c8f 100644
--- a/src/link/C/zig.h
+++ b/src/link/C/zig.h
@@ -89,6 +89,18 @@
#define zig_prefetch(addr, rw, locality)
#endif
+#if defined(__clang__)
+#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
+#else
+#define zig_wasm_memory_size(index) 0
+#endif
+
+#if defined(__clang__)
+#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
+#else
+#define zig_wasm_memory_grow(index, delta) 0
+#endif
+
#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
#include <stdatomic.h>
#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
diff --git a/src/print_air.zig b/src/print_air.zig
index 3dd1decf53..3158daee6d 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -627,16 +627,12 @@ const Writer = struct {
fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
- const extra = w.air.extraData(Air.WasmMemoryIndex, ty_pl.payload).data;
-
- try s.print("{d}", .{extra.index});
+ try s.print("{d}", .{ty_pl.payload});
}
fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const pl_op = w.air.instructions.items(.data)[inst].pl_op;
- const extra = w.air.extraData(Air.WasmMemoryIndex, pl_op.payload).data;
-
- try s.print("{d}, ", .{extra.index});
+ try s.print("{d}, ", .{pl_op.payload});
try w.writeOperand(s, inst, 0, pl_op.operand);
}