diff --git a/lib/std/heap.zig b/lib/std/heap.zig index f28f5c4b25..f05378c215 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -352,7 +352,7 @@ const WasmPageAllocator = struct { return idx + extendedOffset(); } - const prev_page_count = @wasmMemoryGrow(@intCast(u32, page_count)); + const prev_page_count = @wasmMemoryGrow(0, @intCast(u32, page_count)); if (prev_page_count <= 0) { return error.OutOfMemory; } diff --git a/src/all_types.hpp b/src/all_types.hpp index eaf7203df8..9413ea73a4 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -3737,21 +3737,27 @@ struct IrInstGenMemcpy { struct IrInstSrcWasmMemorySize { IrInstSrc base; + + IrInstSrc *index; }; struct IrInstGenWasmMemorySize { IrInstGen base; + + IrInstGen *index; }; struct IrInstSrcWasmMemoryGrow { IrInstSrc base; + IrInstSrc *index; IrInstSrc *delta; }; struct IrInstGenWasmMemoryGrow { IrInstGen base; + IrInstGen *index; IrInstGen *delta; }; diff --git a/src/codegen.cpp b/src/codegen.cpp index 765d57d7db..f945dd6545 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5620,26 +5620,16 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, Ir } static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemorySize *instruction) { - // When Wasm lands multi-memory support, we can relax this to permit the user specify - // memory index to inquire about. For now, we pass in the recommended default of index 0. - // - // More info: - // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#current-linear-memory-size // TODO adjust for wasm64 - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &zero, 1, ""); + LLVMValueRef param = ir_llvm_value(g, instruction->index); + LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), ¶m, 1, ""); return val; } static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemoryGrow *instruction) { - // When Wasm lands multi-memory support, we can relax this to permit the user specify - // memory index to inquire about. For now, we pass in the recommended default of index 0. - // - // More info: - // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#grow-linear-memory-size // TODO adjust for wasm64 LLVMValueRef params[] = { - LLVMConstNull(g->builtin_types.entry_i32->llvm_type), + ir_llvm_value(g, instruction->index), ir_llvm_value(g, instruction->delta), }; LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_grow(g), params, 2, ""); @@ -8722,8 +8712,8 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdAs, "as", 2); create_builtin_fn(g, BuiltinFnIdCall, "call", 3); create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1); - create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 0); - create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 1); + create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1); + create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2); } static const char *bool_to_str(bool b) { diff --git a/src/ir.cpp b/src/ir.cpp index 3edb61556e..aaa9599a1f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4985,35 +4985,45 @@ static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_in return &instruction->base; } -static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { +static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index) { IrInstSrcWasmMemorySize *instruction = ir_build_instruction(irb, scope, source_node); + instruction->index = index; + + ir_ref_instruction(index, irb->current_basic_block); return &instruction->base; } -static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr) { +static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index) { IrInstGenWasmMemorySize *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); instruction->base.value->type = ira->codegen->builtin_types.entry_i32; + instruction->index = index; + + ir_ref_inst_gen(index); return &instruction->base; } -static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *delta) { +static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction(irb, scope, source_node); + instruction->index = index; instruction->delta = delta; + ir_ref_instruction(index, irb->current_basic_block); ir_ref_instruction(delta, irb->current_basic_block); return &instruction->base; } -static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *delta) { +static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index, IrInstGen *delta) { IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); instruction->base.value->type = ira->codegen->builtin_types.entry_i32; + instruction->index = index; instruction->delta = delta; + ir_ref_inst_gen(index); ir_ref_inst_gen(delta); return &instruction->base; @@ -6815,7 +6825,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod } case BuiltinFnIdWasmMemorySize: { - IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node); + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; + + IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); } case BuiltinFnIdWasmMemoryGrow: @@ -6825,7 +6840,12 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value); + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) + return arg1_value; + + IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc); } case BuiltinFnIdField: @@ -27733,7 +27753,17 @@ static IrInstGen *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, IrInst return ira->codegen->invalid_inst_gen; } - return ir_build_wasm_memory_size_gen(ira, &instruction->base.base); + IrInstGen *index = instruction->index->child; + if (type_is_invalid(index->value->type)) + return ira->codegen->invalid_inst_gen; + + ZigType *i32_type = ira->codegen->builtin_types.entry_i32; + + IrInstGen *casted_index = ir_implicit_cast(ira, index, i32_type); + if (type_is_invalid(casted_index->value->type)) + return ira->codegen->invalid_inst_gen; + + return ir_build_wasm_memory_size_gen(ira, &instruction->base.base, casted_index); } static IrInstGen *ir_analyze_instruction_wasm_memory_grow(IrAnalyze *ira, IrInstSrcWasmMemoryGrow *instruction) { @@ -27744,17 +27774,25 @@ static IrInstGen *ir_analyze_instruction_wasm_memory_grow(IrAnalyze *ira, IrInst return ira->codegen->invalid_inst_gen; } - IrInstGen *delta = instruction->delta->child; - if (type_is_invalid(delta->value->type)) + IrInstGen *index = instruction->index->child; + if (type_is_invalid(index->value->type)) return ira->codegen->invalid_inst_gen; ZigType *i32_type = ira->codegen->builtin_types.entry_i32; + IrInstGen *casted_index = ir_implicit_cast(ira, index, i32_type); + if (type_is_invalid(casted_index->value->type)) + return ira->codegen->invalid_inst_gen; + + IrInstGen *delta = instruction->delta->child; + if (type_is_invalid(delta->value->type)) + return ira->codegen->invalid_inst_gen; + IrInstGen *casted_delta = ir_implicit_cast(ira, delta, i32_type); if (type_is_invalid(casted_delta->value->type)) return ira->codegen->invalid_inst_gen; - return ir_build_wasm_memory_grow_gen(ira, &instruction->base.base, casted_delta); + return ir_build_wasm_memory_grow_gen(ira, &instruction->base.base, casted_index, casted_delta); } static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index e287ca74fc..c826d76e03 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1717,21 +1717,29 @@ static void ir_print_bool_not(IrPrintGen *irp, IrInstGenBoolNot *instruction) { } static void ir_print_wasm_memory_size(IrPrintSrc *irp, IrInstSrcWasmMemorySize *instruction) { - fprintf(irp->f, "@wasmMemorySize()"); + fprintf(irp->f, "@wasmMemorySize("); + ir_print_other_inst_src(irp, instruction->index); + fprintf(irp->f, ")"); } static void ir_print_wasm_memory_size(IrPrintGen *irp, IrInstGenWasmMemorySize *instruction) { - fprintf(irp->f, "@wasmMemorySize()"); + fprintf(irp->f, "@wasmMemorySize("); + ir_print_other_inst_gen(irp, instruction->index); + fprintf(irp->f, ")"); } static void ir_print_wasm_memory_grow(IrPrintSrc *irp, IrInstSrcWasmMemoryGrow *instruction) { fprintf(irp->f, "@wasmMemoryGrow("); + ir_print_other_inst_src(irp, instruction->index); + fprintf(irp->f, ", "); ir_print_other_inst_src(irp, instruction->delta); fprintf(irp->f, ")"); } static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *instruction) { fprintf(irp->f, "@wasmMemoryGrow("); + ir_print_other_inst_gen(irp, instruction->index); + fprintf(irp->f, ", "); ir_print_other_inst_gen(irp, instruction->delta); fprintf(irp->f, ")"); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 77438e5bb0..278d66ab9f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -7507,7 +7507,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add("wasmMemorySize is a compile error in non-Wasm targets", \\export fn foo() void { - \\ _ = @wasmMemorySize(); + \\ _ = @wasmMemorySize(0); \\ return; \\} , &[_][]const u8{ @@ -7516,7 +7516,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add("wasmMemoryGrow is a compile error in non-Wasm targets", \\export fn foo() void { - \\ _ = @wasmMemoryGrow(1); + \\ _ = @wasmMemoryGrow(0, 1); \\ return; \\} , &[_][]const u8{