diff --git a/src/cgen.c b/src/cgen.c index cae51b534..df7e0f12d 100644 --- a/src/cgen.c +++ b/src/cgen.c @@ -20,17 +20,18 @@ #include "common.h" #include "diag.h" #include "hash.h" -#include "lower.h" #include "jit/jit-ffi.h" #include "jit/jit-llvm.h" #include "jit/jit.h" #include "lib.h" +#include "lower.h" #include "object.h" #include "option.h" #include "phase.h" #include "rt/cover.h" #include "rt/rt.h" #include "thread.h" +#include "type.h" #include "vcode.h" #include @@ -411,13 +412,20 @@ void cgen(tree_t top, unit_registry_t *ur) workq_free(wq); } -static void preload_add_children(vcode_unit_t vu, unit_list_t *list) +static void preload_add_unit(preload_job_t *job, ident_t ident) { - vcode_select_unit(vu); - APUSH(*list, vu); + vcode_unit_t vu = unit_registry_get(job->registry, ident); + if (vu == NULL) + fatal("missing code for %s", istr(ident)); - for (vcode_unit_t it = vcode_unit_child(vu); it; it = vcode_unit_next(it)) - preload_add_children(it, list); + unsigned pos = 0; + for (; pos < job->units.count; pos++) { + if (job->units.items[pos] == vu) + break; + } + + if (pos == job->units.count) + APUSH(job->units, vu); } static void preload_walk_index(lib_t lib, ident_t ident, int kind, void *ctx) @@ -434,11 +442,79 @@ static void preload_walk_index(lib_t lib, ident_t ident, int kind, void *ctx) if (is_uninstantiated_package(unit)) return; - vcode_unit_t vu = unit_registry_get(job->registry, ident); - if (vu == NULL) - fatal("missing code for %s", istr(ident)); + preload_add_unit(job, ident); + + ident_t helper_suffix[] = { + ident_new("image"), + ident_new("value"), + ident_new("resolved"), + ident_new("copy"), + ident_new("new"), + }; + + const int ndecls = tree_decls(unit); + for (int i = 0; i < ndecls; i++) { + tree_t d = tree_decl(unit, i); + if (is_subprogram(d)) { + const subprogram_kind_t kind = tree_subkind(d); + if (kind != S_FOREIGN && !is_open_coded_builtin(kind)) + preload_add_unit(job, tree_ident2(d)); + } + else if (tree_kind(d) == T_TYPE_DECL) { + type_t type = tree_type(d); + ident_t id = type_ident(type); + + if (type_is_protected(type)) { + preload_add_unit(job, id); + + const int nmeth = type_decls(type); + for (int i = 0; i < nmeth; i++) { + tree_t m = type_decl(type, i); + if (is_subprogram(m)) + preload_add_unit(job, tree_ident2(m)); + } + } + else { + for (int i = 0; i < ARRAY_LEN(helper_suffix); i++) { + ident_t func = ident_prefix(id, helper_suffix[i], '$'); + if (unit_registry_query(job->registry, func)) + preload_add_unit(job, func); + } + } + } + } +} + +static void preload_find_dependencies(preload_job_t *job, vcode_unit_t unit) +{ + vcode_select_unit(unit); - preload_add_children(vu, &job->units); + const int nblocks = vcode_count_blocks(); + for (int i = 0; i < nblocks; i++) { + vcode_select_block(i); + + const int nops = vcode_count_ops(); + for (int op = 0; op < nops; op++) { + switch (vcode_get_op(op)) { + case VCODE_OP_LINK_PACKAGE: + preload_add_unit(job, vcode_get_ident(op)); + break; + case VCODE_OP_FCALL: + case VCODE_OP_PCALL: + case VCODE_OP_CLOSURE: + case VCODE_OP_PROTECTED_INIT: + case VCODE_OP_PACKAGE_INIT: + { + const vcode_cc_t cc = vcode_get_subkind(op); + if (cc != VCODE_CC_FOREIGN && cc != VCODE_CC_VARIADIC) + preload_add_unit(job, vcode_get_func(op)); + } + break; + default: + break; + } + } + } } static void preload_do_link(const char *so_name, const char *obj_file) @@ -496,7 +572,7 @@ void aotgen(const char *outfile, char **argv, int argc) } for (unsigned i = 0; i < job.units.count; i++) - cgen_find_dependencies(job.units.items[i], job.registry, &job.units); + preload_find_dependencies(&job, job.units.items[i]); LLVMInitializeNativeTarget(); LLVMInitializeNativeAsmPrinter(); diff --git a/src/common.c b/src/common.c index 743acbebf..36419e48d 100644 --- a/src/common.c +++ b/src/common.c @@ -2254,9 +2254,6 @@ void analyse_file(const char *file, jit_t *jit, unit_registry_t *ur) simplify_local(unit, jit, ur); bounds_check(unit); - - if (error_count() == base_errors && unit_needs_cgen(unit)) - lower_standalone_unit(ur, unit); } else lib_put_error(work, unit); diff --git a/src/elab.c b/src/elab.c index daa68a92a..ffaac1510 100644 --- a/src/elab.c +++ b/src/elab.c @@ -1645,7 +1645,8 @@ static void elab_pop_scope(elab_ctx_t *ctx) cover_pop_scope(ctx->cover); - lower_unit_free(ctx->lowered); + if (ctx->lowered != NULL) + unit_registry_finalise(ctx->registry, ctx->lowered); } static bool elab_copy_genvar_cb(tree_t t, void *ctx) @@ -1879,7 +1880,7 @@ static void elab_psl(tree_t t, const elab_ctx_t *ctx) elab_external_names(t, ctx); if (error_count() == 0) - psl_lower_assert(ctx->lowered, tree_psl(t), tree_ident(t)); + psl_lower_assert(ctx->registry, ctx->lowered, tree_psl(t), tree_ident(t)); tree_add_stmt(ctx->out, t); } diff --git a/src/lower.c b/src/lower.c index 3f6183dd3..dac3d2813 100644 --- a/src/lower.c +++ b/src/lower.c @@ -80,6 +80,7 @@ typedef struct _lower_unit { bool finished; bool elaborating; lower_mode_t mode; + unsigned deferred; } lower_unit_t; typedef enum { @@ -126,8 +127,8 @@ typedef A(concat_param_t) concat_list_t; static vcode_reg_t lower_expr(lower_unit_t *lu, tree_t expr, expr_ctx_t ctx); static vcode_type_t lower_bounds(type_t type); static void lower_stmt(lower_unit_t *lu, tree_t stmt, loop_stack_t *loops); -static void lower_func_body(lower_unit_t *parent, tree_t body); -static void lower_proc_body(lower_unit_t *parent, tree_t body); +static void lower_func_body(lower_unit_t *lu, object_t *obj); +static void lower_proc_body(lower_unit_t *lu, object_t *obj); static vcode_reg_t lower_record_aggregate(lower_unit_t *lu, tree_t expr, bool nest, bool is_const, vcode_reg_t hint); @@ -141,7 +142,7 @@ static void lower_check_array_sizes(lower_unit_t *lu, type_t ltype, static vcode_type_t lower_alias_type(tree_t alias); static bool lower_const_bounds(type_t type); static type_t lower_elem_recur(type_t type); -static void lower_predef(lower_unit_t *parent, tree_t decl); +static void lower_predef(lower_unit_t *lu, object_t *obj); static ident_t lower_predef_func_name(type_t type, const char *op); static void lower_generics(lower_unit_t *lu, tree_t block); static vcode_reg_t lower_default_value(lower_unit_t *lu, type_t type, @@ -7613,10 +7614,12 @@ static void lower_implicit_decl(lower_unit_t *parent, tree_t decl) lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + unit_registry_put(parent->registry, lu); emit_return(lower_rvalue(lu, expr)); - lower_unit_free(lu); + unit_registry_finalise(parent->registry, lu); + vcode_state_restore(&state); vcode_reg_t one_reg = emit_const(vtype_offset(), 1); @@ -7657,6 +7660,7 @@ static void lower_implicit_decl(lower_unit_t *parent, tree_t decl) lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + unit_registry_put(parent->registry, lu); vcode_reg_t nets_reg = lower_signal_ref(lu, decl); vcode_reg_t count_reg = lower_type_width(lu, type, nets_reg); @@ -7693,7 +7697,7 @@ static void lower_implicit_decl(lower_unit_t *parent, tree_t decl) emit_return(VCODE_INVALID_REG); - lower_unit_free(lu); + unit_registry_finalise(parent->registry, lu); vcode_state_restore(&state); @@ -7719,10 +7723,12 @@ static void lower_implicit_decl(lower_unit_t *parent, tree_t decl) lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + unit_registry_put(parent->registry, lu); emit_return(lower_rvalue(lu, expr)); - lower_unit_free(lu); + unit_registry_finalise(parent->registry, lu); + vcode_state_restore(&state); vcode_reg_t one_reg = emit_const(vtype_offset(), 1); @@ -7902,31 +7908,18 @@ static void lower_numeric_image_helper(type_t type, vcode_reg_t preg) emit_return(str_reg); } -static void lower_image_helper(lower_unit_t *parent, tree_t decl) +static void lower_image_helper(lower_unit_t *lu, object_t *obj) { - type_t type = tree_type(decl); - if (!type_is_scalar(type)) - return; - - ident_t func = ident_prefix(type_ident(type), ident_new("image"), '$'); - - if (unit_registry_query(parent->registry, func)) - return; + tree_t decl = tree_from_object(obj); - vcode_state_t state; - vcode_state_save(&state); - - ident_t context_id = vcode_unit_name(); - - vcode_unit_t vu = emit_function(func, tree_to_object(decl), parent->vunit); - - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + type_t type = tree_type(decl); + assert(type_is_scalar(type)); vcode_type_t ctype = vtype_char(); vcode_type_t strtype = vtype_uarray(1, ctype, ctype); vcode_set_result(strtype); - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); vcode_reg_t preg = emit_param(lower_type(type), lower_bounds(type), @@ -7947,9 +7940,6 @@ static void lower_image_helper(lower_unit_t *parent, tree_t decl) fatal_trace("cannot lower image helper for type %s", type_kind_str(type_kind(type))); } - - lower_unit_free(lu); - vcode_state_restore(&state); } static vcode_reg_t lower_enum_value_helper(lower_unit_t *lu, type_t type, @@ -8238,32 +8228,16 @@ static vcode_reg_t lower_numeric_value_helper(type_t type, vcode_reg_t preg) type_is_real(type) ? vreal : vint64); } -static void lower_value_helper(lower_unit_t *parent, tree_t decl) +static void lower_value_helper(lower_unit_t *lu, object_t *obj) { - type_t type = tree_type(decl); - const type_kind_t kind = type_kind(type); - - if (kind == T_SUBTYPE) - return; // Delegated to base type - else if (!type_is_scalar(type)) - return; - - ident_t func = ident_prefix(type_ident(type), ident_new("value"), '$'); + tree_t decl = tree_from_object(obj); - if (unit_registry_query(parent->registry, func)) - return; - - vcode_state_t state; - vcode_state_save(&state); - - ident_t context_id = vcode_unit_name(); + type_t type = tree_type(decl); + assert(type_is_scalar(type)); - vcode_unit_t vu = emit_function(func, tree_to_object(decl), parent->vunit); vcode_set_result(lower_type(type)); - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); - - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); vcode_type_t ctype = vtype_char(); @@ -8271,7 +8245,7 @@ static void lower_value_helper(lower_unit_t *parent, tree_t decl) vcode_reg_t preg = emit_param(strtype, strtype, ident_new("VAL")); vcode_reg_t result = VCODE_INVALID_REG; - switch (kind) { + switch (type_kind(type)) { case T_ENUM: result = lower_enum_value_helper(lu, type, preg); break; @@ -8283,42 +8257,27 @@ static void lower_value_helper(lower_unit_t *parent, tree_t decl) result = lower_physical_value_helper(lu, type, preg); break; default: - fatal_trace("cannot lower value helper for type %s", type_kind_str(kind)); + fatal_trace("cannot lower value helper for type %s", type_pp(type)); } lower_check_scalar_bounds(lu, result, type, decl, NULL); emit_return(emit_cast(lower_type(type), lower_bounds(type), result)); - - lower_unit_free(lu); - vcode_state_restore(&state); } -static void lower_resolved_helper(lower_unit_t *parent, tree_t decl) +static void lower_resolved_helper(lower_unit_t *lu, object_t *obj) { - type_t type = tree_type(decl); - if (type_is_homogeneous(type) || !lower_can_be_signal(type)) - return; - - ident_t func = ident_prefix(type_ident(type), ident_new("resolved"), '$'); - - if (unit_registry_query(parent->registry, func)) - return; + tree_t decl = tree_from_object(obj); - vcode_state_t state; - vcode_state_save(&state); - - ident_t context_id = vcode_unit_name(); + type_t type = tree_type(decl); + assert(!type_is_homogeneous(type) && lower_can_be_signal(type)); - vcode_unit_t vu = emit_function(func, tree_to_object(decl), parent->vunit); vcode_set_result(lower_func_result_type(type)); - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); - vcode_type_t vtype = lower_type(type); vcode_type_t vbounds = lower_bounds(type); vcode_type_t vatype = lower_param_type(type, C_SIGNAL, PORT_IN); - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); vcode_reg_t p_reg = emit_param(vatype, vbounds, ident_new("p")); @@ -8341,36 +8300,20 @@ static void lower_resolved_helper(lower_unit_t *parent, tree_t decl) lower_for_each_field(lu, type, p_reg, data_reg, VCODE_INVALID_REG, lower_resolved_field_cb, NULL); emit_return(result_reg); - - lower_unit_free(lu); - vcode_state_restore(&state); } -static void lower_copy_helper(lower_unit_t *parent, tree_t decl) +static void lower_copy_helper(lower_unit_t *lu, object_t *obj) { - type_t type = tree_type(decl); - if (lower_trivially_copyable(type)) - return; - - vcode_state_t state; - vcode_state_save(&state); - - ident_t func = ident_prefix(type_ident(type), ident_new("copy"), '$'); - - if (unit_registry_query(parent->registry, func)) - return; + tree_t decl = tree_from_object(obj); - ident_t context_id = vcode_unit_name(); - - vcode_unit_t vu = emit_function(func, tree_to_object(decl), parent->vunit); - - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + type_t type = tree_type(decl); + assert(!lower_trivially_copyable(type)); vcode_type_t vbounds = lower_bounds(type); vcode_type_t vdtype = lower_param_type(type, C_VARIABLE, PORT_OUT); vcode_type_t vstype = lower_param_type(type, C_VARIABLE, PORT_IN); vcode_type_t vlocus = vtype_debug_locus(); - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); vcode_reg_t pdst_reg = emit_param(vdtype, vbounds, ident_new("dest")); @@ -8452,35 +8395,19 @@ static void lower_copy_helper(lower_unit_t *parent, tree_t decl) } emit_return(VCODE_INVALID_REG); - - lower_unit_free(lu); - vcode_state_restore(&state); } -static void lower_new_helper(lower_unit_t *parent, tree_t decl) +static void lower_new_helper(lower_unit_t *lu, object_t *obj) { - type_t type = tree_type(decl); - if (!type_is_record(type) || lower_const_bounds(type)) - return; - - vcode_state_t state; - vcode_state_save(&state); + tree_t decl = tree_from_object(obj); - ident_t func = ident_prefix(type_ident(type), ident_new("new"), '$'); - - if (unit_registry_query(parent->registry, func)) - return; - - ident_t context_id = vcode_unit_name(); - - vcode_unit_t vu = emit_function(func, tree_to_object(decl), parent->vunit); - - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + type_t type = tree_type(decl); + assert(type_is_record(type) && !lower_const_bounds(type)); vcode_type_t vbounds = lower_bounds(type); vcode_type_t vdtype = lower_param_type(type, C_VARIABLE, PORT_OUT); vcode_type_t vstype = lower_param_type(type, C_VARIABLE, PORT_IN); - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); vcode_reg_t pdst_reg = emit_param(vdtype, vbounds, ident_new("dest")); @@ -8527,9 +8454,6 @@ static void lower_new_helper(lower_unit_t *parent, tree_t decl) } emit_return(VCODE_INVALID_REG); - - lower_unit_free(lu); - vcode_state_restore(&state); } static void lower_instantiated_package(lower_unit_t *parent, tree_t decl) @@ -8545,6 +8469,7 @@ static void lower_instantiated_package(lower_unit_t *parent, tree_t decl) lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, parent->cover, decl); + unit_registry_put(parent->registry, lu); cover_push_scope(lu->cover, decl); @@ -8555,7 +8480,8 @@ static void lower_instantiated_package(lower_unit_t *parent, tree_t decl) cover_pop_scope(lu->cover); - lower_unit_free(lu); + unit_registry_finalise(parent->registry, lu); + vcode_state_restore(&state); vcode_type_t vcontext = vtype_context(name); @@ -8608,11 +8534,39 @@ static void lower_decl(lower_unit_t *lu, tree_t decl) break; case T_TYPE_DECL: - lower_image_helper(lu, decl); - lower_value_helper(lu, decl); - lower_resolved_helper(lu, decl); - lower_copy_helper(lu, decl); - lower_new_helper(lu, decl); + { + type_t type = tree_type(decl); + ident_t id = type_ident(type); + object_t *obj = tree_to_object(decl); + + if (type_is_scalar(type)) { + ident_t image = ident_prefix(id, ident_new("image"), '$'); + unit_registry_defer(lu->registry, image, lu, emit_function, + lower_image_helper, NULL, obj); + + ident_t value = ident_prefix(id, ident_new("value"), '$'); + unit_registry_defer(lu->registry, value, lu, emit_function, + lower_value_helper, NULL, obj); + } + + if (!type_is_homogeneous(type) && lower_can_be_signal(type)) { + ident_t resolved = ident_prefix(id, ident_new("resolved"), '$'); + unit_registry_defer(lu->registry, resolved, lu, emit_function, + lower_resolved_helper, NULL, obj); + } + + if (!lower_trivially_copyable(type)) { + ident_t copy = ident_prefix(id, ident_new("copy"), '$'); + unit_registry_defer(lu->registry, copy, lu, emit_function, + lower_copy_helper, NULL, obj); + } + + if (type_is_record(type) && !lower_const_bounds(type)) { + ident_t new = ident_prefix(id, ident_new("new"), '$'); + unit_registry_defer(lu->registry, new, lu, emit_function, + lower_new_helper, NULL, obj); + } + } break; case T_FUNC_DECL: @@ -8636,7 +8590,7 @@ static void lower_decl(lower_unit_t *lu, tree_t decl) break; case T_PSL: - psl_lower_decl(lu, tree_psl(decl), tree_ident(decl)); + psl_lower_decl(lu->registry, lu, tree_psl(decl), tree_ident(decl)); break; default: @@ -8657,16 +8611,10 @@ void lower_finished(lower_unit_t *lu) lu->finished = true; } -static void lower_protected_body(lower_unit_t *parent, tree_t body) +static void lower_protected_body(lower_unit_t *lu, object_t *obj) { - vcode_select_unit(parent->vunit); - - object_t *obj = tree_to_object(body); - type_t type = tree_type(body); - vcode_unit_t vu = emit_protected(type_ident(type), obj, parent->vunit); - - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, - parent->cover, body); + tree_t body = tree_from_object(obj); + assert(tree_kind(body) == T_PROT_BODY); cover_push_scope(lu->cover, body); @@ -8674,8 +8622,6 @@ static void lower_protected_body(lower_unit_t *parent, tree_t body) emit_return(VCODE_INVALID_REG); cover_pop_scope(lu->cover); - - lower_unit_free(lu); } static void lower_decls(lower_unit_t *lu, tree_t scope) @@ -8706,12 +8652,43 @@ static void lower_decls(lower_unit_t *lu, tree_t scope) switch (kind) { case T_FUNC_INST: - case T_FUNC_BODY: lower_func_body(lu, d); break; + case T_FUNC_BODY: + unit_registry_defer(lu->registry, tree_ident2(d), + lu, emit_function, lower_func_body, + lu->cover, tree_to_object(d)); + break; case T_PROC_INST: - case T_PROC_BODY: lower_proc_body(lu, d); break; - case T_PROT_BODY: lower_protected_body(lu, d); break; - case T_FUNC_DECL: lower_predef(lu, d); break; - default: break; + case T_PROC_BODY: + { + const bool never_waits = !!(tree_flags(d) & TREE_F_NEVER_WAITS) + || (tree_flags(d) & TREE_F_PROTECTED); + emit_fn_t emitfn = never_waits ? emit_function : emit_procedure; + + unit_registry_defer(lu->registry, tree_ident2(d), + lu, emitfn, lower_proc_body, lu->cover, + tree_to_object(d)); + } + break; + case T_PROT_BODY: + unit_registry_defer(lu->registry, type_ident(tree_type(d)), + lu, emit_protected, lower_protected_body, + lu->cover, tree_to_object(d)); + break; + case T_FUNC_DECL: + { + const subprogram_kind_t kind = tree_subkind(d); + if (kind == S_USER || kind == S_FOREIGN) + continue; + else if (is_open_coded_builtin(kind)) + continue; + + unit_registry_defer(lu->registry, tree_ident2(d), + lu, emit_function, lower_predef, + lu->cover, tree_to_object(d)); + } + break; + default: + break; } vcode_select_unit(lu->vunit); @@ -9762,30 +9739,20 @@ static void lower_predef_negate(tree_t decl, const char *op) emit_return(emit_not(eq_reg)); } -static void lower_predef(lower_unit_t *parent, tree_t decl) +static void lower_predef(lower_unit_t *lu, object_t *obj) { - const subprogram_kind_t kind = tree_subkind(decl); - if (kind == S_USER || kind == S_FOREIGN) - return; - else if (is_open_coded_builtin(kind)) - return; + tree_t decl = tree_from_object(obj); - ident_t name = tree_ident2(decl); - if (unit_registry_query(parent->registry, name)) - return; + const subprogram_kind_t kind = tree_subkind(decl); + assert(kind != S_USER && kind != S_FOREIGN); + assert(!is_open_coded_builtin(kind)); type_t type = tree_type(decl); - - vcode_select_unit(parent->vunit); - ident_t context_id = vcode_unit_name(); - - vcode_unit_t vu = emit_function(name, tree_to_object(decl), parent->vunit); vcode_set_result(lower_func_result_type(type_result(type))); - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); - - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); + lower_subprogram_ports(lu, decl, false); switch (tree_subkind(decl)) { @@ -9864,36 +9831,15 @@ static void lower_predef(lower_unit_t *parent, tree_t decl) default: break; } - - lower_unit_free(lu); } -static void lower_proc_body(lower_unit_t *parent, tree_t body) +static void lower_proc_body(lower_unit_t *lu, object_t *obj) { - const bool never_waits = !!(tree_flags(body) & TREE_F_NEVER_WAITS) - || (tree_flags(body) & TREE_F_PROTECTED); - - vcode_select_unit(parent->vunit); - - ident_t name = tree_ident2(body); - if (unit_registry_query(parent->registry, name)) - return; - - if (is_uninstantiated_subprogram(body)) - return; + tree_t body = tree_from_object(obj); + assert(!is_uninstantiated_subprogram(body)); ident_t context_id = vcode_unit_name(); - vcode_unit_t vu; - object_t *obj = tree_to_object(body); - if (never_waits) - vu = emit_function(name, obj, parent->vunit); - else - vu = emit_procedure(name, obj, parent->vunit); - - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, - parent->cover, body); - cover_push_scope(lu->cover, body); vcode_type_t vcontext = vtype_context(context_id); @@ -9902,6 +9848,7 @@ static void lower_proc_body(lower_unit_t *parent, tree_t body) if (tree_kind(body) == T_PROC_INST) lower_generics(lu, body); + const bool never_waits = vcode_unit_kind() == VCODE_UNIT_FUNCTION; const bool has_subprograms = lower_has_subprograms(body); lower_subprogram_ports(lu, body, has_subprograms || !never_waits); @@ -9915,37 +9862,19 @@ static void lower_proc_body(lower_unit_t *parent, tree_t body) } cover_pop_scope(lu->cover); - - lower_unit_free(lu); - - if (vcode_unit_has_undefined()) - vcode_unit_unref(vu); } -static void lower_func_body(lower_unit_t *parent, tree_t body) +static void lower_func_body(lower_unit_t *lu, object_t *obj) { - vcode_select_unit(parent->vunit); - - ident_t name = tree_ident2(body); - if (unit_registry_query(parent->registry, name)) - return; + tree_t body = tree_from_object(obj); + assert(!is_uninstantiated_subprogram(body)); - if (is_uninstantiated_subprogram(body)) - return; - - ident_t context_id = vcode_unit_name(); type_t result = type_result(tree_type(body)); - - vcode_unit_t vu = emit_function(name, tree_to_object(body), parent->vunit); vcode_set_result(lower_func_result_type(result)); - emit_debug_info(tree_loc(body)); - vcode_type_t vcontext = vtype_context(context_id); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); - lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, - parent->cover, body); - cover_push_scope(lu->cover, body); if (tree_kind(body) == T_FUNC_INST) @@ -9971,8 +9900,6 @@ static void lower_func_body(lower_unit_t *parent, tree_t body) emit_unreachable(lower_debug_locus(body)); cover_pop_scope(lu->cover); - - lower_unit_free(lu); } static void lower_driver_field_cb(lower_unit_t *lu, tree_t field, @@ -10074,6 +10001,7 @@ void lower_process(lower_unit_t *parent, tree_t proc) lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, parent->cover, proc); + unit_registry_put(parent->registry, lu); cover_push_scope(lu->cover, proc); @@ -10106,7 +10034,8 @@ void lower_process(lower_unit_t *parent, tree_t proc) cover_pop_scope(lu->cover); - lower_unit_free(lu); + lower_finished(lu); + unit_registry_finalise(parent->registry, lu); } static bool lower_is_signal_ref(tree_t expr) @@ -10209,6 +10138,7 @@ static ident_t lower_converter(lower_unit_t *parent, tree_t expr, emit_debug_info(tree_loc(expr)); lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + unit_registry_put(parent->registry, lu); vcode_type_t vcontext = vtype_context(context_id); emit_param(vcontext, vcontext, ident_new("context")); @@ -10238,7 +10168,8 @@ static ident_t lower_converter(lower_unit_t *parent, tree_t expr, emit_return(result_reg); } - lower_unit_free(lu); + unit_registry_finalise(parent->registry, lu); + vcode_state_restore(&state); return name; @@ -10430,6 +10361,7 @@ static void lower_non_static_actual(lower_unit_t *parent, tree_t port, vcode_unit_t vu = emit_process(pname, tree_to_object(wave), parent->vunit); lower_unit_t *lu = lower_unit_new(parent->registry, parent, vu, NULL, NULL); + unit_registry_put(parent->registry, lu); { vcode_reg_t nets_reg = emit_load_indirect(emit_var_upref(1, var)); @@ -10468,7 +10400,7 @@ static void lower_non_static_actual(lower_unit_t *parent, tree_t port, emit_return(VCODE_INVALID_REG); - lower_unit_free(lu); + unit_registry_finalise(parent->registry, lu); vcode_state_restore(&state); @@ -11107,52 +11039,37 @@ static void lower_dependencies(tree_t primary, tree_t secondary) tree_walk_deps(secondary, lower_deps_cb, NULL); } -static vcode_unit_t lower_pack_body(unit_registry_t *ur, tree_t unit) +static void lower_pack_body(lower_unit_t *lu, object_t *obj) { - tree_t pack = tree_primary(unit); - assert(!is_uninstantiated_package(pack)); + tree_t body = tree_from_object(obj); - ident_t name = tree_ident(pack); - object_t *obj = tree_to_object(unit); - vcode_unit_t context = emit_package(name, obj, NULL); - - lower_unit_t *lu = lower_unit_new(ur, NULL, context, NULL, unit); + tree_t pack = tree_primary(body); + assert(!is_uninstantiated_package(pack)); - if (standard() >= STD_08 && is_well_known(name) == W_IEEE_1164) { + if (standard() >= STD_08 && is_well_known(lu->name) == W_IEEE_1164) { // VHDL-2008 and later matching operators on STD_LOGIC are // implemented in the support package ident_t ieee_support = ident_new("NVC.IEEE_SUPPORT"); emit_package_init(ieee_support, VCODE_INVALID_REG); } - lower_dependencies(pack, unit); + lower_dependencies(pack, body); lower_decls(lu, pack); - lower_decls(lu, unit); + lower_decls(lu, body); emit_return(VCODE_INVALID_REG); - - lower_unit_free(lu); - return context; } -static vcode_unit_t lower_package(unit_registry_t *ur, tree_t unit) +static void lower_package(lower_unit_t *lu, object_t *obj) { - assert(!is_uninstantiated_package(unit)); - - ident_t name = tree_ident(unit); - object_t *obj = tree_to_object(unit); - vcode_unit_t context = emit_package(name, obj, NULL); - - lower_unit_t *lu = lower_unit_new(ur, NULL, context, NULL, unit); + tree_t pack = tree_from_object(obj); + assert(!is_uninstantiated_package(pack)); - lower_dependencies(unit, NULL); - lower_generics(lu, unit); - lower_decls(lu, unit); + lower_dependencies(pack, NULL); + lower_generics(lu, pack); + lower_decls(lu, pack); emit_return(VCODE_INVALID_REG); - - lower_unit_free(lu); - return context; } vcode_reg_t lower_lvalue(lower_unit_t *lu, tree_t expr) @@ -11282,6 +11199,7 @@ vcode_unit_t lower_case_generate_thunk(lower_unit_t *parent, tree_t t) if (!vcode_block_finished()) emit_return(emit_const(vint, -1)); + lower_finished(lu); lower_unit_free(lu); return thunk; @@ -11297,7 +11215,8 @@ vcode_unit_t lower_thunk(lower_unit_t *parent, tree_t t) vcode_unit_t context = parent ? parent->vunit : NULL; vcode_unit_t thunk = emit_thunk(NULL, tree_to_object(t), context); - lower_unit_t *lu = lower_unit_new(parent ? parent->registry : NULL, parent, thunk, NULL, NULL); + lower_unit_t *lu = lower_unit_new(parent ? parent->registry : NULL, + parent, thunk, NULL, NULL); vcode_type_t vtype = VCODE_INVALID_TYPE; switch (tree_kind(t)) { @@ -11333,6 +11252,7 @@ vcode_unit_t lower_thunk(lower_unit_t *parent, tree_t t) else emit_return(result_reg); + lower_finished(lu); lower_unit_free(lu); if (vcode_unit_has_undefined()) { @@ -11359,6 +11279,7 @@ lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, parent ? parent->vunit : NULL); lower_unit_t *lu = lower_unit_new(ur, parent, vu, cover, block); + unit_registry_put(ur, lu); cover_push_scope(cover, block); @@ -11376,29 +11297,6 @@ lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, return lu; } -void lower_standalone_unit(unit_registry_t *ur, tree_t unit) -{ - freeze_global_arena(); - - vcode_unit_t root = NULL; - switch (tree_kind(unit)) { - case T_PACK_BODY: - root = lower_pack_body(ur, unit); - break; - case T_PACKAGE: - assert(!package_needs_body(unit)); - // Fall-through - case T_PACK_INST: - root = lower_package(ur, unit); - break; - default: - fatal("cannot lower unit kind %s to vcode", - tree_kind_str(tree_kind(unit))); - } - - lib_put_vcode(lib_work(), unit, root); -} - lower_unit_t *lower_unit_new(unit_registry_t *ur, lower_unit_t *parent, vcode_unit_t vunit, cover_tagging_t *cover, tree_t container) @@ -11409,7 +11307,7 @@ lower_unit_t *lower_unit_new(unit_registry_t *ur, lower_unit_t *parent, new->container = container; new->vunit = vunit; new->cover = cover; - new->registry = ur ?: (parent ? parent->registry : NULL); + new->registry = ur; vcode_state_t state; vcode_state_save(&state); @@ -11426,19 +11324,12 @@ lower_unit_t *lower_unit_new(unit_registry_t *ur, lower_unit_t *parent, new->elaborating = kind == VCODE_UNIT_INSTANCE || kind == VCODE_UNIT_PROTECTED || kind == VCODE_UNIT_PACKAGE; - if (kind != VCODE_UNIT_THUNK) - unit_registry_put(new->registry, new->name, vunit); - return new; } void lower_unit_free(lower_unit_t *lu) { - if (lu == NULL) - return; - - if (lu->vunit && !lu->finished) - lower_finished(lu); + assert(lu->finished); hash_free(lu->objects); ACLEAR(lu->free_temps); @@ -11453,9 +11344,9 @@ vcode_unit_t get_vcode(lower_unit_t *lu) //////////////////////////////////////////////////////////////////////////////// typedef enum { - UNIT_DEFERRED = 1, - UNIT_GENERATED = 2, - UNIT_FINALISED = 3, + UNIT_DEFERRED = 1, + UNIT_GENERATED = 2, + UNIT_FINALISED = 3, } unit_kind_t; typedef struct _unit_registry { @@ -11463,10 +11354,12 @@ typedef struct _unit_registry { } unit_registry_t; typedef struct { - lower_unit_t *parent; - emit_fn_t emit_fn; - lower_fn_t fn; - object_t *object; + lower_unit_t *parent; + emit_fn_t emit_fn; + lower_fn_t fn; + ident_t arena; + ptrdiff_t offset; + cover_tagging_t *cover; } deferred_unit_t; unit_registry_t *unit_registry_new(void) @@ -11489,8 +11382,20 @@ void unit_registry_free(unit_registry_t *ur) break; case UNIT_GENERATED: + { + lower_unit_t *lu = untag_pointer(value, lower_unit_t); + assert(lu->finished); + assert(lu->registry == ur); + lower_unit_free(lu); + } + break; + case UNIT_DEFERRED: - fatal_trace("cannot free this unit kind"); + { + deferred_unit_t *du = untag_pointer(value, deferred_unit_t); + free(du); + } + break; default: fatal_trace("invalid tagged pointer %p", value); @@ -11501,10 +11406,10 @@ void unit_registry_free(unit_registry_t *ur) free(ur); } -void unit_registry_put(unit_registry_t *ur, ident_t ident, vcode_unit_t vu) +void unit_registry_put(unit_registry_t *ur, lower_unit_t *lu) { - assert(hash_get(ur->map, ident) == NULL); - hash_put(ur->map, ident, tag_pointer(vu, UNIT_FINALISED)); + assert(hash_get(ur->map, lu->name) == NULL); + hash_put(ur->map, lu->name, tag_pointer(lu, UNIT_GENERATED)); } bool unit_registry_query(unit_registry_t *ur, ident_t ident) @@ -11538,10 +11443,28 @@ void unit_registry_purge(unit_registry_t *ur, ident_t prefix) } } -static void unit_registry_put_all(unit_registry_t *ur, vcode_unit_t vu) +void unit_registry_finalise(unit_registry_t *ur, lower_unit_t *lu) +{ + assert(pointer_tag(hash_get(ur->map, lu->name)) == UNIT_GENERATED); + + if (!lu->finished) + lower_finished(lu); + + if (lu->deferred > 0) + return; + + hash_put(ur->map, lu->name, tag_pointer(lu->vunit, UNIT_FINALISED)); + + lower_unit_free(lu); +} + +void unit_registry_put_all(unit_registry_t *ur, vcode_unit_t vu) { vcode_select_unit(vu); - unit_registry_put(ur, vcode_unit_name(), vu); + + ident_t ident = vcode_unit_name(); + assert(hash_get(ur->map, ident) == NULL); + hash_put(ur->map, ident, tag_pointer(vu, UNIT_FINALISED)); for (vcode_unit_t it = vcode_unit_child(vu); it; it = vcode_unit_next(it)) unit_registry_put_all(ur, it); @@ -11559,25 +11482,26 @@ vcode_unit_t unit_registry_get(unit_registry_t *ur, ident_t ident) ident_t unit_name = ident_prefix(lname, uname, '.'); tree_t unit = lib_get(lib, unit_name); - if (unit == NULL) + if (unit == NULL || !is_package(unit)) return NULL; - else if (tree_kind(unit) == T_PACKAGE && package_needs_body(unit)) { - if ((unit = body_of(unit)) == NULL) - return NULL; - } - else if (tree_kind(unit) == T_ENTITY) { - ident_t ename = ident_prefix(unit_name, well_known(W_ELAB), '.'); - if ((unit = lib_get(lib, ename)) == NULL) + + if (tree_kind(unit) == T_PACKAGE && package_needs_body(unit)) { + tree_t body = body_of(unit); + if (body == NULL) return NULL; - } - else if (!is_package(unit)) - return NULL; - vcode_unit_t root = lib_get_vcode(lib, unit); - if (root == NULL) - return NULL; + unit_registry_defer(ur, unit_name, NULL, emit_package, + lower_pack_body, NULL, tree_to_object(body)); + } + else + unit_registry_defer(ur, unit_name, NULL, emit_package, + lower_package, NULL, tree_to_object(unit)); - unit_registry_put_all(ur, root); + if (unit_name != ident) { + // We actually wanted a unit inside this package so need to + // force code generation + (void)unit_registry_get(ur, unit_name); + } if ((ptr = hash_get(ur->map, ident)) == NULL) return NULL; @@ -11588,18 +11512,33 @@ vcode_unit_t unit_registry_get(unit_registry_t *ur, ident_t ident) { deferred_unit_t *du = untag_pointer(ptr, deferred_unit_t); - vcode_select_unit(du->parent->vunit); + vcode_state_t state; + vcode_state_save(&state); - vcode_unit_t vu = (*du->emit_fn)(ident, du->object, du->parent->vunit); - tree_t container = tree_from_object(du->object); - lower_unit_t *lu = lower_unit_new(ur, du->parent, vu, NULL, container); + object_t *obj = object_from_locus(du->arena, du->offset, + lib_load_handler); - (*du->fn)(lu, du->object); + vcode_unit_t context = du->parent ? du->parent->vunit : NULL; + vcode_unit_t vu = (*du->emit_fn)(ident, obj, context); + tree_t container = tree_from_object(obj); + lower_unit_t *lu = lower_unit_new(ur, du->parent, vu, + du->cover, container); hash_put(ur->map, ident, tag_pointer(lu, UNIT_GENERATED)); - free(du); - return lu->vunit; + (*du->fn)(lu, obj); + + if (du->parent != NULL) { + assert(du->parent->deferred > 0); + du->parent->deferred--; + } + + unit_registry_finalise(ur, lu); + + vcode_state_restore(&state); + + free(du); + return vu; } case UNIT_GENERATED: @@ -11618,15 +11557,33 @@ vcode_unit_t unit_registry_get(unit_registry_t *ur, ident_t ident) void unit_registry_defer(unit_registry_t *ur, ident_t ident, lower_unit_t *parent, emit_fn_t emit_fn, - lower_fn_t fn, object_t *object) + lower_fn_t fn, cover_tagging_t *cover, + object_t *object) { - assert(hash_get(ur->map, ident) == NULL); + void *ptr = hash_get(ur->map, ident); + if (ptr == NULL) { + deferred_unit_t *du = xcalloc(sizeof(deferred_unit_t)); + du->emit_fn = emit_fn; + du->fn = fn; + du->parent = parent; + du->cover = cover; + + if (du->parent != NULL) + du->parent->deferred++; - deferred_unit_t *du = xcalloc(sizeof(deferred_unit_t)); - du->emit_fn = emit_fn; - du->fn = fn; - du->object = object; - du->parent = parent; + object_locus(object, &du->arena, &du->offset); - hash_put(ur->map, ident, tag_pointer(du, UNIT_DEFERRED)); + hash_put(ur->map, ident, tag_pointer(du, UNIT_DEFERRED)); + } +#ifdef DEBUG + else if (pointer_tag(ptr) == UNIT_DEFERRED) { + deferred_unit_t *du = untag_pointer(ptr, deferred_unit_t); + assert(du->emit_fn == emit_fn); + assert(du->fn == fn); + assert(du->cover == cover); + + object_t *o = object_from_locus(du->arena, du->offset, lib_load_handler); + assert(o == object); + } +#endif } diff --git a/src/lower.h b/src/lower.h index 141b0a6c7..577da3291 100644 --- a/src/lower.h +++ b/src/lower.h @@ -28,12 +28,15 @@ typedef vcode_unit_t (*emit_fn_t)(ident_t, object_t *, vcode_unit_t); unit_registry_t *unit_registry_new(void); void unit_registry_free(unit_registry_t *ur); vcode_unit_t unit_registry_get(unit_registry_t *ur, ident_t ident); -void unit_registry_put(unit_registry_t *ur, ident_t ident, vcode_unit_t vu); +void unit_registry_put(unit_registry_t *ur, lower_unit_t *lu); void unit_registry_defer(unit_registry_t *ur, ident_t ident, lower_unit_t *parent, emit_fn_t emit_fn, - lower_fn_t fn, object_t *object); + lower_fn_t fn, cover_tagging_t *cover, + object_t *object); void unit_registry_purge(unit_registry_t *ur, ident_t prefix); bool unit_registry_query(unit_registry_t *ur, ident_t ident); +void unit_registry_put_all(unit_registry_t *ur, vcode_unit_t vu); +void unit_registry_finalise(unit_registry_t *ur, lower_unit_t *lu); lower_unit_t *lower_unit_new(unit_registry_t *ur, lower_unit_t *parent, vcode_unit_t vunit, cover_tagging_t *cover, @@ -46,7 +49,6 @@ vcode_unit_t get_vcode(lower_unit_t *lu); vcode_reg_t lower_lvalue(lower_unit_t *lu, tree_t expr); vcode_reg_t lower_rvalue(lower_unit_t *lu, tree_t expr); -void lower_standalone_unit(unit_registry_t *ur, tree_t unit); lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, cover_tagging_t *cover, tree_t block); void lower_process(lower_unit_t *parent, tree_t proc); diff --git a/src/psl/psl-lower.c b/src/psl/psl-lower.c index d6b711259..05475a5df 100644 --- a/src/psl/psl-lower.c +++ b/src/psl/psl-lower.c @@ -101,7 +101,8 @@ static void psl_lower_state(lower_unit_t *lu, fsm_state_t *state) emit_return(VCODE_INVALID_REG); } -void psl_lower_assert(lower_unit_t *parent, psl_node_t p, ident_t label) +void psl_lower_assert(unit_registry_t *ur, lower_unit_t *parent, psl_node_t p, + ident_t label) { assert(psl_kind(p) == P_ASSERT); @@ -119,7 +120,8 @@ void psl_lower_assert(lower_unit_t *parent, psl_node_t p, ident_t label) ident_t name = ident_prefix(prefix, label, '.'); vcode_unit_t vu = emit_property(name, psl_to_object(p), context); - lower_unit_t *lu = lower_unit_new(NULL, parent, vu, NULL, NULL); + lower_unit_t *lu = lower_unit_new(ur, parent, vu, NULL, NULL); + unit_registry_put(ur, lu); vcode_type_t vcontext = vtype_context(prefix); emit_param(vcontext, vcontext, ident_new("context")); @@ -180,13 +182,13 @@ void psl_lower_assert(lower_unit_t *parent, psl_node_t p, ident_t label) } assert(pos == fsm->next_id); - lower_unit_free(lu); + unit_registry_finalise(ur, lu); psl_fsm_free(fsm); } -static void psl_lower_clock_decl(lower_unit_t *parent, psl_node_t p, - ident_t label) +static void psl_lower_clock_decl(unit_registry_t *ur, lower_unit_t *parent, + psl_node_t p, ident_t label) { vcode_state_t state; vcode_state_save(&state); @@ -203,12 +205,14 @@ static void psl_lower_clock_decl(lower_unit_t *parent, psl_node_t p, vcode_type_t vcontext = vtype_context(prefix); emit_param(vcontext, vcontext, ident_new("context")); - lower_unit_t *lu = lower_unit_new(NULL, parent, vu, NULL, NULL); + lower_unit_t *lu = lower_unit_new(ur, parent, vu, NULL, NULL); + unit_registry_put(ur, lu); vcode_reg_t clk_reg = lower_rvalue(lu, psl_tree(p)); emit_return(clk_reg); - lower_unit_free(lu); + unit_registry_finalise(ur, lu); + vcode_state_restore(&state); vcode_type_t vtrigger = vtype_trigger(); @@ -223,11 +227,12 @@ static void psl_lower_clock_decl(lower_unit_t *parent, psl_node_t p, lower_put_vcode_obj(p, var, parent); } -void psl_lower_decl(lower_unit_t *parent, psl_node_t p, ident_t label) +void psl_lower_decl(unit_registry_t *ur, lower_unit_t *parent, psl_node_t p, + ident_t label) { switch (psl_kind(p)) { case P_CLOCK_DECL: - psl_lower_clock_decl(parent, p, label); + psl_lower_clock_decl(ur, parent, p, label); break; default: fatal_at(psl_loc(p), "cannot lower PSL declaration kind %s", diff --git a/src/psl/psl-phase.h b/src/psl/psl-phase.h index 74febf37f..71080dad1 100644 --- a/src/psl/psl-phase.h +++ b/src/psl/psl-phase.h @@ -27,9 +27,11 @@ void psl_check(psl_node_t p); void psl_dump(psl_node_t p); // Convert PSL assertion to vcode unit. -void psl_lower_assert(lower_unit_t *parent, psl_node_t p, ident_t name); +void psl_lower_assert(unit_registry_t *ur, lower_unit_t *parent, psl_node_t p, + ident_t name); // Convert PSL declaration to vcode variable -void psl_lower_decl(lower_unit_t *parent, psl_node_t p, ident_t name); +void psl_lower_decl(unit_registry_t *ur, lower_unit_t *parent, psl_node_t p, + ident_t name); #endif // _PSL_PHASE_H diff --git a/src/rt/shell.c b/src/rt/shell.c index 7084ef27f..e6caeb6a4 100644 --- a/src/rt/shell.c +++ b/src/rt/shell.c @@ -1173,6 +1173,10 @@ void shell_reset(tcl_shell_t *sh, tree_t top) sh->top = top; + vcode_unit_t vu = lib_get_vcode(lib_work(), top); + if (vu != NULL) + unit_registry_put_all(sh->registry, vu); + shell_create_model(sh); sh->nsignals = count_signals(sh->root); diff --git a/src/vlog/vlog-lower.c b/src/vlog/vlog-lower.c index 34d176726..36cd94a38 100644 --- a/src/vlog/vlog-lower.c +++ b/src/vlog/vlog-lower.c @@ -371,7 +371,8 @@ static void vlog_driver_cb(vlog_node_t v, void *context) } } -static void vlog_lower_always(lower_unit_t *parent, vlog_node_t stmt) +static void vlog_lower_always(unit_registry_t *ur, lower_unit_t *parent, + vlog_node_t stmt) { vcode_unit_t context = get_vcode(parent); vcode_select_unit(context); @@ -382,7 +383,8 @@ static void vlog_lower_always(lower_unit_t *parent, vlog_node_t stmt) vcode_block_t start_bb = emit_block(); assert(start_bb == 1); - lower_unit_t *lu = lower_unit_new(NULL, parent, vu, NULL, NULL); + lower_unit_t *lu = lower_unit_new(ur, parent, vu, NULL, NULL); + unit_registry_put(ur, lu); vlog_visit(stmt, vlog_driver_cb, lu); @@ -403,10 +405,11 @@ static void vlog_lower_always(lower_unit_t *parent, vlog_node_t stmt) emit_wait(start_bb, VCODE_INVALID_REG); - lower_unit_free(lu); + unit_registry_finalise(ur, lu); } -static void vlog_lower_initial(lower_unit_t *parent, vlog_node_t stmt) +static void vlog_lower_initial(unit_registry_t *ur, lower_unit_t *parent, + vlog_node_t stmt) { vcode_unit_t context = get_vcode(parent); vcode_select_unit(context); @@ -417,7 +420,8 @@ static void vlog_lower_initial(lower_unit_t *parent, vlog_node_t stmt) vcode_block_t start_bb = emit_block(); assert(start_bb == 1); - lower_unit_t *lu = lower_unit_new(NULL, parent, vu, NULL, NULL); + lower_unit_t *lu = lower_unit_new(ur, parent, vu, NULL, NULL); + unit_registry_put(ur, lu); emit_return(VCODE_INVALID_REG); @@ -427,20 +431,21 @@ static void vlog_lower_initial(lower_unit_t *parent, vlog_node_t stmt) emit_wait(start_bb, VCODE_INVALID_REG); - lower_unit_free(lu); + unit_registry_finalise(ur, lu); } -static void vlog_lower_concurrent(lower_unit_t *parent, vlog_node_t scope) +static void vlog_lower_concurrent(unit_registry_t *ur, lower_unit_t *parent, + vlog_node_t scope) { const int nstmts = vlog_stmts(scope); for (int i = 0; i < nstmts; i++) { vlog_node_t s = vlog_stmt(scope, i); switch (vlog_kind(s)) { case V_ALWAYS: - vlog_lower_always(parent, s); + vlog_lower_always(ur, parent, s); break; case V_INITIAL: - vlog_lower_initial(parent, s); + vlog_lower_initial(ur, parent, s); break; default: CANNOT_HANDLE(s); @@ -465,6 +470,7 @@ void vlog_lower(unit_registry_t *ur, tree_t wrap, lower_unit_t *parent) vcode_unit_t vu = emit_instance(name, tree_to_object(wrap), context); lower_unit_t *lu = lower_unit_new(ur, parent, vu, NULL, NULL); + unit_registry_put(ur, lu); vlog_lower_decls(lu, root); vlog_lower_port_map(lu, root, wrap); @@ -473,7 +479,7 @@ void vlog_lower(unit_registry_t *ur, tree_t wrap, lower_unit_t *parent) lower_finished(lu); - vlog_lower_concurrent(lu, root); + vlog_lower_concurrent(ur, lu, root); - lower_unit_free(lu); + unit_registry_finalise(ur, lu); } diff --git a/test/lower/conv1.vhd b/test/lower/conv1.vhd index ab8bf209d..ae607c6d7 100644 --- a/test/lower/conv1.vhd +++ b/test/lower/conv1.vhd @@ -1,13 +1,14 @@ package conv1 is -end package; - -package body conv1 is type rec is record x : integer; end record; type rec_array is array (natural range <>) of rec; + function get(a : rec_array) return real; +end package; + +package body conv1 is function get(a : rec_array) return real is begin return real(a(0).x); -- Must reify a(0).x diff --git a/test/lower/extern1.vhd b/test/lower/extern1.vhd index 6c084c197..b7ed908ce 100644 --- a/test/lower/extern1.vhd +++ b/test/lower/extern1.vhd @@ -9,6 +9,7 @@ package complex is constant MATH_CBASE_J : COMPLEX := COMPLEX'(0.0, 1.0); constant MATH_CZERO : COMPLEX := COMPLEX'(0.0, 0.0); + function SQRT(Z: in COMPLEX ) return COMPLEX; end package; package body complex is diff --git a/test/lower/issue158.vhd b/test/lower/issue158.vhd index be949dda5..9ed8598ed 100644 --- a/test/lower/issue158.vhd +++ b/test/lower/issue158.vhd @@ -1,4 +1,5 @@ package cannot_return_safety_check_pkg is + impure function fun return string; end package cannot_return_safety_check_pkg; package body cannot_return_safety_check_pkg is diff --git a/test/lower/issue164.vhd b/test/lower/issue164.vhd index a4267da18..4f24866c5 100644 --- a/test/lower/issue164.vhd +++ b/test/lower/issue164.vhd @@ -1,4 +1,6 @@ package issue164 is + procedure same_name(variable var : out integer); + impure function same_name return integer; end package; package body issue164 is diff --git a/test/lower/sum.vhd b/test/lower/sum.vhd index 5498e8d26..0a2a57d49 100644 --- a/test/lower/sum.vhd +++ b/test/lower/sum.vhd @@ -1,10 +1,10 @@ package sumpkg is + type int_vector is array (natural range <>) of integer; + function sum(a : int_vector) return integer; end package; package body sumpkg is - type int_vector is array (natural range <>) of integer; - function sum(a : int_vector) return integer is variable result : integer := 0; begin diff --git a/test/lower/synopsys1.vhd b/test/lower/synopsys1.vhd index 37e8d06ac..f30248a43 100644 --- a/test/lower/synopsys1.vhd +++ b/test/lower/synopsys1.vhd @@ -3,6 +3,9 @@ package synopsys1 is type line is access string; type side is (left, right); subtype width is natural; + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); end package; package body synopsys1 is diff --git a/test/lower/vital1.vhd b/test/lower/vital1.vhd index 72821d2f8..6d91f4dce 100644 --- a/test/lower/vital1.vhd +++ b/test/lower/vital1.vhd @@ -1,4 +1,8 @@ package vital_timing is + PROCEDURE VitalSetupHoldCheck ( + SIGNAL TestSignal : IN bit_vector + + ); end package; PACKAGE BODY VITAL_Timing IS diff --git a/test/lower/vital2.vhd b/test/lower/vital2.vhd index 861e63a0e..42a343c59 100644 --- a/test/lower/vital2.vhd +++ b/test/lower/vital2.vhd @@ -1,8 +1,4 @@ package vital_timing is -end package; - -PACKAGE BODY VITAL_Timing IS - -- Types for fields of VitalTimingDataType TYPE VitalTimeArrayT IS ARRAY (INTEGER RANGE <>) OF TIME; TYPE VitalTimeArrayPT IS ACCESS VitalTimeArrayT; @@ -23,6 +19,15 @@ PACKAGE BODY VITAL_Timing IS SetupEnA : VitalBoolArrayPT; END RECORD; + PROCEDURE VitalSetupHoldCheck ( + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN bit_vector; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE --IR252 3/23/98 + + ); +end package; + +PACKAGE BODY VITAL_Timing IS PROCEDURE VitalSetupHoldCheck ( VARIABLE TimingData : INOUT VitalTimingDataType; SIGNAL TestSignal : IN bit_vector; diff --git a/test/simp/allsens.vhd b/test/simp/allsens.vhd index 2e941ac36..8ec9fed5d 100644 --- a/test/simp/allsens.vhd +++ b/test/simp/allsens.vhd @@ -56,7 +56,7 @@ begin begin case x is when '0' => - v(0) <= v(1); + v(2) <= v(1); when '1' => proc(y); end case; diff --git a/test/simp/order1.vhd b/test/simp/order1.vhd index 809e93267..ea56e25cd 100644 --- a/test/simp/order1.vhd +++ b/test/simp/order1.vhd @@ -6,5 +6,5 @@ end package; package order1 is type t is (C, B, A); -- Redefine t type t_vec is array (1 to 2) of t; - constant x : boolean := t_vec'(A, A) < t_vec'(C, C); -- Should not fold! + constant x : boolean := t_vec'(A, A) < t_vec'(C, C); -- False end package; diff --git a/test/test_bounds.c b/test/test_bounds.c index 7dbcb2d73..06809cec0 100644 --- a/test/test_bounds.c +++ b/test/test_bounds.c @@ -394,10 +394,8 @@ START_TEST(test_issue98) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -440,10 +438,8 @@ START_TEST(test_aggregate) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -453,13 +449,8 @@ START_TEST(test_osvvm1) set_standard(STD_08); input_from_file(TESTDIR "/bounds/osvvm1.vhd"); - tree_t p = parse_check_and_simplify(T_PACKAGE, -1); - bounds_check(p); - - tree_t b = parse_check_and_simplify(T_PACK_BODY); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); - bounds_check(b); fail_if_errors(); } END_TEST @@ -475,10 +466,8 @@ START_TEST(test_range1) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -494,10 +483,8 @@ START_TEST(test_case2) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -508,7 +495,6 @@ START_TEST(test_issue477a) input_from_file(TESTDIR "/bounds/issue477a.vhd"); tree_t p = parse_check_and_simplify(T_PACKAGE); - bounds_check(p); tree_t d = search_decls(p, ident_new("C_DATA_VERSION"), 0); fail_if(d == NULL); @@ -535,10 +521,8 @@ START_TEST(test_issue477b) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_PACKAGE); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_PACKAGE); - bounds_check(a); check_expected_errors(); } END_TEST @@ -553,10 +537,8 @@ START_TEST(test_case3) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -573,10 +555,8 @@ START_TEST(test_driver1) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -585,10 +565,8 @@ START_TEST(test_nullrange) { input_from_file(TESTDIR "/bounds/nullrange.vhd"); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); fail_if_errors(); } END_TEST @@ -604,10 +582,8 @@ START_TEST(test_issue617) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST @@ -623,10 +599,8 @@ START_TEST(test_issue734) }; expect_errors(expect); - tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); - fail_unless(error_count() == 0); + parse_check_and_simplify(T_ENTITY, T_ARCH); - bounds_check(a); check_expected_errors(); } END_TEST diff --git a/test/test_elab.c b/test/test_elab.c index f7b635354..b6d980a82 100644 --- a/test/test_elab.c +++ b/test/test_elab.c @@ -303,7 +303,7 @@ START_TEST(test_issue159) lib_t other = lib_tmp("dummy"); lib_set_work(other); - parse_check_simplify_and_lower(T_PACKAGE, T_ENTITY, T_ARCH, -1); + parse_check_and_simplify(T_PACKAGE, T_ENTITY, T_ARCH, -1); fail_if_errors(); lib_set_work(work); @@ -318,8 +318,7 @@ START_TEST(test_issue175) lib_t lib2 = lib_tmp("lib2"); lib_set_work(lib2); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, T_PACKAGE, - T_PACK_BODY, -1); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, T_PACKAGE, T_PACK_BODY, -1); fail_if_errors(); lib_t lib = lib_tmp("lib"); diff --git a/test/test_jit.c b/test/test_jit.c index c619ad561..685bd0300 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -107,7 +107,7 @@ START_TEST(test_add1) { input_from_file(TESTDIR "/jit/add1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -128,7 +128,7 @@ START_TEST(test_fact) { input_from_file(TESTDIR "/jit/fact.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -148,7 +148,7 @@ START_TEST(test_sum) { input_from_file(TESTDIR "/jit/sum.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -199,7 +199,7 @@ START_TEST(test_context1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -242,8 +242,7 @@ START_TEST(test_record1) { input_from_file(TESTDIR "/jit/record1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, - T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -267,8 +266,7 @@ START_TEST(test_record2) { input_from_file(TESTDIR "/jit/record2.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, - T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -292,8 +290,7 @@ START_TEST(test_record3) { input_from_file(TESTDIR "/jit/record3.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, - T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -365,7 +362,7 @@ START_TEST(test_overflow) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -415,7 +412,7 @@ START_TEST(test_record4) { input_from_file(TESTDIR "/jit/record4.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -449,7 +446,7 @@ START_TEST(test_access1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -493,7 +490,7 @@ START_TEST(test_array1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -549,7 +546,7 @@ START_TEST(test_relop1) { input_from_file(TESTDIR "/jit/relop1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -582,9 +579,9 @@ START_TEST(test_proc1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, - T_PACKAGE, T_PACK_BODY, - T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, + T_PACKAGE, T_PACK_BODY, + T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -604,7 +601,7 @@ START_TEST(test_packsignal) { input_from_file(TESTDIR "/jit/packsignal.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -626,7 +623,7 @@ START_TEST(test_unreachable) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -655,7 +652,7 @@ START_TEST(test_arith1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -740,7 +737,7 @@ START_TEST(test_assert1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -762,7 +759,7 @@ START_TEST(test_case1) { input_from_file(TESTDIR "/jit/case1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -790,7 +787,7 @@ START_TEST(test_real1) { input_from_file(TESTDIR "/jit/real1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -808,7 +805,7 @@ START_TEST(test_prot1) input_from_file(TESTDIR "/jit/prot1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -932,7 +929,7 @@ START_TEST(test_range1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -972,7 +969,7 @@ START_TEST(test_trace1) diag_set_consumer(trace1_diag_fn, NULL); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -992,7 +989,7 @@ START_TEST(test_issue496) input_from_file(TESTDIR "/jit/issue496.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACKAGE); + parse_check_and_simplify(T_PACKAGE, T_PACKAGE); jit_t *j = jit_new(get_registry()); @@ -1063,7 +1060,7 @@ START_TEST(test_value1) }; expect_errors(expect); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -1461,7 +1458,7 @@ START_TEST(test_issue575) { input_from_file(TESTDIR "/jit/issue575.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); @@ -1771,7 +1768,7 @@ START_TEST(test_tlab1) input_from_file(TESTDIR "/jit/tlab1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); jit_t *j = jit_new(get_registry()); diff --git a/test/test_lower.c b/test/test_lower.c index 01a12ed83..285722d4e 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -355,6 +355,7 @@ static vcode_unit_t find_unit_for(tree_t decl) vcode_unit_t vu = unit_registry_get(ur, tree_ident2(decl)); if (vu == NULL) fail("missing vcode unit for %s", istr(tree_ident2(decl))); + return vu; } @@ -868,7 +869,7 @@ START_TEST(test_pack1) { input_from_file(TESTDIR "/lower/pack1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t v0 = find_unit("WORK.PACK1.ADD1(I)I"); vcode_select_unit(v0); @@ -2149,6 +2150,8 @@ START_TEST(test_issue136) fail_if(body == NULL); fail_unless(tree_kind(body) == T_PROT_BODY); + (void)find_unit("WORK.CANNOT_RETURN_SAFETY_CHECK_PKG.RECORD_RETURNER_T"); + vcode_unit_t v0 = find_unit_for(tree_decl(body, 1)); vcode_select_unit(v0); @@ -2233,12 +2236,27 @@ START_TEST(test_issue158) { input_from_file(TESTDIR "/lower/issue158.vhd"); - unit_registry_t *ur = get_registry(); - jit_t *jit = jit_new(ur); - tree_t p = parse_and_check(T_PACKAGE, T_PACK_BODY); - simplify_local(p, jit, ur); - lower_standalone_unit(get_registry(), p); - jit_free(jit); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); + + vcode_unit_t vu = find_unit("WORK.CANNOT_RETURN_SAFETY_CHECK_PKG.FUN()S"); + vcode_select_unit(vu); + + EXPECT_BB(0) = { + { VCODE_OP_NULL }, + { VCODE_OP_STORE, .name = "VALUE" }, + { VCODE_OP_CONTEXT_UPREF, .hops = 1 }, + { VCODE_OP_INDEX, .name = "VALUE" }, + { VCODE_OP_FCALL, .func = "WORK.CANNOT_RETURN_SAFETY_CHECK_PKG.PROC(" + "46WORK.CANNOT_RETURN_SAFETY_CHECK_PKG.STRING_PTR)" }, + { VCODE_OP_LOAD, .name = "VALUE" }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_NULL_CHECK }, + { VCODE_OP_ALL }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_RETURN }, + }; + + CHECK_BB(0); } END_TEST @@ -2270,7 +2288,6 @@ START_TEST(test_issue164) input_from_file(TESTDIR "/lower/issue164.vhd"); tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); - lower_standalone_unit(get_registry(), p); vcode_select_unit(find_unit_for(tree_decl(p, 0))); fail_unless(icmp(vcode_unit_name(), "WORK.ISSUE164.SAME_NAME(I)")); @@ -2693,7 +2710,6 @@ START_TEST(test_dealloc) input_from_file(TESTDIR "/lower/dealloc.vhd"); tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); - lower_standalone_unit(get_registry(), p); vcode_unit_t v1 = find_unit_for(tree_decl(p, 1)); vcode_select_unit(v1); @@ -3038,7 +3054,6 @@ START_TEST(test_tounsigned) input_from_file(TESTDIR "/lower/tounsigned.vhd"); tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); - lower_standalone_unit(get_registry(), p); vcode_unit_t v0 = find_unit_for(tree_decl(p, 0)); vcode_select_unit(v0); @@ -3235,9 +3250,8 @@ START_TEST(test_sum) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); - tree_t f = tree_decl(p, 11); + tree_t f = search_decls(p, ident_new("SUM"), 0); fail_unless(tree_kind(f) == T_FUNC_BODY); vcode_unit_t v0 = find_unit_for(f); @@ -3290,7 +3304,6 @@ START_TEST(test_extern1) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); tree_t f = tree_decl(p, 0); fail_unless(tree_kind(f) == T_FUNC_BODY); @@ -3314,7 +3327,6 @@ START_TEST(test_synopsys1) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); tree_t f = search_decls(p, ident_new("WRITE"), 0); fail_if(f == NULL); @@ -3379,7 +3391,6 @@ START_TEST(test_access2) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); tree_t f = search_decls(p, ident_new("GET_FRESH"), 0); fail_if(f == NULL); @@ -3416,7 +3427,6 @@ START_TEST(test_vital1) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); tree_t f = search_decls(p, ident_new("VITALSETUPHOLDCHECK"), 0); fail_if(f == NULL); @@ -3500,7 +3510,6 @@ START_TEST(test_incomplete) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); vcode_unit_t v0 = find_unit("WORK.P"); vcode_select_unit(v0); @@ -3526,7 +3535,6 @@ START_TEST(test_issue389) tree_t p = parse_check_and_simplify(T_PACKAGE); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); vcode_unit_t v0 = find_unit("WORK.COMMON"); vcode_select_unit(v0); @@ -3554,7 +3562,6 @@ START_TEST(test_const1) tree_t b = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(b); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), b); { vcode_unit_t v1 = find_unit("WORK.ISSUEH"); @@ -3606,8 +3613,6 @@ START_TEST(test_vital2) bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); - tree_t f = search_decls(p, ident_new("VITALSETUPHOLDCHECK"), 0); fail_if(f == NULL); @@ -3660,7 +3665,6 @@ START_TEST(test_conv1) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); tree_t f = search_decls(p, ident_new("GET"), 0); fail_if(f == NULL); @@ -3833,7 +3837,9 @@ START_TEST(test_protupref) input_from_file(TESTDIR "/lower/protupref.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); + + (void)find_unit("WORK.ALERTLOGPKG.ALERTLOGSTRUCTPTYPE"); vcode_unit_t vu = find_unit( "WORK.ALERTLOGPKG.ALERTLOGSTRUCTPTYPE.ALERT(" @@ -3860,7 +3866,7 @@ START_TEST(test_closefile) { input_from_file(TESTDIR "/lower/closefile.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t vu = find_unit("WORK.FILEPACK.TEST"); vcode_select_unit(vu); @@ -4304,7 +4310,19 @@ START_TEST(test_issue444) { input_from_file(TESTDIR "/lower/issue444.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); + + vcode_unit_t vu1 = find_unit("WORK.ISSUE444.PROC(I)"); + vcode_select_unit(vu1); + + ck_assert_int_eq(vcode_count_vars(), 2); + fail_unless(vcode_var_flags(1) & VAR_TEMP); + + vcode_unit_t vu2 = find_unit("WORK.ISSUE444.PROC(I).T$value"); + vcode_select_unit(vu2); + + ck_assert_int_eq(vcode_count_vars(), 1); + fail_unless(vcode_var_flags(0) & VAR_TEMP); fail_if_errors(); } @@ -4315,7 +4333,50 @@ START_TEST(test_vunit1) set_standard(STD_02); input_from_file(TESTDIR "/lower/vunit1.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); + + (void)find_unit("WORK.STRING_PTR_PKG.PROT_STORAGE_T"); + + vcode_unit_t vu = find_unit("WORK.STRING_PTR_PKG.PROT_STORAGE_T.SET(NPC)"); + vcode_select_unit(vu); + + EXPECT_BB(3) = { + { VCODE_OP_VAR_UPREF, .name = "ST", .hops = 1 }, + { VCODE_OP_RECORD_REF, .field = 5 }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_NULL_CHECK }, + { VCODE_OP_ALL }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_INDEX, .name = "S" }, + { VCODE_OP_RECORD_REF, .field = 0 }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_UARRAY_LEFT }, + { VCODE_OP_CAST }, + { VCODE_OP_UARRAY_RIGHT }, + { VCODE_OP_CAST }, + { VCODE_OP_UARRAY_DIR }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_INDEX_CHECK }, + { VCODE_OP_SUB }, + { VCODE_OP_SUB }, + { VCODE_OP_SELECT }, + { VCODE_OP_CAST }, + { VCODE_OP_UNWRAP }, + { VCODE_OP_ARRAY_REF }, + { VCODE_OP_LOAD_INDIRECT }, + { VCODE_OP_DEBUG_LOCUS }, + { VCODE_OP_NULL_CHECK }, + { VCODE_OP_ALL }, + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_SUB }, + { VCODE_OP_CAST }, + { VCODE_OP_ARRAY_REF }, + { VCODE_OP_STORE_INDIRECT }, + { VCODE_OP_JUMP, .target = 1 }, + }; + + CHECK_BB(3); fail_if_errors(); } @@ -4325,7 +4386,7 @@ START_TEST(test_vunit2) { input_from_file(TESTDIR "/lower/vunit2.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t vu = find_unit( "WORK.VUNIT2.GET_ONE(N)19WORK.VUNIT2.INT_PTR"); @@ -4355,7 +4416,7 @@ START_TEST(test_vunit3) { input_from_file(TESTDIR "/lower/vunit3.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t vu = find_unit("WORK.VUNIT3.ALLOC_REG()19WORK.VUNIT3.REC_PTR"); vcode_select_unit(vu); @@ -4381,7 +4442,7 @@ START_TEST(test_vunit4) { input_from_file(TESTDIR "/lower/vunit4.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t vu = find_unit("WORK.VUNIT4.GET_REC(N)15WORK.VUNIT4.REC"); vcode_select_unit(vu); @@ -4647,7 +4708,7 @@ START_TEST(test_issue476) input_from_file(TESTDIR "/lower/issue476.vhd"); - parse_check_simplify_and_lower(T_PACKAGE); + parse_check_and_simplify(T_PACKAGE); fail_if_errors(); } @@ -4659,7 +4720,7 @@ START_TEST(test_issue478) input_from_file(TESTDIR "/lower/issue478.vhd"); - parse_check_simplify_and_lower(T_PACKAGE); + parse_check_and_simplify(T_PACKAGE); vcode_unit_t vu = find_unit("WORK.TEST_PKG"); vcode_select_unit(vu); @@ -4765,7 +4826,7 @@ START_TEST(test_bigarray) { input_from_file(TESTDIR "/lower/bigarray.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t vu = find_unit("WORK.BIGARRAY.GET_ARRAY()21WORK.BIGARRAY.INT_VEC"); @@ -5018,7 +5079,6 @@ START_TEST(test_copy1) tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); bounds_check(p); fail_if(error_count() > 0); - lower_standalone_unit(get_registry(), p); tree_t f = search_decls(p, ident_new("TEST_COPY"), 0); fail_if(f == NULL); @@ -5089,7 +5149,7 @@ START_TEST(test_issue725) input_from_file(TESTDIR "/lower/issue725.vhd"); - parse_check_simplify_and_lower(T_PACKAGE); + parse_check_and_simplify(T_PACKAGE); fail_if_errors(); } @@ -5101,7 +5161,7 @@ START_TEST(test_cond2) input_from_file(TESTDIR "/lower/cond2.vhd"); - parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY); + parse_check_and_simplify(T_PACKAGE, T_PACK_BODY); vcode_unit_t vu = find_unit("WORK.COND2.DUMMY_LOOP(Q)"); vcode_select_unit(vu); diff --git a/test/test_simp.c b/test/test_simp.c index 508c377ab..8fb623586 100644 --- a/test/test_simp.c +++ b/test/test_simp.c @@ -313,8 +313,8 @@ START_TEST(test_ffold) { input_from_file(TESTDIR "/simp/ffold.vhd"); - tree_t a = parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, - T_ENTITY, T_ARCH); + tree_t a = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, + T_ENTITY, T_ARCH); fail_if_errors(); tree_t b = tree_stmt(a, 0); @@ -363,8 +363,8 @@ START_TEST(test_ffold2) { input_from_file(TESTDIR "/simp/ffold2.vhd"); - tree_t a = parse_check_simplify_and_lower(T_PACKAGE, T_PACK_BODY, - T_ENTITY, T_ARCH); + tree_t a = parse_check_and_simplify(T_PACKAGE, T_PACK_BODY, + T_ENTITY, T_ARCH); tree_t b = tree_stmt(a, 0); fail_unless(tree_kind(b) == T_BLOCK); @@ -1055,11 +1055,11 @@ START_TEST(test_order1) { input_from_file(TESTDIR "/simp/order1.vhd"); - tree_t p = parse_check_simplify_and_lower(T_PACKAGE, T_PACKAGE); + tree_t p = parse_check_and_simplify(T_PACKAGE, T_PACKAGE); tree_t x = search_decls(p, ident_new("X"), 0); fail_if(x == NULL); - fail_unless(tree_kind(tree_value(x)) == T_FCALL); + fail_unless(folded_b(tree_value(x), false)); fail_if_errors(); } @@ -1069,8 +1069,8 @@ START_TEST(test_genmap) { input_from_file(TESTDIR "/simp/genmap.vhd"); - tree_t a = parse_check_simplify_and_lower(T_ENTITY, T_PACKAGE, T_ENTITY, - T_ENTITY, T_ARCH); + tree_t a = parse_check_and_simplify(T_ENTITY, T_PACKAGE, T_ENTITY, + T_ENTITY, T_ARCH); tree_t u1 = tree_stmt(a, 0); fail_unless(tree_genmaps(u1) == 2); diff --git a/test/test_util.c b/test/test_util.c index b007cb965..59f69c20e 100644 --- a/test/test_util.c +++ b/test/test_util.c @@ -137,9 +137,6 @@ tree_t run_elab(void) bounds_check(t); fail_if(error_count() > 0); - if (unit_needs_cgen(t)) - lower_standalone_unit(ur, t); - const tree_kind_t kind = tree_kind(t); if (kind == T_ENTITY || kind == T_CONFIGURATION) last_ent = t; @@ -152,8 +149,7 @@ tree_t run_elab(void) return top; } -tree_t _parse_and_check(const tree_kind_t *array, int num, - bool simp, bool lower) +tree_t _parse_and_check(const tree_kind_t *array, int num, bool simp) { jit_t *jit = NULL; tree_t last = NULL; @@ -182,13 +178,7 @@ tree_t _parse_and_check(const tree_kind_t *array, int num, unit_registry_purge(ur, tree_ident(last)); simplify_local(last, jit, ur); - } - - if (lower && error_count() == 0) { bounds_check(last); - - if (unit_needs_cgen(last)) - lower_standalone_unit(get_registry(), last); } } diff --git a/test/test_util.h b/test/test_util.h index efa21a023..7c98ee18f 100644 --- a/test/test_util.h +++ b/test/test_util.h @@ -54,17 +54,12 @@ #define parse_and_check(...) ({ \ static const tree_kind_t array[] = { __VA_ARGS__ }; \ - _parse_and_check(array, ARRAY_LEN(array), false, false); \ + _parse_and_check(array, ARRAY_LEN(array), false); \ }) #define parse_check_and_simplify(...) ({ \ static const tree_kind_t array[] = { __VA_ARGS__ }; \ - _parse_and_check(array, ARRAY_LEN(array), true, false); \ - }) - -#define parse_check_simplify_and_lower(...) ({ \ - static const tree_kind_t array[] = { __VA_ARGS__ }; \ - _parse_and_check(array, ARRAY_LEN(array), true, true); \ + _parse_and_check(array, ARRAY_LEN(array), true); \ }) typedef struct { @@ -79,7 +74,6 @@ TCase *nvc_unit_test(void); int nvc_run_test(Suite *s); unit_registry_t *get_registry(void); tree_t run_elab(void); -tree_t _parse_and_check(const tree_kind_t *array, int num, - bool simp, bool lower); +tree_t _parse_and_check(const tree_kind_t *array, int num, bool simp); #endif // _TEST_UTIL_H