From 444c1c75f04938fc27bea89ac861df5653b72b7e Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 21 Oct 2022 19:27:14 +0100 Subject: [PATCH] Implement MACRO_EXIT in LLVM JIT backend --- src/jit/jit-exits.c | 29 ++++++++++++++++++++++++++++- src/jit/jit-llvm.c | 40 +++++++++++++++++++++++++++++++++++++--- src/jit/jit-priv.h | 2 ++ src/symbols.txt | 1 + test/perf/simple.vhd | 12 ++++++++++++ 5 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/jit/jit-exits.c b/src/jit/jit-exits.c index c4a5c607..b314d0c4 100644 --- a/src/jit/jit-exits.c +++ b/src/jit/jit-exits.c @@ -497,7 +497,34 @@ void *x_mspace_alloc(uint32_t size, uint32_t nelems) } //////////////////////////////////////////////////////////////////////////////// -// Entry points from compiled code +// Entry point from interpreter or JIT compiled code + +DLLEXPORT +void __nvc_do_exit(jit_exit_t which, jit_scalar_t *args) +{ + switch (which) { + case JIT_EXIT_INT_TO_STRING: + { + int64_t value = args[0].integer; + + mspace_t *m = jit_get_mspace(jit_for_thread()); + char *buf = mspace_alloc(m, 20); + if (buf == NULL) + return; + + ffi_uarray_t u = x_int_to_string(value, buf, 20); + args[0].pointer = u.ptr; + args[1].integer = u.dims[0].left; + args[2].integer = u.dims[0].length; + } + break; + default: + fatal_trace("unhandled exit %s", jit_exit_name(which)); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Entry points from AOT compiled code // Helper macro for passing debug loci from LLVM #define DEBUG_LOCUS(name) \ diff --git a/src/jit/jit-llvm.c b/src/jit/jit-llvm.c index 0e837533..a5c9eaf0 100644 --- a/src/jit/jit-llvm.c +++ b/src/jit/jit-llvm.c @@ -86,6 +86,8 @@ typedef enum { LLVM_MUL_OVERFLOW_U32, LLVM_MUL_OVERFLOW_U64, + LLVM_DO_EXIT, + LLVM_LAST_FN, } llvm_fn_t; @@ -326,6 +328,17 @@ static LLVMValueRef cgen_get_fn(cgen_req_t *req, llvm_fn_t which) } break; + case LLVM_DO_EXIT: + { + LLVMTypeRef args[] = { req->types[LLVM_INT32], req->types[LLVM_PTR] }; + req->fntypes[which] = LLVMFunctionType(req->types[LLVM_VOID], args, + ARRAY_LEN(args), false); + + fn = LLVMAddFunction(req->module, "__nvc_do_exit", + req->fntypes[which]); + } + break; + default: fatal_trace("cannot generate prototype for function %d", which); } @@ -394,6 +407,8 @@ static LLVMValueRef cgen_get_value(cgen_req_t *req, cgen_block_t *cgb, case JIT_VALUE_LABEL: return (jit_scalar_t){ .integer = value.label }; */ + case JIT_VALUE_EXIT: + return llvm_int32(req, value.exit); default: fatal_trace("cannot handle value kind %d", value.kind); } @@ -488,7 +503,7 @@ static void cgen_op_load(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) { LLVMValueRef ptr = cgen_get_value(req, cgb, ir->arg1); - LLVMValueRef result; + LLVMValueRef result = NULL; switch (ir->size) { case JIT_SZ_8: result = LLVMBuildLoad2(req->builder, req->types[LLVM_INT8], ptr, ""); @@ -721,7 +736,7 @@ static void cgen_op_neg(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) cgb->outregs[ir->result] = neg; } -static void cgen_op_copy(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) +static void cgen_macro_copy(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) { LLVMValueRef count = cgb->outregs[ir->result]; LLVMValueRef dest = cgen_get_value(req, cgb, ir->arg1); @@ -730,6 +745,19 @@ static void cgen_op_copy(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) LLVMBuildMemMove(req->builder, dest, 0, src, 0, count); } +static void cgen_macro_exit(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) +{ + LLVMValueRef which = cgen_get_value(req, cgb, ir->arg1); + LLVMValueRef fn = cgen_get_fn(req, LLVM_DO_EXIT); + + LLVMValueRef args[] = { + which, + req->args + }; + LLVMBuildCall2(req->builder, req->fntypes[LLVM_DO_EXIT], fn, + args, ARRAY_LEN(args), ""); +} + static void cgen_ir(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) { switch (ir->op) { @@ -743,6 +771,7 @@ static void cgen_ir(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) cgen_op_store(req, cgb, ir); break; case J_LOAD: + case J_ULOAD: cgen_op_load(req, cgb, ir); break; case J_ADD: @@ -784,7 +813,10 @@ static void cgen_ir(cgen_req_t *req, cgen_block_t *cgb, jit_ir_t *ir) cgen_op_neg(req, cgb, ir); break; case MACRO_COPY: - cgen_op_copy(req, cgb, ir); + cgen_macro_copy(req, cgb, ir); + break; + case MACRO_EXIT: + cgen_macro_exit(req, cgb, ir); break; default: warnf("cannot generate LLVM for %s", jit_op_name(ir->op)); @@ -897,6 +929,7 @@ static void cgen_reg_types(cgen_req_t *req) break; case J_LOAD: + case J_ULOAD: case J_MUL: case J_ADD: case J_SUB: @@ -923,6 +956,7 @@ static void cgen_reg_types(cgen_req_t *req) break; case J_LEA: + case MACRO_GETPRIV: cgen_force_reg_type(req, ir->result, LLVM_PTR); break; diff --git a/src/jit/jit-priv.h b/src/jit/jit-priv.h index 4a2b254d..faa5fe81 100644 --- a/src/jit/jit-priv.h +++ b/src/jit/jit-priv.h @@ -264,4 +264,6 @@ void jit_free_cfg(jit_func_t *f); jit_block_t *jit_block_for(jit_cfg_t *cfg, int pos); int jit_get_edge(jit_edge_list_t *list, int nth); +void __nvc_do_exit(jit_exit_t which, jit_scalar_t *args); + #endif // _JIT_PRIV_H diff --git a/src/symbols.txt b/src/symbols.txt index 4f488bc7..15b020cf 100644 --- a/src/symbols.txt +++ b/src/symbols.txt @@ -35,6 +35,7 @@ __nvc_assert_fail; __nvc_claim_tlab; __nvc_div_zero; + __nvc_do_exit; __nvc_drive_signal; __nvc_elab_order_fail; __nvc_exponent_fail; diff --git a/test/perf/simple.vhd b/test/perf/simple.vhd index b16da9e6..977b2387 100644 --- a/test/perf/simple.vhd +++ b/test/perf/simple.vhd @@ -2,6 +2,7 @@ package simple is procedure test_add2; procedure test_fact; procedure test_sum; + procedure test_int_image; end package; package body simple is @@ -65,4 +66,15 @@ package body simple is end loop; end procedure; + --------------------------------------------------------------------------- + + procedure test_int_image is + variable s : string(1 to 3); + begin + assert integer'image(4) = "4"; + for i in 1 to 100 loop + assert integer'image(i)'length <= 3; + end loop; + end procedure; + end package body; -- 2.39.2