mirror of
https://github.com/ziglang/zig.git
synced 2025-12-27 08:33:15 +00:00
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.
This commit is contained in:
parent
21f0503c01
commit
7fd32de018
10
src/Air.zig
10
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
|
||||
|
||||
@ -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,
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user