From e532b0c0b5d55d212d885c779ab9f2fa7443e56a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 3 Mar 2022 18:31:55 -0700 Subject: stage2: cleanups to wasm memory intrinsics * AIR: use pl_op instead of ty_pl for wasm_memory_size. No need to store the type because the type is always `u32`. * AstGen: use coerced_ty for `@wasmMemorySize` and `@wasmMemoryGrow` and do the coercions in Sema. * Sema: use more accurate source locations for errors. * Provide more information in the compiler error message. * Codegen: use liveness data to avoid lowering unused `@wasmMemorySize`. * LLVM backend: add implementation - I wasn't able to test it because we are hitting a linker error for `-target wasm32-wasi -fLLVM`. * C backend: use `zig_unimplemented()` instead of silently doing wrong behavior for these builtins. * behavior tests: branch only on stage2_arch for inclusion of the wasm.zig file. We would change it to `builtin.cpu.arch` but that is causing a compiler crash on some backends. --- src/codegen/c.zig | 6 ++++-- src/codegen/llvm.zig | 22 ++++++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index a36b58041c..ba7bb6fa3a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -3592,14 +3592,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { } fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { - const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; + 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", .{ty_pl.payload}); + try writer.print("zig_wasm_memory_size({d});\n", .{pl_op.payload}); return local; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index bf754c975b..368a67f4b4 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3478,13 +3478,27 @@ pub const FuncGen = struct { } fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { - _ = inst; - return self.todo("implement builtin `@wasmMemorySize()`", .{}); + 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 { - _ = inst; - return self.todo("implement builtin `@wasmMemoryGrow()`", .{}); + 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 { -- cgit v1.2.3