aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-03 20:39:10 -0500
committerGitHub <noreply@github.com>2022-03-03 20:39:10 -0500
commitc9ee3c1e474a7b10fb806b60ef108057395a3cca (patch)
tree0a1e9b277c745518f2b64d8913fe5e065fe9cc1b /src/codegen
parent0ea51f7f494cd84a48fd997b60196d6c4254ccac (diff)
parente532b0c0b5d55d212d885c779ab9f2fa7443e56a (diff)
downloadzig-c9ee3c1e474a7b10fb806b60ef108057395a3cca.tar.gz
zig-c9ee3c1e474a7b10fb806b60ef108057395a3cca.zip
Merge pull request #11048 from Luukdegram/wasm-builtins
stage2: Implement wasm builtins
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig33
-rw-r--r--src/codegen/llvm.zig27
2 files changed, 60 insertions, 0 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 3e47637c76..ba7bb6fa3a 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1758,6 +1758,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
.wrap_errunion_err => try airWrapErrUnionErr(f, inst),
.errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
+
+ .wasm_memory_size => try airWasmMemorySize(f, inst),
+ .wasm_memory_grow => try airWasmMemoryGrow(f, inst),
// zig fmt: on
};
switch (result_value) {
@@ -3588,6 +3591,36 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
return CValue.none;
}
+fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
+ if (f.liveness.isUnused(inst)) return CValue.none;
+
+ const pl_op = f.air.instructions.items(.data)[inst].pl_op;
+
+ 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", .{pl_op.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/codegen/llvm.zig b/src/codegen/llvm.zig
index 252d449fc2..368a67f4b4 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2314,6 +2314,9 @@ pub const FuncGen = struct {
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
+ .wasm_memory_size => try self.airWasmMemorySize(inst),
+ .wasm_memory_grow => try self.airWasmMemoryGrow(inst),
+
.constant => unreachable,
.const_ty => unreachable,
.unreach => self.airUnreach(inst),
@@ -3474,6 +3477,30 @@ pub const FuncGen = struct {
return partial;
}
+ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst)) return null;
+
+ const pl_op = self.air.instructions.items(.data)[inst].pl_op;
+ const index = pl_op.payload;
+ const llvm_u32 = self.context.intType(32);
+ const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size.i32", &.{llvm_u32});
+ const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)};
+ return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, "");
+ }
+
+ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ const pl_op = self.air.instructions.items(.data)[inst].pl_op;
+ const index = pl_op.payload;
+ const operand = try self.resolveInst(pl_op.operand);
+ const llvm_u32 = self.context.intType(32);
+ const llvm_fn = self.getIntrinsic("llvm.wasm.memory.grow.i32", &.{ llvm_u32, llvm_u32 });
+ const args: [2]*const llvm.Value = .{
+ llvm_u32.constInt(index, .False),
+ operand,
+ };
+ return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, "");
+ }
+
fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;