Add builtin for llvm.wasm.memory.grow.i32 intrinsic
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()); ```
This commit is contained in:
parent
ce3f0077cf
commit
601e831f1d
@ -1826,6 +1826,7 @@ enum BuiltinFnId {
|
|||||||
BuiltinFnIdCall,
|
BuiltinFnIdCall,
|
||||||
BuiltinFnIdBitSizeof,
|
BuiltinFnIdBitSizeof,
|
||||||
BuiltinFnIdWasmMemorySize,
|
BuiltinFnIdWasmMemorySize,
|
||||||
|
BuiltinFnIdWasmMemoryGrow,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuiltinFnEntry {
|
struct BuiltinFnEntry {
|
||||||
@ -2077,6 +2078,7 @@ struct CodeGen {
|
|||||||
LLVMValueRef safety_crash_err_fn;
|
LLVMValueRef safety_crash_err_fn;
|
||||||
LLVMValueRef return_err_fn;
|
LLVMValueRef return_err_fn;
|
||||||
LLVMValueRef wasm_memory_size;
|
LLVMValueRef wasm_memory_size;
|
||||||
|
LLVMValueRef wasm_memory_grow;
|
||||||
LLVMTypeRef anyframe_fn_type;
|
LLVMTypeRef anyframe_fn_type;
|
||||||
|
|
||||||
// reminder: hash tables must be initialized before use
|
// reminder: hash tables must be initialized before use
|
||||||
@ -2751,6 +2753,7 @@ enum IrInstSrcId {
|
|||||||
IrInstSrcIdSpillBegin,
|
IrInstSrcIdSpillBegin,
|
||||||
IrInstSrcIdSpillEnd,
|
IrInstSrcIdSpillEnd,
|
||||||
IrInstSrcIdWasmMemorySize,
|
IrInstSrcIdWasmMemorySize,
|
||||||
|
IrInstSrcIdWasmMemoryGrow,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
|
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
|
||||||
@ -2844,6 +2847,7 @@ enum IrInstGenId {
|
|||||||
IrInstGenIdAlloca,
|
IrInstGenIdAlloca,
|
||||||
IrInstGenIdConst,
|
IrInstGenIdConst,
|
||||||
IrInstGenIdWasmMemorySize,
|
IrInstGenIdWasmMemorySize,
|
||||||
|
IrInstGenIdWasmMemoryGrow,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Common fields between IrInstSrc and IrInstGen. This allows future passes
|
// Common fields between IrInstSrc and IrInstGen. This allows future passes
|
||||||
@ -3732,11 +3736,23 @@ struct IrInstGenMemcpy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstSrcWasmMemorySize {
|
struct IrInstSrcWasmMemorySize {
|
||||||
IrInstSrc base;
|
IrInstSrc base;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstGenWasmMemorySize {
|
struct IrInstGenWasmMemorySize {
|
||||||
IrInstGen base;
|
IrInstGen base;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IrInstSrcWasmMemoryGrow {
|
||||||
|
IrInstSrc base;
|
||||||
|
|
||||||
|
IrInstSrc *delta;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IrInstGenWasmMemoryGrow {
|
||||||
|
IrInstGen base;
|
||||||
|
|
||||||
|
IrInstGen *delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstSrcSlice {
|
struct IrInstSrcSlice {
|
||||||
|
@ -1047,8 +1047,9 @@ static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstGen *source_instr
|
|||||||
|
|
||||||
static LLVMValueRef gen_wasm_memory_size(CodeGen *g) {
|
static LLVMValueRef gen_wasm_memory_size(CodeGen *g) {
|
||||||
if (g->wasm_memory_size)
|
if (g->wasm_memory_size)
|
||||||
return g->wasm_memory_size;
|
return g->wasm_memory_size;
|
||||||
|
|
||||||
|
// TODO adjust for wasm64 as well
|
||||||
// declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly
|
// declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly
|
||||||
LLVMTypeRef param_type = LLVMInt32Type();
|
LLVMTypeRef param_type = LLVMInt32Type();
|
||||||
LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), ¶m_type, 1, false);
|
LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), ¶m_type, 1, false);
|
||||||
@ -1058,6 +1059,23 @@ static LLVMValueRef gen_wasm_memory_size(CodeGen *g) {
|
|||||||
return g->wasm_memory_size;
|
return g->wasm_memory_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) {
|
||||||
|
if (g->wasm_memory_grow)
|
||||||
|
return g->wasm_memory_grow;
|
||||||
|
|
||||||
|
// TODO adjust for wasm64 as well
|
||||||
|
// declare i32 @llvm.wasm.memory.grow.i32(i32, i32) nounwind
|
||||||
|
LLVMTypeRef param_types[] = {
|
||||||
|
LLVMInt32Type(),
|
||||||
|
LLVMInt32Type(),
|
||||||
|
};
|
||||||
|
LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, false);
|
||||||
|
g->wasm_memory_grow = LLVMAddFunction(g->module, "llvm.wasm.memory.grow.i32", fn_type);
|
||||||
|
assert(LLVMGetIntrinsicID(g->wasm_memory_grow));
|
||||||
|
|
||||||
|
return g->wasm_memory_grow;
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
|
static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
|
||||||
if (g->stacksave_fn_val)
|
if (g->stacksave_fn_val)
|
||||||
return g->stacksave_fn_val;
|
return g->stacksave_fn_val;
|
||||||
@ -5607,11 +5625,27 @@ static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *exec
|
|||||||
//
|
//
|
||||||
// More info:
|
// More info:
|
||||||
// https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#current-linear-memory-size
|
// 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 zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type);
|
||||||
LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &zero, 1, "");
|
LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &zero, 1, "");
|
||||||
return val;
|
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->delta),
|
||||||
|
};
|
||||||
|
LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_grow(g), params, 2, "");
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) {
|
static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) {
|
||||||
Error err;
|
Error err;
|
||||||
|
|
||||||
@ -6824,6 +6858,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl
|
|||||||
return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction);
|
return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction);
|
||||||
case IrInstGenIdWasmMemorySize:
|
case IrInstGenIdWasmMemorySize:
|
||||||
return ir_render_wasm_memory_size(g, executable, (IrInstGenWasmMemorySize *) instruction);
|
return ir_render_wasm_memory_size(g, executable, (IrInstGenWasmMemorySize *) instruction);
|
||||||
|
case IrInstGenIdWasmMemoryGrow:
|
||||||
|
return ir_render_wasm_memory_grow(g, executable, (IrInstGenWasmMemoryGrow *) instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -8687,6 +8723,7 @@ static void define_builtin_fns(CodeGen *g) {
|
|||||||
create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
|
create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
|
||||||
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
|
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
|
||||||
create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 0);
|
create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 0);
|
||||||
|
create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *bool_to_str(bool b) {
|
static const char *bool_to_str(bool b) {
|
||||||
|
107
src/ir.cpp
107
src/ir.cpp
@ -558,6 +558,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
|
|||||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst));
|
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst));
|
||||||
case IrInstSrcIdWasmMemorySize:
|
case IrInstSrcIdWasmMemorySize:
|
||||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst));
|
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst));
|
||||||
|
case IrInstSrcIdWasmMemoryGrow:
|
||||||
|
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst));
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -740,6 +742,8 @@ void destroy_instruction_gen(IrInstGen *inst) {
|
|||||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegationWrapping *>(inst));
|
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenNegationWrapping *>(inst));
|
||||||
case IrInstGenIdWasmMemorySize:
|
case IrInstGenIdWasmMemorySize:
|
||||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemorySize *>(inst));
|
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemorySize *>(inst));
|
||||||
|
case IrInstGenIdWasmMemoryGrow:
|
||||||
|
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenWasmMemoryGrow *>(inst));
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -1338,10 +1342,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) {
|
|||||||
return IrInstSrcIdBoolNot;
|
return IrInstSrcIdBoolNot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) {
|
|
||||||
return IrInstSrcIdWasmMemorySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) {
|
static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) {
|
||||||
return IrInstSrcIdMemset;
|
return IrInstSrcIdMemset;
|
||||||
}
|
}
|
||||||
@ -1618,6 +1618,14 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) {
|
|||||||
return IrInstSrcIdSpillEnd;
|
return IrInstSrcIdSpillEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) {
|
||||||
|
return IrInstSrcIdWasmMemorySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) {
|
||||||
|
return IrInstSrcIdWasmMemoryGrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
|
static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
|
||||||
return IrInstGenIdDeclVar;
|
return IrInstGenIdDeclVar;
|
||||||
@ -1967,6 +1975,10 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemorySize *) {
|
|||||||
return IrInstGenIdWasmMemorySize;
|
return IrInstGenIdWasmMemorySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemoryGrow *) {
|
||||||
|
return IrInstGenIdWasmMemoryGrow;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
|
static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
|
||||||
T *special_instruction = heap::c_allocator.create<T>();
|
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
|
|||||||
return &instruction->base;
|
return &instruction->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
|
|
||||||
IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(irb, scope, source_node);
|
|
||||||
|
|
||||||
return &instruction->base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr) {
|
|
||||||
IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb,
|
|
||||||
source_instr->scope, source_instr->source_node);
|
|
||||||
instruction->base.value->type = ira->codegen->builtin_types.entry_i32;
|
|
||||||
|
|
||||||
return &instruction->base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
|
static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
|
||||||
IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count)
|
IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count)
|
||||||
{
|
{
|
||||||
@ -4987,6 +4985,41 @@ static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_in
|
|||||||
return &instruction->base;
|
return &instruction->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
|
||||||
|
IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(irb, scope, source_node);
|
||||||
|
|
||||||
|
return &instruction->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr) {
|
||||||
|
IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb,
|
||||||
|
source_instr->scope, source_instr->source_node);
|
||||||
|
instruction->base.value->type = ira->codegen->builtin_types.entry_i32;
|
||||||
|
|
||||||
|
return &instruction->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *delta) {
|
||||||
|
IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction<IrInstSrcWasmMemoryGrow>(irb, scope, source_node);
|
||||||
|
instruction->delta = delta;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen<IrInstGenWasmMemoryGrow>(&ira->new_irb,
|
||||||
|
source_instr->scope, source_instr->source_node);
|
||||||
|
instruction->base.value->type = ira->codegen->builtin_types.entry_i32;
|
||||||
|
instruction->delta = delta;
|
||||||
|
|
||||||
|
ir_ref_inst_gen(delta);
|
||||||
|
|
||||||
|
return &instruction->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
||||||
results[ReturnKindUnconditional] = 0;
|
results[ReturnKindUnconditional] = 0;
|
||||||
results[ReturnKindError] = 0;
|
results[ReturnKindError] = 0;
|
||||||
@ -6785,6 +6818,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
|
|||||||
IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node);
|
IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node);
|
||||||
return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc);
|
return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc);
|
||||||
}
|
}
|
||||||
|
case BuiltinFnIdWasmMemoryGrow:
|
||||||
|
{
|
||||||
|
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_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value);
|
||||||
|
return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc);
|
||||||
|
}
|
||||||
case BuiltinFnIdField:
|
case BuiltinFnIdField:
|
||||||
{
|
{
|
||||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
static IrInstGen *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, IrInstSrcWasmMemorySize *instruction) {
|
static IrInstGen *ir_analyze_instruction_wasm_memory_size(IrAnalyze *ira, IrInstSrcWasmMemorySize *instruction) {
|
||||||
|
// TODO generate compile error for target_arch different than 32bit
|
||||||
if (!target_is_wasm(ira->codegen->zig_target)) {
|
if (!target_is_wasm(ira->codegen->zig_target)) {
|
||||||
ir_add_error_node(ira, instruction->base.base.source_node,
|
ir_add_error_node(ira, instruction->base.base.source_node,
|
||||||
buf_sprintf("@wasmMemorySize is a wasm feature only"));
|
buf_sprintf("@wasmMemorySize is a wasm32 feature only"));
|
||||||
return ira->codegen->invalid_inst_gen;
|
return ira->codegen->invalid_inst_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ir_build_wasm_memory_size_gen(ira, &instruction->base.base);
|
return ir_build_wasm_memory_size_gen(ira, &instruction->base.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IrInstGen *ir_analyze_instruction_wasm_memory_grow(IrAnalyze *ira, IrInstSrcWasmMemoryGrow *instruction) {
|
||||||
|
// TODO generate compile error for target_arch different than 32bit
|
||||||
|
if (!target_is_wasm(ira->codegen->zig_target)) {
|
||||||
|
ir_add_error_node(ira, instruction->base.base.source_node,
|
||||||
|
buf_sprintf("@wasmMemoryGrow is a wasm32 feature only"));
|
||||||
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrInstGen *delta = instruction->delta->child;
|
||||||
|
if (type_is_invalid(delta->value->type))
|
||||||
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
|
||||||
|
ZigType *i32_type = ira->codegen->builtin_types.entry_i32;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) {
|
static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) {
|
||||||
return ir_build_breakpoint_gen(ira, &instruction->base.base);
|
return ir_build_breakpoint_gen(ira, &instruction->base.base);
|
||||||
}
|
}
|
||||||
@ -30935,6 +31000,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
|
|||||||
return ir_analyze_instruction_spill_end(ira, (IrInstSrcSpillEnd *)instruction);
|
return ir_analyze_instruction_spill_end(ira, (IrInstSrcSpillEnd *)instruction);
|
||||||
case IrInstSrcIdWasmMemorySize:
|
case IrInstSrcIdWasmMemorySize:
|
||||||
return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
|
return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
|
||||||
|
case IrInstSrcIdWasmMemoryGrow:
|
||||||
|
return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -31111,6 +31178,7 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) {
|
|||||||
case IrInstGenIdResume:
|
case IrInstGenIdResume:
|
||||||
case IrInstGenIdAwait:
|
case IrInstGenIdAwait:
|
||||||
case IrInstGenIdSpillBegin:
|
case IrInstGenIdSpillBegin:
|
||||||
|
case IrInstGenIdWasmMemoryGrow:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case IrInstGenIdPhi:
|
case IrInstGenIdPhi:
|
||||||
@ -31243,6 +31311,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
|
|||||||
case IrInstSrcIdResume:
|
case IrInstSrcIdResume:
|
||||||
case IrInstSrcIdAwait:
|
case IrInstSrcIdAwait:
|
||||||
case IrInstSrcIdSpillBegin:
|
case IrInstSrcIdSpillBegin:
|
||||||
|
case IrInstSrcIdWasmMemoryGrow:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case IrInstSrcIdPhi:
|
case IrInstSrcIdPhi:
|
||||||
|
@ -323,6 +323,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
|
|||||||
return "SrcSpillEnd";
|
return "SrcSpillEnd";
|
||||||
case IrInstSrcIdWasmMemorySize:
|
case IrInstSrcIdWasmMemorySize:
|
||||||
return "SrcWasmMemorySize";
|
return "SrcWasmMemorySize";
|
||||||
|
case IrInstSrcIdWasmMemoryGrow:
|
||||||
|
return "SrcWasmMemoryGrow";
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -505,6 +507,8 @@ const char* ir_inst_gen_type_str(IrInstGenId id) {
|
|||||||
return "GenNegationWrapping";
|
return "GenNegationWrapping";
|
||||||
case IrInstGenIdWasmMemorySize:
|
case IrInstGenIdWasmMemorySize:
|
||||||
return "GenWasmMemorySize";
|
return "GenWasmMemorySize";
|
||||||
|
case IrInstGenIdWasmMemoryGrow:
|
||||||
|
return "GenWasmMemoryGrow";
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -1720,6 +1724,18 @@ static void ir_print_wasm_memory_size(IrPrintGen *irp, IrInstGenWasmMemorySize *
|
|||||||
fprintf(irp->f, "@wasmMemorySize()");
|
fprintf(irp->f, "@wasmMemorySize()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ir_print_wasm_memory_grow(IrPrintSrc *irp, IrInstSrcWasmMemoryGrow *instruction) {
|
||||||
|
fprintf(irp->f, "@wasmMemoryGrow(");
|
||||||
|
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->delta);
|
||||||
|
fprintf(irp->f, ")");
|
||||||
|
}
|
||||||
|
|
||||||
static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
|
static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
|
||||||
fprintf(irp->f, "@memset(");
|
fprintf(irp->f, "@memset(");
|
||||||
ir_print_other_inst_src(irp, instruction->dest_ptr);
|
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
|
|||||||
case IrInstSrcIdWasmMemorySize:
|
case IrInstSrcIdWasmMemorySize:
|
||||||
ir_print_wasm_memory_size(irp, (IrInstSrcWasmMemorySize *)instruction);
|
ir_print_wasm_memory_size(irp, (IrInstSrcWasmMemorySize *)instruction);
|
||||||
break;
|
break;
|
||||||
|
case IrInstSrcIdWasmMemoryGrow:
|
||||||
|
ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fprintf(irp->f, "\n");
|
fprintf(irp->f, "\n");
|
||||||
}
|
}
|
||||||
@ -3237,6 +3256,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai
|
|||||||
case IrInstGenIdWasmMemorySize:
|
case IrInstGenIdWasmMemorySize:
|
||||||
ir_print_wasm_memory_size(irp, (IrInstGenWasmMemorySize *)instruction);
|
ir_print_wasm_memory_size(irp, (IrInstGenWasmMemorySize *)instruction);
|
||||||
break;
|
break;
|
||||||
|
case IrInstGenIdWasmMemoryGrow:
|
||||||
|
ir_print_wasm_memory_grow(irp, (IrInstGenWasmMemoryGrow *)instruction);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fprintf(irp->f, "\n");
|
fprintf(irp->f, "\n");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user