aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2020-05-31 21:11:06 +0200
committerAndrew Kelley <andrew@ziglang.org>2020-06-09 00:22:17 -0400
commitce3f0077cf3c5ae8edc116177f2f3d33258be9f7 (patch)
treea8cc4c5d9721c90b4ccd0304049551952f662dfd /src/codegen.cpp
parent12051b02f1f455b85d5a519dd1747a67d4bb68d0 (diff)
downloadzig-ce3f0077cf3c5ae8edc116177f2f3d33258be9f7.tar.gz
zig-ce3f0077cf3c5ae8edc116177f2f3d33258be9f7.zip
Add builtin for llvm.wasm.memory.size.i32 instrinsic
This will allow the developer to poll the runtime for currently allocated memory in the number of Wasm pages. Typical usage: ```zig var wasm_pages = @wasmMemorySize(); @import("std").debug.assert(wasm_pages > 0); ```
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 92317f0965..c00ac41a95 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1045,6 +1045,19 @@ static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstGen *source_instr
return gen_assertion_scope(g, msg_id, source_instruction->base.scope);
}
+static LLVMValueRef gen_wasm_memory_size(CodeGen *g) {
+ if (g->wasm_memory_size)
+ return g->wasm_memory_size;
+
+ // declare i32 @llvm.wasm.memory.size.i32(i32) nounwind readonly
+ LLVMTypeRef param_type = LLVMInt32Type();
+ LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt32Type(), &param_type, 1, false);
+ g->wasm_memory_size = LLVMAddFunction(g->module, "llvm.wasm.memory.size.i32", fn_type);
+ assert(LLVMGetIntrinsicID(g->wasm_memory_size));
+
+ return g->wasm_memory_size;
+}
+
static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
if (g->stacksave_fn_val)
return g->stacksave_fn_val;
@@ -5588,6 +5601,17 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, Ir
return nullptr;
}
+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
+ LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type);
+ LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &zero, 1, "");
+ return val;
+}
+
static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) {
Error err;
@@ -6798,6 +6822,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl
return ir_render_splat(g, executable, (IrInstGenSplat *) instruction);
case IrInstGenIdVectorExtractElem:
return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction);
+ case IrInstGenIdWasmMemorySize:
+ return ir_render_wasm_memory_size(g, executable, (IrInstGenWasmMemorySize *) instruction);
}
zig_unreachable();
}
@@ -8660,6 +8686,7 @@ 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);
}
static const char *bool_to_str(bool b) {