| author | |
| committer | |
| log | 601e831f1d15ba5c8f89fbab265a72bfabb6af96 |
| tree | 2883351a9ebaa4759b239bff24090133e5f8961c |
| parent | ce3f0077cf3c5ae8edc116177f2f3d33258be9f7 |
This will allow the developer to request additional memory pages
from the runtime to be allocated for the Wasm app. Typical usage:
```zig
var wasm_pages = @wasmMemorySize();
@wasmMemoryGrow(1);
@import("std").debug.assert((wasm_pages + 1) == @wasmMemorySize());
```4 files changed, 166 insertions(+), 22 deletions(-)
src/all_types.hpp+18-2| ... | @@ -1826,6 +1826,7 @@ enum BuiltinFnId { | ... | @@ -1826,6 +1826,7 @@ enum BuiltinFnId { |
| 1826 | BuiltinFnIdCall, | 1826 | BuiltinFnIdCall, |
| 1827 | BuiltinFnIdBitSizeof, | 1827 | BuiltinFnIdBitSizeof, |
| 1828 | BuiltinFnIdWasmMemorySize, | 1828 | BuiltinFnIdWasmMemorySize, |
| 1829 | BuiltinFnIdWasmMemoryGrow, | ||
| 1829 | }; | 1830 | }; |
| 1830 | 1831 | ||
| 1831 | struct BuiltinFnEntry { | 1832 | struct BuiltinFnEntry { |
| ... | @@ -2077,6 +2078,7 @@ struct CodeGen { | ... | @@ -2077,6 +2078,7 @@ struct CodeGen { |
| 2077 | LLVMValueRef safety_crash_err_fn; | 2078 | LLVMValueRef safety_crash_err_fn; |
| 2078 | LLVMValueRef return_err_fn; | 2079 | LLVMValueRef return_err_fn; |
| 2079 | LLVMValueRef wasm_memory_size; | 2080 | LLVMValueRef wasm_memory_size; |
| 2081 | LLVMValueRef wasm_memory_grow; | ||
| 2080 | LLVMTypeRef anyframe_fn_type; | 2082 | LLVMTypeRef anyframe_fn_type; |
| 2081 | 2083 | ||
| 2082 | // reminder: hash tables must be initialized before use | 2084 | // reminder: hash tables must be initialized before use |
| ... | @@ -2751,6 +2753,7 @@ enum IrInstSrcId { | ... | @@ -2751,6 +2753,7 @@ enum IrInstSrcId { |
| 2751 | IrInstSrcIdSpillBegin, | 2753 | IrInstSrcIdSpillBegin, |
| 2752 | IrInstSrcIdSpillEnd, | 2754 | IrInstSrcIdSpillEnd, |
| 2753 | IrInstSrcIdWasmMemorySize, | 2755 | IrInstSrcIdWasmMemorySize, |
| 2756 | IrInstSrcIdWasmMemoryGrow, | ||
| 2754 | }; | 2757 | }; |
| 2755 | 2758 | ||
| 2756 | // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. | 2759 | // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. |
| ... | @@ -2844,6 +2847,7 @@ enum IrInstGenId { | ... | @@ -2844,6 +2847,7 @@ enum IrInstGenId { |
| 2844 | IrInstGenIdAlloca, | 2847 | IrInstGenIdAlloca, |
| 2845 | IrInstGenIdConst, | 2848 | IrInstGenIdConst, |
| 2846 | IrInstGenIdWasmMemorySize, | 2849 | IrInstGenIdWasmMemorySize, |
| 2850 | IrInstGenIdWasmMemoryGrow, | ||
| 2847 | }; | 2851 | }; |
| 2848 | 2852 | ||
| 2849 | // Common fields between IrInstSrc and IrInstGen. This allows future passes | 2853 | // Common fields between IrInstSrc and IrInstGen. This allows future passes |
| ... | @@ -3732,11 +3736,23 @@ struct IrInstGenMemcpy { | ... | @@ -3732,11 +3736,23 @@ struct IrInstGenMemcpy { |
| 3732 | }; | 3736 | }; |
| 3733 | 3737 | ||
| 3734 | struct IrInstSrcWasmMemorySize { | 3738 | struct IrInstSrcWasmMemorySize { |
| 3735 | IrInstSrc base; | 3739 | IrInstSrc base; |
| 3736 | }; | 3740 | }; |
| 3737 | 3741 | ||
| 3738 | struct IrInstGenWasmMemorySize { | 3742 | struct IrInstGenWasmMemorySize { |
| 3739 | IrInstGen base; | 3743 | IrInstGen base; |
| 3744 | }; | ||
| 3745 | |||
| 3746 | struct IrInstSrcWasmMemoryGrow { | ||
| 3747 | IrInstSrc base; | ||
| 3748 | |||
| 3749 | IrInstSrc *delta; | ||
| 3750 | }; | ||
| 3751 | |||
| 3752 | struct IrInstGenWasmMemoryGrow { | ||
| 3753 | IrInstGen base; | ||
| 3754 | |||
| 3755 | IrInstGen *delta; | ||
| 3740 | }; | 3756 | }; |
| 3741 | 3757 | ||
| 3742 | struct IrInstSrcSlice { | 3758 | struct IrInstSrcSlice { |
src/codegen.cpp+38-1| ... | @@ -1047,8 +1047,9 @@ static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstGen *source_instr | ... | @@ -1047,8 +1047,9 @@ static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstGen *source_instr |
| 1047 | 1047 | ||
| 1048 | static LLVMValueRef gen_wasm_memory_size(CodeGen *g) { | 1048 | static LLVMValueRef gen_wasm_memory_size(CodeGen *g) { |
| 1049 | if (g->wasm_memory_size) | 1049 | if (g->wasm_memory_size) |
| 1050 | return g->wasm_memory_size; | 1050 | return g->wasm_memory_size; |
| 1051 | 1051 | ||
| 1052 | // TODO adjust for wasm64 as well | ||
| 1052 | // declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly | 1053 | // declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly |
| 1053 | LLVMTypeRef param_type = LLVMInt32Type(); | 1054 | LLVMTypeRef param_type = LLVMInt32Type(); |
| 1054 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), &param_type, 1, false); | 1055 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), &param_type, 1, false); |
| ... | @@ -1058,6 +1059,23 @@ static LLVMValueRef gen_wasm_memory_size(CodeGen *g) { | ... | @@ -1058,6 +1059,23 @@ static LLVMValueRef gen_wasm_memory_size(CodeGen *g) { |
| 1058 | return g->wasm_memory_size; | 1059 | return g->wasm_memory_size; |
| 1059 | } | 1060 | } |
| 1060 | 1061 | ||
| 1062 | static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) { | ||
| 1063 | if (g->wasm_memory_grow) | ||
| 1064 | return g->wasm_memory_grow; | ||
| 1065 | |||
| 1066 | // TODO adjust for wasm64 as well | ||
| 1067 | // declare i32 @llvm.wasm.memory.grow.i32(i32, i32) nounwind | ||
| 1068 | LLVMTypeRef param_types[] = { | ||
| 1069 | LLVMInt32Type(), | ||
| 1070 | LLVMInt32Type(), | ||
| 1071 | }; | ||
| 1072 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, false); | ||
| 1073 | g->wasm_memory_grow = LLVMAddFunction(g->module, "llvm.wasm.memory.grow.i32", fn_type); | ||
| 1074 | assert(LLVMGetIntrinsicID(g->wasm_memory_grow)); | ||
| 1075 | |||
| 1076 | return g->wasm_memory_grow; | ||
| 1077 | } | ||
| 1078 | |||
| 1061 | static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { | 1079 | static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { |
| 1062 | if (g->stacksave_fn_val) | 1080 | if (g->stacksave_fn_val) |
| 1063 | return g->stacksave_fn_val; | 1081 | return g->stacksave_fn_val; |
| ... | @@ -5607,11 +5625,27 @@ static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *exec | ... | @@ -5607,11 +5625,27 @@ static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *exec |
| 5607 | // | 5625 | // |
| 5608 | // More info: | 5626 | // More info: |
| 5609 | // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#current-linear-memory-size | 5627 | // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#current-linear-memory-size |
| 5628 | // TODO adjust for wasm64 | ||
| 5610 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); | 5629 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); |
| 5611 | LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &zero, 1, ""); | 5630 | LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &zero, 1, ""); |
| 5612 | return val; | 5631 | return val; |
| 5613 | } | 5632 | } |
| 5614 | 5633 | ||
| 5634 | static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemoryGrow *instruction) { | ||
| 5635 | // When Wasm lands multi-memory support, we can relax this to permit the user specify | ||
| 5636 | // memory index to inquire about. For now, we pass in the recommended default of index 0. | ||
| 5637 | // | ||
| 5638 | // More info: | ||
| 5639 | // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#grow-linear-memory-size | ||
| 5640 | // TODO adjust for wasm64 | ||
| 5641 | LLVMValueRef params[] = { | ||
| 5642 | LLVMConstNull(g->builtin_types.entry_i32->llvm_type), | ||
| 5643 | ir_llvm_value(g, instruction->delta), | ||
| 5644 | }; | ||
| 5645 | LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_grow(g), params, 2, ""); | ||
| 5646 | return val; | ||
| 5647 | } | ||
| 5648 | |||
| 5615 | static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) { | 5649 | static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) { |
| 5616 | Error err; | 5650 | Error err; |
| 5617 | 5651 | ||
| ... | @@ -6824,6 +6858,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6824,6 +6858,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl |
| 6824 | return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction); | 6858 | return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction); |
| 6825 | case IrInstGenIdWasmMemorySize: | 6859 | case IrInstGenIdWasmMemorySize: |
| 6826 | return ir_render_wasm_memory_size(g, executable, (IrInstGenWasmMemorySize *) instruction); | 6860 | return ir_render_wasm_memory_size(g, executable, (IrInstGenWasmMemorySize *) instruction); |
| 6861 | case IrInstGenIdWasmMemoryGrow: | ||
| 6862 | return ir_render_wasm_memory_grow(g, executable, (IrInstGenWasmMemoryGrow *) instruction); | ||
| 6827 | } | 6863 | } |
| 6828 | zig_unreachable(); | 6864 | zig_unreachable(); |
| 6829 | } | 6865 | } |
| ... | @@ -8687,6 +8723,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -8687,6 +8723,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 8687 | create_builtin_fn(g, BuiltinFnIdCall, "call", 3); | 8723 | create_builtin_fn(g, BuiltinFnIdCall, "call", 3); |
| 8688 | create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1); | 8724 | create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1); |
| 8689 | create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 0); | 8725 | create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 0); |
| 8726 | create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 1); | ||
| 8690 | } | 8727 | } |
| 8691 | 8728 | ||
| 8692 | static const char *bool_to_str(bool b) { | 8729 | static const char *bool_to_str(bool b) { |
src/ir.cpp+88-19| ... | @@ -558,6 +558,8 @@ static void destroy_instruction_src(IrInstSrc *inst) { | ... | @@ -558,6 +558,8 @@ static void destroy_instruction_src(IrInstSrc *inst) { |
| 558 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst)); | 558 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst)); |
| 559 | case IrInstSrcIdWasmMemorySize: | 559 | case IrInstSrcIdWasmMemorySize: |
| 560 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst)); | 560 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst)); |
| 561 | case IrInstSrcIdWasmMemoryGrow: | ||
| 562 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst)); | ||
| 561 | } | 563 | } |
| 562 | zig_unreachable(); | 564 | zig_unreachable(); |
| 563 | } | 565 | } |
| ... | @@ -740,6 +742,8 @@ void destroy_instruction_gen(IrInstGen *inst) { | ... | @@ -740,6 +742,8 @@ void destroy_instruction_gen(IrInstGen *inst) { |
| 740 | return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegationWrapping *>(inst)); | 742 | return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegationWrapping *>(inst)); |
| 741 | case IrInstGenIdWasmMemorySize: | 743 | case IrInstGenIdWasmMemorySize: |
| 742 | return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemorySize *>(inst)); | 744 | return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemorySize *>(inst)); |
| 745 | case IrInstGenIdWasmMemoryGrow: | ||
| 746 | return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemoryGrow *>(inst)); | ||
| 743 | } | 747 | } |
| 744 | zig_unreachable(); | 748 | zig_unreachable(); |
| 745 | } | 749 | } |
| ... | @@ -1338,10 +1342,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { | ... | @@ -1338,10 +1342,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { |
| 1338 | return IrInstSrcIdBoolNot; | 1342 | return IrInstSrcIdBoolNot; |
| 1339 | } | 1343 | } |
| 1340 | 1344 | ||
| 1341 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) { | ||
| 1342 | return IrInstSrcIdWasmMemorySize; | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { | 1345 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { |
| 1346 | return IrInstSrcIdMemset; | 1346 | return IrInstSrcIdMemset; |
| 1347 | } | 1347 | } |
| ... | @@ -1618,6 +1618,14 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { | ... | @@ -1618,6 +1618,14 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { |
| 1618 | return IrInstSrcIdSpillEnd; | 1618 | return IrInstSrcIdSpillEnd; |
| 1619 | } | 1619 | } |
| 1620 | 1620 | ||
| 1621 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) { | ||
| 1622 | return IrInstSrcIdWasmMemorySize; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) { | ||
| 1626 | return IrInstSrcIdWasmMemoryGrow; | ||
| 1627 | } | ||
| 1628 | |||
| 1621 | 1629 | ||
| 1622 | static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) { | 1630 | static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) { |
| 1623 | return IrInstGenIdDeclVar; | 1631 | return IrInstGenIdDeclVar; |
| ... | @@ -1967,6 +1975,10 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemorySize *) { | ... | @@ -1967,6 +1975,10 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemorySize *) { |
| 1967 | return IrInstGenIdWasmMemorySize; | 1975 | return IrInstGenIdWasmMemorySize; |
| 1968 | } | 1976 | } |
| 1969 | 1977 | ||
| 1978 | static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemoryGrow *) { | ||
| 1979 | return IrInstGenIdWasmMemoryGrow; | ||
| 1980 | } | ||
| 1981 | |||
| 1970 | template<typename T> | 1982 | template<typename T> |
| 1971 | static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | 1983 | static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { |
| 1972 | T *special_instruction = heap::c_allocator.create<T>(); | 1984 | T *special_instruction = heap::c_allocator.create<T>(); |
| ... | @@ -3654,20 +3666,6 @@ static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, Ir | ... | @@ -3654,20 +3666,6 @@ static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, Ir |
| 3654 | return &instruction->base; | 3666 | return &instruction->base; |
| 3655 | } | 3667 | } |
| 3656 | 3668 | ||
| 3657 | static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 3658 | IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(irb, scope, source_node); | ||
| 3659 | |||
| 3660 | return &instruction->base; | ||
| 3661 | } | ||
| 3662 | |||
| 3663 | static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 3664 | IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb, | ||
| 3665 | source_instr->scope, source_instr->source_node); | ||
| 3666 | instruction->base.value->type = ira->codegen->builtin_types.entry_i32; | ||
| 3667 | |||
| 3668 | return &instruction->base; | ||
| 3669 | } | ||
| 3670 | |||
| 3671 | static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 3669 | static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, |
| 3672 | IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) | 3670 | IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) |
| 3673 | { | 3671 | { |
| ... | @@ -4987,6 +4985,41 @@ static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_in | ... | @@ -4987,6 +4985,41 @@ static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_in |
| 4987 | return &instruction->base; | 4985 | return &instruction->base; |
| 4988 | } | 4986 | } |
| 4989 | 4987 | ||
| 4988 | static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 4989 | IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(irb, scope, source_node); | ||
| 4990 | |||
| 4991 | return &instruction->base; | ||
| 4992 | } | ||
| 4993 | |||
| 4994 | static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 4995 | IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb, | ||
| 4996 | source_instr->scope, source_instr->source_node); | ||
| 4997 | instruction->base.value->type = ira->codegen->builtin_types.entry_i32; | ||
| 4998 | |||
| 4999 | return &instruction->base; | ||
| 5000 | } | ||
| 5001 | |||
| 5002 | static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *delta) { | ||
| 5003 | IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction<IrInstSrcWasmMemoryGrow>(irb, scope, source_node); | ||
| 5004 | instruction->delta = delta; | ||
| 5005 | |||
| 5006 | ir_ref_instruction(delta, irb->current_basic_block); | ||
| 5007 | |||
| 5008 | return &instruction->base; | ||
| 5009 | } | ||
| 5010 | |||
| 5011 | static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *delta) { | ||
| 5012 | IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen<IrInstGenWasmMemoryGrow>(&ira->new_irb, | ||
| 5013 | source_instr->scope, source_instr->source_node); | ||
| 5014 | instruction->base.value->type = ira->codegen->builtin_types.entry_i32; | ||
| 5015 | instruction->delta = delta; | ||
| 5016 | |||
| 5017 | ir_ref_inst_gen(delta); | ||
| 5018 | |||
| 5019 | return &instruction->base; | ||
| 5020 | } | ||
| 5021 | |||
| 5022 | |||
| 4990 | static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 5023 | static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 4991 | results[ReturnKindUnconditional] = 0; | 5024 | results[ReturnKindUnconditional] = 0; |
| 4992 | results[ReturnKindError] = 0; | 5025 | results[ReturnKindError] = 0; |
| ... | @@ -6785,6 +6818,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod | ... | @@ -6785,6 +6818,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod |
| 6785 | IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node); | 6818 | IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node); |
| 6786 | return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); | 6819 | return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); |
| 6787 | } | 6820 | } |
| 6821 | case BuiltinFnIdWasmMemoryGrow: | ||
| 6822 | { | ||
| 6823 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6824 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6825 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6826 | return arg0_value; | ||
| 6827 | |||
| 6828 | IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value); | ||
| 6829 | return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc); | ||
| 6830 | } | ||
| 6788 | case BuiltinFnIdField: | 6831 | case BuiltinFnIdField: |
| 6789 | { | 6832 | { |
| 6790 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | 6833 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | @@ -27683,15 +27726,37 @@ static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasF | ... | @@ -27683,15 +27726,37 @@ static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasF |
| 27683 | } | 27726 | } |
| 27684 | 27727 | ||
| 27685 | static IrInstGen *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, IrInstSrcWasmMemorySize *instruction) { | 27728 | static IrInstGen *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, IrInstSrcWasmMemorySize *instruction) { |
| 27729 | // TODO generate compile error for target_arch different than 32bit | ||
| 27686 | if (!target_is_wasm(ira->codegen->zig_target)) { | 27730 | if (!target_is_wasm(ira->codegen->zig_target)) { |
| 27687 | ir_add_error_node(ira, instruction->base.base.source_node, | 27731 | ir_add_error_node(ira, instruction->base.base.source_node, |
| 27688 | buf_sprintf("@wasmMemorySize is a wasm feature only")); | 27732 | buf_sprintf("@wasmMemorySize is a wasm32 feature only")); |
| 27689 | return ira->codegen->invalid_inst_gen; | 27733 | return ira->codegen->invalid_inst_gen; |
| 27690 | } | 27734 | } |
| 27691 | 27735 | ||
| 27692 | return ir_build_wasm_memory_size_gen(ira, &instruction->base.base); | 27736 | return ir_build_wasm_memory_size_gen(ira, &instruction->base.base); |
| 27693 | } | 27737 | } |
| 27694 | 27738 | ||
| 27739 | static IrInstGen *ir_analyze_instruction_wasm_memory_grow(IrAnalyze *ira, IrInstSrcWasmMemoryGrow *instruction) { | ||
| 27740 | // TODO generate compile error for target_arch different than 32bit | ||
| 27741 | if (!target_is_wasm(ira->codegen->zig_target)) { | ||
| 27742 | ir_add_error_node(ira, instruction->base.base.source_node, | ||
| 27743 | buf_sprintf("@wasmMemoryGrow is a wasm32 feature only")); | ||
| 27744 | return ira->codegen->invalid_inst_gen; | ||
| 27745 | } | ||
| 27746 | |||
| 27747 | IrInstGen *delta = instruction->delta->child; | ||
| 27748 | if (type_is_invalid(delta->value->type)) | ||
| 27749 | return ira->codegen->invalid_inst_gen; | ||
| 27750 | |||
| 27751 | ZigType *i32_type = ira->codegen->builtin_types.entry_i32; | ||
| 27752 | |||
| 27753 | IrInstGen *casted_delta = ir_implicit_cast(ira, delta, i32_type); | ||
| 27754 | if (type_is_invalid(casted_delta->value->type)) | ||
| 27755 | return ira->codegen->invalid_inst_gen; | ||
| 27756 | |||
| 27757 | return ir_build_wasm_memory_grow_gen(ira, &instruction->base.base, casted_delta); | ||
| 27758 | } | ||
| 27759 | |||
| 27695 | static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) { | 27760 | static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) { |
| 27696 | return ir_build_breakpoint_gen(ira, &instruction->base.base); | 27761 | return ir_build_breakpoint_gen(ira, &instruction->base.base); |
| 27697 | } | 27762 | } |
| ... | @@ -30935,6 +31000,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc | ... | @@ -30935,6 +31000,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc |
| 30935 | return ir_analyze_instruction_spill_end(ira, (IrInstSrcSpillEnd *)instruction); | 31000 | return ir_analyze_instruction_spill_end(ira, (IrInstSrcSpillEnd *)instruction); |
| 30936 | case IrInstSrcIdWasmMemorySize: | 31001 | case IrInstSrcIdWasmMemorySize: |
| 30937 | return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction); | 31002 | return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction); |
| 31003 | case IrInstSrcIdWasmMemoryGrow: | ||
| 31004 | return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction); | ||
| 30938 | } | 31005 | } |
| 30939 | zig_unreachable(); | 31006 | zig_unreachable(); |
| 30940 | } | 31007 | } |
| ... | @@ -31111,6 +31178,7 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { | ... | @@ -31111,6 +31178,7 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { |
| 31111 | case IrInstGenIdResume: | 31178 | case IrInstGenIdResume: |
| 31112 | case IrInstGenIdAwait: | 31179 | case IrInstGenIdAwait: |
| 31113 | case IrInstGenIdSpillBegin: | 31180 | case IrInstGenIdSpillBegin: |
| 31181 | case IrInstGenIdWasmMemoryGrow: | ||
| 31114 | return true; | 31182 | return true; |
| 31115 | 31183 | ||
| 31116 | case IrInstGenIdPhi: | 31184 | case IrInstGenIdPhi: |
| ... | @@ -31243,6 +31311,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { | ... | @@ -31243,6 +31311,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { |
| 31243 | case IrInstSrcIdResume: | 31311 | case IrInstSrcIdResume: |
| 31244 | case IrInstSrcIdAwait: | 31312 | case IrInstSrcIdAwait: |
| 31245 | case IrInstSrcIdSpillBegin: | 31313 | case IrInstSrcIdSpillBegin: |
| 31314 | case IrInstSrcIdWasmMemoryGrow: | ||
| 31246 | return true; | 31315 | return true; |
| 31247 | 31316 | ||
| 31248 | case IrInstSrcIdPhi: | 31317 | case IrInstSrcIdPhi: |
src/ir_print.cpp+22| ... | @@ -323,6 +323,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { | ... | @@ -323,6 +323,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { |
| 323 | return "SrcSpillEnd"; | 323 | return "SrcSpillEnd"; |
| 324 | case IrInstSrcIdWasmMemorySize: | 324 | case IrInstSrcIdWasmMemorySize: |
| 325 | return "SrcWasmMemorySize"; | 325 | return "SrcWasmMemorySize"; |
| 326 | case IrInstSrcIdWasmMemoryGrow: | ||
| 327 | return "SrcWasmMemoryGrow"; | ||
| 326 | } | 328 | } |
| 327 | zig_unreachable(); | 329 | zig_unreachable(); |
| 328 | } | 330 | } |
| ... | @@ -505,6 +507,8 @@ const char* ir_inst_gen_type_str(IrInstGenId id) { | ... | @@ -505,6 +507,8 @@ const char* ir_inst_gen_type_str(IrInstGenId id) { |
| 505 | return "GenNegationWrapping"; | 507 | return "GenNegationWrapping"; |
| 506 | case IrInstGenIdWasmMemorySize: | 508 | case IrInstGenIdWasmMemorySize: |
| 507 | return "GenWasmMemorySize"; | 509 | return "GenWasmMemorySize"; |
| 510 | case IrInstGenIdWasmMemoryGrow: | ||
| 511 | return "GenWasmMemoryGrow"; | ||
| 508 | } | 512 | } |
| 509 | zig_unreachable(); | 513 | zig_unreachable(); |
| 510 | } | 514 | } |
| ... | @@ -1720,6 +1724,18 @@ static void ir_print_wasm_memory_size(IrPrintGen *irp, IrInstGenWasmMemorySize * | ... | @@ -1720,6 +1724,18 @@ static void ir_print_wasm_memory_size(IrPrintGen *irp, IrInstGenWasmMemorySize * |
| 1720 | fprintf(irp->f, "@wasmMemorySize()"); | 1724 | fprintf(irp->f, "@wasmMemorySize()"); |
| 1721 | } | 1725 | } |
| 1722 | 1726 | ||
| 1727 | static void ir_print_wasm_memory_grow(IrPrintSrc *irp, IrInstSrcWasmMemoryGrow *instruction) { | ||
| 1728 | fprintf(irp->f, "@wasmMemoryGrow("); | ||
| 1729 | ir_print_other_inst_src(irp, instruction->delta); | ||
| 1730 | fprintf(irp->f, ")"); | ||
| 1731 | } | ||
| 1732 | |||
| 1733 | static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *instruction) { | ||
| 1734 | fprintf(irp->f, "@wasmMemoryGrow("); | ||
| 1735 | ir_print_other_inst_gen(irp, instruction->delta); | ||
| 1736 | fprintf(irp->f, ")"); | ||
| 1737 | } | ||
| 1738 | |||
| 1723 | static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) { | 1739 | static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) { |
| 1724 | fprintf(irp->f, "@memset("); | 1740 | fprintf(irp->f, "@memset("); |
| 1725 | ir_print_other_inst_src(irp, instruction->dest_ptr); | 1741 | ir_print_other_inst_src(irp, instruction->dest_ptr); |
| ... | @@ -2967,6 +2983,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai | ... | @@ -2967,6 +2983,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai |
| 2967 | case IrInstSrcIdWasmMemorySize: | 2983 | case IrInstSrcIdWasmMemorySize: |
| 2968 | ir_print_wasm_memory_size(irp, (IrInstSrcWasmMemorySize *)instruction); | 2984 | ir_print_wasm_memory_size(irp, (IrInstSrcWasmMemorySize *)instruction); |
| 2969 | break; | 2985 | break; |
| 2986 | case IrInstSrcIdWasmMemoryGrow: | ||
| 2987 | ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction); | ||
| 2988 | break; | ||
| 2970 | } | 2989 | } |
| 2971 | fprintf(irp->f, "\n"); | 2990 | fprintf(irp->f, "\n"); |
| 2972 | } | 2991 | } |
| ... | @@ -3237,6 +3256,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai | ... | @@ -3237,6 +3256,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai |
| 3237 | case IrInstGenIdWasmMemorySize: | 3256 | case IrInstGenIdWasmMemorySize: |
| 3238 | ir_print_wasm_memory_size(irp, (IrInstGenWasmMemorySize *)instruction); | 3257 | ir_print_wasm_memory_size(irp, (IrInstGenWasmMemorySize *)instruction); |
| 3239 | break; | 3258 | break; |
| 3259 | case IrInstGenIdWasmMemoryGrow: | ||
| 3260 | ir_print_wasm_memory_grow(irp, (IrInstGenWasmMemoryGrow *)instruction); | ||
| 3261 | break; | ||
| 3240 | } | 3262 | } |
| 3241 | fprintf(irp->f, "\n"); | 3263 | fprintf(irp->f, "\n"); |
| 3242 | } | 3264 | } |