authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-09 00:22:43-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-09 00:22:43-04:00
log4302f276ed3083b4f261f9e50a9546c9877d2785
treec857775bf067e7838764125d68210376491058c5
parent12051b02f1f455b85d5a519dd1747a67d4bb68d0
parent42c95a64d67ec6fc2839fad36ef50bacc7545258

Merge branch 'kubkon-wasm-instrinsics'

closes #5507

9 files changed, 361 insertions(+), 6 deletions(-)

doc/langref.html.in+43
......@@ -7643,6 +7643,49 @@ mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre>
76437643mem.set(u8, dest, c);{#endsyntax#}</pre>
76447644 {#header_close#}
76457645
7646 {#header_open|@wasmMemorySize#}
7647 <pre>{#syntax#}@wasmMemorySize(index: u32) u32{#endsyntax#}</pre>
7648 <p>
7649 This function returns the size of the Wasm memory identified by {#syntax#}index{#endsyntax#} as
7650 an unsigned value in units of Wasm pages. Note that each Wasm page is 64KB in size.
7651 </p>
7652 <p>
7653 This function is a low level intrinsic with no safety mechanisms usually useful for allocator
7654 designers targeting Wasm. So unless you are writing a new allocator from scratch, you should use
7655 something like {#syntax#}@import("std").heap.WasmPageAllocator{#endsyntax#}.
7656 </p>
7657 {#see_also|@wasmMemoryGrow#}
7658 {#header_close#}
7659
7660 {#header_open|@wasmMemoryGrow#}
7661 <pre>{#syntax#}@wasmMemoryGrow(index: u32, delta: u32) i32{#endsyntax#}</pre>
7662 <p>
7663 This function increases the size of the Wasm memory identified by {#syntax#}index{#endsyntax#} by
7664 {#syntax#}delta{#endsyntax#} in units of unsigned number of Wasm pages. Note that each Wasm page
7665 is 64KB in size. On success, returns previous memory size; on failure, if the allocation fails,
7666 returns -1.
7667 </p>
7668 <p>
7669 This function is a low level intrinsic with no safety mechanisms usually useful for allocator
7670 designers targeting Wasm. So unless you are writing a new allocator from scratch, you should use
7671 something like {#syntax#}@import("std").heap.WasmPageAllocator{#endsyntax#}.
7672 </p>
7673 {#code_begin|test#}
7674const std = @import("std");
7675const builtin = @import("builtin");
7676const assert = std.debug.assert;
7677
7678test "@wasmMemoryGrow" {
7679 if (builtin.arch != .wasm32) return error.SkipZigTest;
7680
7681 var prev = @wasmMemorySize(0);
7682 assert(prev == @wasmMemoryGrow(0, 1));
7683 assert(prev + 1 == @wasmMemorySize(0));
7684}
7685 {#code_end#}
7686 {#see_also|@wasmMemorySize#}
7687 {#header_close#}
7688
76467689 {#header_open|@mod#}
76477690 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
76487691 <p>
lib/std/heap.zig+1-6
......@@ -250,11 +250,6 @@ const PageAllocator = struct {
250250 }
251251};
252252
253// TODO Exposed LLVM intrinsics is a bug
254// See: https://github.com/ziglang/zig/issues/2291
255extern fn @"llvm.wasm.memory.size.i32"(u32) u32;
256extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32;
257
258253const WasmPageAllocator = struct {
259254 comptime {
260255 if (!std.Target.current.isWasm()) {
......@@ -357,7 +352,7 @@ const WasmPageAllocator = struct {
357352 return idx + extendedOffset();
358353 }
359354
360 const prev_page_count = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, page_count));
355 const prev_page_count = @wasmMemoryGrow(0, @intCast(u32, page_count));
361356 if (prev_page_count <= 0) {
362357 return error.OutOfMemory;
363358 }
src/all_types.hpp+34
......@@ -1825,6 +1825,8 @@ enum BuiltinFnId {
18251825 BuiltinFnIdAs,
18261826 BuiltinFnIdCall,
18271827 BuiltinFnIdBitSizeof,
1828 BuiltinFnIdWasmMemorySize,
1829 BuiltinFnIdWasmMemoryGrow,
18281830};
18291831
18301832struct BuiltinFnEntry {
......@@ -2075,6 +2077,8 @@ struct CodeGen {
20752077 LLVMValueRef err_name_table;
20762078 LLVMValueRef safety_crash_err_fn;
20772079 LLVMValueRef return_err_fn;
2080 LLVMValueRef wasm_memory_size;
2081 LLVMValueRef wasm_memory_grow;
20782082 LLVMTypeRef anyframe_fn_type;
20792083
20802084 // reminder: hash tables must be initialized before use
......@@ -2748,6 +2752,8 @@ enum IrInstSrcId {
27482752 IrInstSrcIdResume,
27492753 IrInstSrcIdSpillBegin,
27502754 IrInstSrcIdSpillEnd,
2755 IrInstSrcIdWasmMemorySize,
2756 IrInstSrcIdWasmMemoryGrow,
27512757};
27522758
27532759// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
......@@ -2840,6 +2846,8 @@ enum IrInstGenId {
28402846 IrInstGenIdVectorExtractElem,
28412847 IrInstGenIdAlloca,
28422848 IrInstGenIdConst,
2849 IrInstGenIdWasmMemorySize,
2850 IrInstGenIdWasmMemoryGrow,
28432851};
28442852
28452853// Common fields between IrInstSrc and IrInstGen. This allows future passes
......@@ -3727,6 +3735,32 @@ struct IrInstGenMemcpy {
37273735 IrInstGen *count;
37283736};
37293737
3738struct IrInstSrcWasmMemorySize {
3739 IrInstSrc base;
3740
3741 IrInstSrc *index;
3742};
3743
3744struct IrInstGenWasmMemorySize {
3745 IrInstGen base;
3746
3747 IrInstGen *index;
3748};
3749
3750struct IrInstSrcWasmMemoryGrow {
3751 IrInstSrc base;
3752
3753 IrInstSrc *index;
3754 IrInstSrc *delta;
3755};
3756
3757struct IrInstGenWasmMemoryGrow {
3758 IrInstGen base;
3759
3760 IrInstGen *index;
3761 IrInstGen *delta;
3762};
3763
37303764struct IrInstSrcSlice {
37313765 IrInstSrc base;
37323766
src/codegen.cpp+54
......@@ -1045,6 +1045,37 @@ static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstGen *source_instr
10451045 return gen_assertion_scope(g, msg_id, source_instruction->base.scope);
10461046}
10471047
1048static LLVMValueRef gen_wasm_memory_size(CodeGen *g) {
1049 if (g->wasm_memory_size)
1050 return g->wasm_memory_size;
1051
1052 // TODO adjust for wasm64 as well
1053 // declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly
1054 LLVMTypeRef param_type = LLVMInt32Type();
1055 LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), &param_type, 1, false);
1056 g->wasm_memory_size = LLVMAddFunction(g->module, "llvm.wasm.memory.size.i32", fn_type);
1057 assert(LLVMGetIntrinsicID(g->wasm_memory_size));
1058
1059 return g->wasm_memory_size;
1060}
1061
1062static 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
10481079static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
10491080 if (g->stacksave_fn_val)
10501081 return g->stacksave_fn_val;
......@@ -5588,6 +5619,23 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, Ir
55885619 return nullptr;
55895620}
55905621
5622static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemorySize *instruction) {
5623 // TODO adjust for wasm64
5624 LLVMValueRef param = ir_llvm_value(g, instruction->index);
5625 LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &param, 1, "");
5626 return val;
5627}
5628
5629static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemoryGrow *instruction) {
5630 // TODO adjust for wasm64
5631 LLVMValueRef params[] = {
5632 ir_llvm_value(g, instruction->index),
5633 ir_llvm_value(g, instruction->delta),
5634 };
5635 LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_grow(g), params, 2, "");
5636 return val;
5637}
5638
55915639static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) {
55925640 Error err;
55935641
......@@ -6798,6 +6846,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl
67986846 return ir_render_splat(g, executable, (IrInstGenSplat *) instruction);
67996847 case IrInstGenIdVectorExtractElem:
68006848 return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction);
6849 case IrInstGenIdWasmMemorySize:
6850 return ir_render_wasm_memory_size(g, executable, (IrInstGenWasmMemorySize *) instruction);
6851 case IrInstGenIdWasmMemoryGrow:
6852 return ir_render_wasm_memory_grow(g, executable, (IrInstGenWasmMemoryGrow *) instruction);
68016853 }
68026854 zig_unreachable();
68036855}
......@@ -8660,6 +8712,8 @@ static void define_builtin_fns(CodeGen *g) {
86608712 create_builtin_fn(g, BuiltinFnIdAs, "as", 2);
86618713 create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
86628714 create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
8715 create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1);
8716 create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
86638717}
86648718
86658719static const char *bool_to_str(bool b) {
src/ir.cpp+152
......@@ -556,6 +556,10 @@ static void destroy_instruction_src(IrInstSrc *inst) {
556556 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSpillEnd *>(inst));
557557 case IrInstSrcIdCallArgs:
558558 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst));
559 case IrInstSrcIdWasmMemorySize:
560 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst));
561 case IrInstSrcIdWasmMemoryGrow:
562 return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst));
559563 }
560564 zig_unreachable();
561565}
......@@ -736,6 +740,10 @@ void destroy_instruction_gen(IrInstGen *inst) {
736740 return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegation *>(inst));
737741 case IrInstGenIdNegationWrapping:
738742 return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegationWrapping *>(inst));
743 case IrInstGenIdWasmMemorySize:
744 return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemorySize *>(inst));
745 case IrInstGenIdWasmMemoryGrow:
746 return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemoryGrow *>(inst));
739747 }
740748 zig_unreachable();
741749}
......@@ -1610,6 +1618,14 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) {
16101618 return IrInstSrcIdSpillEnd;
16111619}
16121620
1621static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) {
1622 return IrInstSrcIdWasmMemorySize;
1623}
1624
1625static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) {
1626 return IrInstSrcIdWasmMemoryGrow;
1627}
1628
16131629
16141630static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
16151631 return IrInstGenIdDeclVar;
......@@ -1955,6 +1971,14 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenConst *) {
19551971 return IrInstGenIdConst;
19561972}
19571973
1974static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemorySize *) {
1975 return IrInstGenIdWasmMemorySize;
1976}
1977
1978static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemoryGrow *) {
1979 return IrInstGenIdWasmMemoryGrow;
1980}
1981
19581982template<typename T>
19591983static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
19601984 T *special_instruction = heap::c_allocator.create<T>();
......@@ -4961,6 +4985,51 @@ static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_in
49614985 return &instruction->base;
49624986}
49634987
4988static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index) {
4989 IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(irb, scope, source_node);
4990 instruction->index = index;
4991
4992 ir_ref_instruction(index, irb->current_basic_block);
4993
4994 return &instruction->base;
4995}
4996
4997static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index) {
4998 IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb,
4999 source_instr->scope, source_instr->source_node);
5000 instruction->base.value->type = ira->codegen->builtin_types.entry_u32;
5001 instruction->index = index;
5002
5003 ir_ref_inst_gen(index);
5004
5005 return &instruction->base;
5006}
5007
5008static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) {
5009 IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction<IrInstSrcWasmMemoryGrow>(irb, scope, source_node);
5010 instruction->index = index;
5011 instruction->delta = delta;
5012
5013 ir_ref_instruction(index, irb->current_basic_block);
5014 ir_ref_instruction(delta, irb->current_basic_block);
5015
5016 return &instruction->base;
5017}
5018
5019static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index, IrInstGen *delta) {
5020 IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen<IrInstGenWasmMemoryGrow>(&ira->new_irb,
5021 source_instr->scope, source_instr->source_node);
5022 instruction->base.value->type = ira->codegen->builtin_types.entry_i32;
5023 instruction->index = index;
5024 instruction->delta = delta;
5025
5026 ir_ref_inst_gen(index);
5027 ir_ref_inst_gen(delta);
5028
5029 return &instruction->base;
5030}
5031
5032
49645033static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
49655034 results[ReturnKindUnconditional] = 0;
49665035 results[ReturnKindError] = 0;
......@@ -6754,6 +6823,31 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
67546823 IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value);
67556824 return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc);
67566825 }
6826 case BuiltinFnIdWasmMemorySize:
6827 {
6828 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
6829 IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
6830 if (arg0_value == irb->codegen->invalid_inst_src)
6831 return arg0_value;
6832
6833 IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node, arg0_value);
6834 return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc);
6835 }
6836 case BuiltinFnIdWasmMemoryGrow:
6837 {
6838 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
6839 IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
6840 if (arg0_value == irb->codegen->invalid_inst_src)
6841 return arg0_value;
6842
6843 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
6844 IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope);
6845 if (arg1_value == irb->codegen->invalid_inst_src)
6846 return arg1_value;
6847
6848 IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value, arg1_value);
6849 return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc);
6850 }
67576851 case BuiltinFnIdField:
67586852 {
67596853 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -27651,6 +27745,56 @@ static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasF
2765127745 return ir_const_bool(ira, &instruction->base.base, result);
2765227746}
2765327747
27748static IrInstGen *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, IrInstSrcWasmMemorySize *instruction) {
27749 // TODO generate compile error for target_arch different than 32bit
27750 if (!target_is_wasm(ira->codegen->zig_target)) {
27751 ir_add_error_node(ira, instruction->base.base.source_node,
27752 buf_sprintf("@wasmMemorySize is a wasm32 feature only"));
27753 return ira->codegen->invalid_inst_gen;
27754 }
27755
27756 IrInstGen *index = instruction->index->child;
27757 if (type_is_invalid(index->value->type))
27758 return ira->codegen->invalid_inst_gen;
27759
27760 ZigType *u32 = ira->codegen->builtin_types.entry_u32;
27761
27762 IrInstGen *casted_index = ir_implicit_cast(ira, index, u32);
27763 if (type_is_invalid(casted_index->value->type))
27764 return ira->codegen->invalid_inst_gen;
27765
27766 return ir_build_wasm_memory_size_gen(ira, &instruction->base.base, casted_index);
27767}
27768
27769static IrInstGen *ir_analyze_instruction_wasm_memory_grow(IrAnalyze *ira, IrInstSrcWasmMemoryGrow *instruction) {
27770 // TODO generate compile error for target_arch different than 32bit
27771 if (!target_is_wasm(ira->codegen->zig_target)) {
27772 ir_add_error_node(ira, instruction->base.base.source_node,
27773 buf_sprintf("@wasmMemoryGrow is a wasm32 feature only"));
27774 return ira->codegen->invalid_inst_gen;
27775 }
27776
27777 IrInstGen *index = instruction->index->child;
27778 if (type_is_invalid(index->value->type))
27779 return ira->codegen->invalid_inst_gen;
27780
27781 ZigType *u32 = ira->codegen->builtin_types.entry_u32;
27782
27783 IrInstGen *casted_index = ir_implicit_cast(ira, index, u32);
27784 if (type_is_invalid(casted_index->value->type))
27785 return ira->codegen->invalid_inst_gen;
27786
27787 IrInstGen *delta = instruction->delta->child;
27788 if (type_is_invalid(delta->value->type))
27789 return ira->codegen->invalid_inst_gen;
27790
27791 IrInstGen *casted_delta = ir_implicit_cast(ira, delta, u32);
27792 if (type_is_invalid(casted_delta->value->type))
27793 return ira->codegen->invalid_inst_gen;
27794
27795 return ir_build_wasm_memory_grow_gen(ira, &instruction->base.base, casted_index, casted_delta);
27796}
27797
2765427798static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) {
2765527799 return ir_build_breakpoint_gen(ira, &instruction->base.base);
2765627800}
......@@ -30892,6 +31036,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
3089231036 return ir_analyze_instruction_spill_begin(ira, (IrInstSrcSpillBegin *)instruction);
3089331037 case IrInstSrcIdSpillEnd:
3089431038 return ir_analyze_instruction_spill_end(ira, (IrInstSrcSpillEnd *)instruction);
31039 case IrInstSrcIdWasmMemorySize:
31040 return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
31041 case IrInstSrcIdWasmMemoryGrow:
31042 return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction);
3089531043 }
3089631044 zig_unreachable();
3089731045}
......@@ -31068,6 +31216,7 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) {
3106831216 case IrInstGenIdResume:
3106931217 case IrInstGenIdAwait:
3107031218 case IrInstGenIdSpillBegin:
31219 case IrInstGenIdWasmMemoryGrow:
3107131220 return true;
3107231221
3107331222 case IrInstGenIdPhi:
......@@ -31117,6 +31266,7 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) {
3111731266 case IrInstGenIdBinaryNot:
3111831267 case IrInstGenIdNegation:
3111931268 case IrInstGenIdNegationWrapping:
31269 case IrInstGenIdWasmMemorySize:
3112031270 return false;
3112131271
3112231272 case IrInstGenIdAsm:
......@@ -31199,6 +31349,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
3119931349 case IrInstSrcIdResume:
3120031350 case IrInstSrcIdAwait:
3120131351 case IrInstSrcIdSpillBegin:
31352 case IrInstSrcIdWasmMemoryGrow:
3120231353 return true;
3120331354
3120431355 case IrInstSrcIdPhi:
......@@ -31283,6 +31434,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
3128331434 case IrInstSrcIdHasDecl:
3128431435 case IrInstSrcIdAlloca:
3128531436 case IrInstSrcIdSpillEnd:
31437 case IrInstSrcIdWasmMemorySize:
3128631438 return false;
3128731439
3128831440 case IrInstSrcIdAsm:
src/ir_print.cpp+48
......@@ -321,6 +321,10 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
321321 return "SrcSpillBegin";
322322 case IrInstSrcIdSpillEnd:
323323 return "SrcSpillEnd";
324 case IrInstSrcIdWasmMemorySize:
325 return "SrcWasmMemorySize";
326 case IrInstSrcIdWasmMemoryGrow:
327 return "SrcWasmMemoryGrow";
324328 }
325329 zig_unreachable();
326330}
......@@ -501,6 +505,10 @@ const char* ir_inst_gen_type_str(IrInstGenId id) {
501505 return "GenNegation";
502506 case IrInstGenIdNegationWrapping:
503507 return "GenNegationWrapping";
508 case IrInstGenIdWasmMemorySize:
509 return "GenWasmMemorySize";
510 case IrInstGenIdWasmMemoryGrow:
511 return "GenWasmMemoryGrow";
504512 }
505513 zig_unreachable();
506514}
......@@ -1708,6 +1716,34 @@ static void ir_print_bool_not(IrPrintGen *irp, IrInstGenBoolNot *instruction) {
17081716 ir_print_other_inst_gen(irp, instruction->value);
17091717}
17101718
1719static void ir_print_wasm_memory_size(IrPrintSrc *irp, IrInstSrcWasmMemorySize *instruction) {
1720 fprintf(irp->f, "@wasmMemorySize(");
1721 ir_print_other_inst_src(irp, instruction->index);
1722 fprintf(irp->f, ")");
1723}
1724
1725static void ir_print_wasm_memory_size(IrPrintGen *irp, IrInstGenWasmMemorySize *instruction) {
1726 fprintf(irp->f, "@wasmMemorySize(");
1727 ir_print_other_inst_gen(irp, instruction->index);
1728 fprintf(irp->f, ")");
1729}
1730
1731static void ir_print_wasm_memory_grow(IrPrintSrc *irp, IrInstSrcWasmMemoryGrow *instruction) {
1732 fprintf(irp->f, "@wasmMemoryGrow(");
1733 ir_print_other_inst_src(irp, instruction->index);
1734 fprintf(irp->f, ", ");
1735 ir_print_other_inst_src(irp, instruction->delta);
1736 fprintf(irp->f, ")");
1737}
1738
1739static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *instruction) {
1740 fprintf(irp->f, "@wasmMemoryGrow(");
1741 ir_print_other_inst_gen(irp, instruction->index);
1742 fprintf(irp->f, ", ");
1743 ir_print_other_inst_gen(irp, instruction->delta);
1744 fprintf(irp->f, ")");
1745}
1746
17111747static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
17121748 fprintf(irp->f, "@memset(");
17131749 ir_print_other_inst_src(irp, instruction->dest_ptr);
......@@ -2952,6 +2988,12 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
29522988 case IrInstSrcIdClz:
29532989 ir_print_clz(irp, (IrInstSrcClz *)instruction);
29542990 break;
2991 case IrInstSrcIdWasmMemorySize:
2992 ir_print_wasm_memory_size(irp, (IrInstSrcWasmMemorySize *)instruction);
2993 break;
2994 case IrInstSrcIdWasmMemoryGrow:
2995 ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction);
2996 break;
29552997 }
29562998 fprintf(irp->f, "\n");
29572999}
......@@ -3219,6 +3261,12 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai
32193261 case IrInstGenIdNegationWrapping:
32203262 ir_print_negation_wrapping(irp, (IrInstGenNegationWrapping *)instruction);
32213263 break;
3264 case IrInstGenIdWasmMemorySize:
3265 ir_print_wasm_memory_size(irp, (IrInstGenWasmMemorySize *)instruction);
3266 break;
3267 case IrInstGenIdWasmMemoryGrow:
3268 ir_print_wasm_memory_grow(irp, (IrInstGenWasmMemoryGrow *)instruction);
3269 break;
32223270 }
32233271 fprintf(irp->f, "\n");
32243272}
test/compile_errors.zig+18
......@@ -7504,4 +7504,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
75047504 , &[_][]const u8{
75057505 ":3:52: error: slice '[]const u8' cannot have its bytes reinterpreted",
75067506 });
7507
7508 cases.add("wasmMemorySize is a compile error in non-Wasm targets",
7509 \\export fn foo() void {
7510 \\ _ = @wasmMemorySize(0);
7511 \\ return;
7512 \\}
7513 , &[_][]const u8{
7514 "tmp.zig:2:9: error: @wasmMemorySize is a wasm32 feature only",
7515 });
7516
7517 cases.add("wasmMemoryGrow is a compile error in non-Wasm targets",
7518 \\export fn foo() void {
7519 \\ _ = @wasmMemoryGrow(0, 1);
7520 \\ return;
7521 \\}
7522 , &[_][]const u8{
7523 "tmp.zig:2:9: error: @wasmMemoryGrow is a wasm32 feature only",
7524 });
75077525}
test/stage1/behavior.zig+3
......@@ -126,6 +126,9 @@ comptime {
126126 _ = @import("behavior/var_args.zig");
127127 _ = @import("behavior/vector.zig");
128128 _ = @import("behavior/void.zig");
129 if (builtin.arch == .wasm32) {
130 _ = @import("behavior/wasm.zig");
131 }
129132 _ = @import("behavior/while.zig");
130133 _ = @import("behavior/widening.zig");
131134}
test/stage1/behavior/wasm.zig created+8
......@@ -0,0 +1,8 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "memory size and grow" {
5 var prev = @wasmMemorySize(0);
6 expect(prev == @wasmMemoryGrow(0, 1));
7 expect(prev + 1 == @wasmMemorySize(0));
8}