From 27d45468ed9c96b87da04e59d4e57f8300ea3f6b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 19 Nov 2022 12:05:12 +0000 Subject: [PATCH] Rematerialise trees in jit-llvm --- src/jit/jit-dump.c | 2 + src/jit/jit-exits.c | 6 ++ src/jit/jit-interp.c | 2 + src/jit/jit-irgen.c | 2 +- src/jit/jit-llvm.c | 144 ++++++++++++++++++++++++++++++------------- src/jit/jit-priv.h | 2 + src/symbols.txt | 1 + 7 files changed, 114 insertions(+), 45 deletions(-) diff --git a/src/jit/jit-dump.c b/src/jit/jit-dump.c index bd397744..093ae0bd 100644 --- a/src/jit/jit-dump.c +++ b/src/jit/jit-dump.c @@ -127,6 +127,8 @@ static int jit_dump_value(jit_dump_t *d, jit_value_t value) return printf("<%s:%d>", loc_file_str(&value.loc), value.loc.first_line); case JIT_VALUE_FOREIGN: return printf("$%s", istr(ffi_get_sym(value.foreign))); + case JIT_VALUE_TREE: + return printf("%s@%p", tree_kind_str(tree_kind(value.tree)), value.tree); case JIT_VALUE_INVALID: return printf("???"); } diff --git a/src/jit/jit-exits.c b/src/jit/jit-exits.c index de0fc05a..9b504fa3 100644 --- a/src/jit/jit-exits.c +++ b/src/jit/jit-exits.c @@ -1509,3 +1509,9 @@ jit_foreign_t *__nvc_get_foreign(const char *name, ffi_spec_t spec) ident_t id = ident_new(name); return jit_ffi_get(id) ?: jit_ffi_bind(id, spec, NULL); } + +DLLEXPORT +tree_t __nvc_get_tree(const char *unit, ptrdiff_t offset) +{ + return tree_from_locus(ident_new(unit), offset, lib_get_qualified); +} diff --git a/src/jit/jit-interp.c b/src/jit/jit-interp.c index 278abf40..98a3f807 100644 --- a/src/jit/jit-interp.c +++ b/src/jit/jit-interp.c @@ -169,6 +169,8 @@ static jit_scalar_t interp_get_value(jit_interp_t *state, jit_value_t value) return (jit_scalar_t){ .integer = value.handle }; case JIT_VALUE_FOREIGN: return (jit_scalar_t){ .pointer = value.foreign }; + case JIT_VALUE_TREE: + return (jit_scalar_t){ .pointer = value.tree }; default: interp_dump(state); fatal_trace("cannot handle value kind %d", value.kind); diff --git a/src/jit/jit-irgen.c b/src/jit/jit-irgen.c index 287898b3..1d7ed09d 100644 --- a/src/jit/jit-irgen.c +++ b/src/jit/jit-irgen.c @@ -100,7 +100,7 @@ static inline jit_value_t jit_value_from_loc(const loc_t *loc) static inline jit_value_t jit_value_from_tree(tree_t t) { - jit_value_t value = { .kind = JIT_VALUE_INT64, .int64 = (intptr_t)t }; + jit_value_t value = { .kind = JIT_VALUE_TREE, .tree = t }; return value; } diff --git a/src/jit/jit-llvm.c b/src/jit/jit-llvm.c index 938243d9..c605e150 100644 --- a/src/jit/jit-llvm.c +++ b/src/jit/jit-llvm.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -110,6 +111,7 @@ typedef enum { LLVM_REGISTER, LLVM_GET_FUNC, LLVM_GET_FOREIGN, + LLVM_GET_TREE, LLVM_LAST_FN, } llvm_fn_t; @@ -635,6 +637,18 @@ static LLVMValueRef llvm_get_fn(llvm_obj_t *obj, llvm_fn_t which) } break; + case LLVM_GET_TREE: + { + LLVMTypeRef args[] = { + obj->types[LLVM_PTR], + obj->types[LLVM_INTPTR] + }; + obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_PTR], args, + ARRAY_LEN(args), false); + fn = llvm_add_fn(obj, "__nvc_get_tree", obj->fntypes[which]); + } + break; + default: fatal_trace("cannot generate prototype for function %d", which); } @@ -722,6 +736,82 @@ static void cgen_abort(cgen_block_t *cgb, jit_ir_t *ir, const char *fmt, ...) va_end(ap); } +static LLVMBasicBlockRef cgen_add_ctor(llvm_obj_t *obj) +{ + assert(obj->ctor != NULL); + LLVMBasicBlockRef old_bb = LLVMGetInsertBlock(obj->builder); + LLVMPositionBuilderAtEnd(obj->builder, LLVMGetLastBasicBlock(obj->ctor)); + return old_bb; +} + +static LLVMValueRef cgen_rematerialise_tree(llvm_obj_t *obj, tree_t tree) +{ + ident_t unit; + ptrdiff_t offset; + tree_locus(tree, &unit, &offset); + + LOCAL_TEXT_BUF tb = tb_new(); + tb_istr(tb, unit); + tb_printf(tb, ".%"PRIiPTR".tree", offset); + + LLVMValueRef global = LLVMGetNamedGlobal(obj->module, tb_get(tb)); + if (global == NULL) { + global = LLVMAddGlobal(obj->module, obj->types[LLVM_PTR], tb_get(tb)); + LLVMSetUnnamedAddr(global, true); + LLVMSetLinkage(global, LLVMPrivateLinkage); + LLVMSetInitializer(global, llvm_ptr(obj, NULL)); + + LLVMBasicBlockRef old_bb = cgen_add_ctor(obj); + + tb_trim(tb, ident_len(unit)); // Strip suffix + + LLVMValueRef args[] = { + llvm_const_string(obj, tb_get(tb)), + llvm_intptr(obj, offset), + }; + LLVMValueRef init = + llvm_call_fn(obj, LLVM_GET_TREE, args, ARRAY_LEN(args)); + LLVMBuildStore(obj->builder, init, global); + + LLVMPositionBuilderAtEnd(obj->builder, old_bb); + } + + return LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], global, ""); +} + +static LLVMValueRef cgen_rematerialise_ffi(llvm_obj_t *obj, jit_foreign_t *ff) +{ + ident_t sym = ffi_get_sym(ff); + + LOCAL_TEXT_BUF tb = tb_new(); + tb_istr(tb, sym); + tb_cat(tb, ".ffi"); + + LLVMValueRef global = LLVMGetNamedGlobal(obj->module, tb_get(tb)); + if (global == NULL) { + global = LLVMAddGlobal(obj->module, obj->types[LLVM_PTR], tb_get(tb)); + LLVMSetUnnamedAddr(global, true); + LLVMSetLinkage(global, LLVMPrivateLinkage); + LLVMSetInitializer(global, llvm_ptr(obj, NULL)); + + LLVMBasicBlockRef old_bb = cgen_add_ctor(obj); + + tb_trim(tb, ident_len(sym)); // Strip .ffi + + LLVMValueRef args[] = { + llvm_const_string(obj, tb_get(tb)), + llvm_int64(obj, ffi_get_spec(ff)), + }; + LLVMValueRef init = + llvm_call_fn(obj, LLVM_GET_FOREIGN, args, ARRAY_LEN(args)); + LLVMBuildStore(obj->builder, init, global); + + LLVMPositionBuilderAtEnd(obj->builder, old_bb); + } + + return LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], global, ""); +} + static LLVMValueRef cgen_get_value(llvm_obj_t *obj, cgen_block_t *cgb, jit_value_t value) { @@ -773,7 +863,15 @@ static LLVMValueRef cgen_get_value(llvm_obj_t *obj, cgen_block_t *cgb, assert(obj->ctor == NULL || value.int64 == 0); return llvm_ptr(obj, (void *)(intptr_t)value.int64); case JIT_VALUE_FOREIGN: - return llvm_ptr(obj, (void *)(intptr_t)0xdeadbeef); + if (cgb->func->cpool != NULL) + return cgen_rematerialise_ffi(obj, value.foreign); + else + return llvm_ptr(obj, value.foreign); + case JIT_VALUE_TREE: + if (cgb->func->cpool != NULL) + return cgen_rematerialise_tree(obj, value.tree); + else + return llvm_ptr(obj, value.tree); default: fatal_trace("cannot handle value kind %d", value.kind); } @@ -892,14 +990,6 @@ static void cgen_sync_irpos(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir) LLVMBuildStore(obj->builder, llvm_int32(obj, irpos), irpos_ptr); } -static LLVMBasicBlockRef cgen_add_ctor(llvm_obj_t *obj) -{ - assert(obj->ctor != NULL); - LLVMBasicBlockRef old_bb = LLVMGetInsertBlock(obj->builder); - LLVMPositionBuilderAtEnd(obj->builder, LLVMGetLastBasicBlock(obj->ctor)); - return old_bb; -} - static void cgen_op_recv(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir) { assert(ir->arg1.kind == JIT_VALUE_INT64); @@ -1438,41 +1528,7 @@ static void cgen_macro_fficall(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir) { cgen_sync_irpos(obj, cgb, ir); - LLVMValueRef ffptr; - if (obj->ctor != NULL) { - assert(ir->arg1.kind == JIT_VALUE_FOREIGN); - ident_t sym = ffi_get_sym(ir->arg1.foreign); - - LOCAL_TEXT_BUF tb = tb_new(); - tb_istr(tb, sym); - tb_cat(tb, ".ffi"); - - LLVMValueRef global = LLVMGetNamedGlobal(obj->module, tb_get(tb)); - if (global == NULL) { - global = LLVMAddGlobal(obj->module, obj->types[LLVM_PTR], tb_get(tb)); - LLVMSetUnnamedAddr(global, true); - LLVMSetLinkage(global, LLVMPrivateLinkage); - LLVMSetInitializer(global, llvm_ptr(obj, NULL)); - - LLVMBasicBlockRef old_bb = cgen_add_ctor(obj); - - tb_trim(tb, ident_len(sym)); // Strip .ffi - - LLVMValueRef args[] = { - llvm_const_string(obj, tb_get(tb)), - llvm_int64(obj, ffi_get_spec(ir->arg1.foreign)), - }; - LLVMValueRef init = - llvm_call_fn(obj, LLVM_GET_FOREIGN, args, ARRAY_LEN(args)); - LLVMBuildStore(obj->builder, init, global); - - LLVMPositionBuilderAtEnd(obj->builder, old_bb); - } - - ffptr = LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], global, ""); - } - else - ffptr = cgen_get_value(obj, cgb, ir->arg1); + LLVMValueRef ffptr = cgen_get_value(obj, cgb, ir->arg1); LLVMValueRef args[] = { ffptr, diff --git a/src/jit/jit-priv.h b/src/jit/jit-priv.h index 33acb7cb..11ab7ca2 100644 --- a/src/jit/jit-priv.h +++ b/src/jit/jit-priv.h @@ -164,6 +164,7 @@ typedef enum { JIT_VALUE_EXIT, JIT_VALUE_LOC, JIT_VALUE_FOREIGN, + JIT_VALUE_TREE, } jit_value_kind_t; typedef uint32_t jit_label_t; @@ -181,6 +182,7 @@ typedef struct { jit_exit_t exit; loc_t loc; jit_foreign_t *foreign; + tree_t tree; }; } jit_value_t; diff --git a/src/symbols.txt b/src/symbols.txt index b02b56c8..4143a3e3 100644 --- a/src/symbols.txt +++ b/src/symbols.txt @@ -45,6 +45,7 @@ __nvc_get_func; __nvc_get_foreign; __nvc_get_handle; + __nvc_get_tree; __nvc_getpriv; __nvc_index_fail; __nvc_length_fail; -- 2.39.2