From 8af50e5544f51dbae4c91adadf235437b0ffe49a Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 27 Jun 2023 20:39:55 +0100 Subject: [PATCH] WIP lazy lowering --- src/common.c | 7 +- src/lower.c | 291 +++++++++++++++++++++------------------------------ 2 files changed, 126 insertions(+), 172 deletions(-) diff --git a/src/common.c b/src/common.c index 42a00f1e..cd6a6c86 100644 --- a/src/common.c +++ b/src/common.c @@ -2202,8 +2202,11 @@ 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); + //if (error_count() == base_errors && unit_needs_cgen(unit)) { + // unit_registry_t *ur = unit_registry_new(); + // lower_standalone_unit(ur, unit); + // unit_registry_free(ur); + //} } else lib_put_error(work, unit); diff --git a/src/lower.c b/src/lower.c index f7a0187c..e7c39724 100644 --- a/src/lower.c +++ b/src/lower.c @@ -127,8 +127,8 @@ static lower_mode_t mode = LOWER_NORMAL; 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); @@ -142,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, @@ -7861,31 +7861,17 @@ 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) { + tree_t decl = tree_from_object(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; - - 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); + 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), @@ -7907,8 +7893,7 @@ static void lower_image_helper(lower_unit_t *parent, tree_t decl) type_kind_str(type_kind(type))); } - lower_unit_free(lu); - vcode_state_restore(&state); + lower_finished(lu); } static vcode_reg_t lower_enum_value_helper(lower_unit_t *lu, type_t type, @@ -8197,32 +8182,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"), '$'); - - if (unit_registry_query(parent->registry, func)) - return; - - vcode_state_t state; - vcode_state_save(&state); + tree_t decl = tree_from_object(obj); - 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(); @@ -8230,7 +8199,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; @@ -8242,14 +8211,14 @@ 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_kind_str(type_kind(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); + lower_finished(lu); } static void lower_resolved_helper(lower_unit_t *parent, tree_t decl) @@ -8567,11 +8536,25 @@ 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); + object_t *obj = tree_to_object(decl); + ident_t id = type_ident(type); + + 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, obj); + + ident_t value = ident_prefix(id, ident_new("value"), '$'); + unit_registry_defer(lu->registry, value, lu, emit_function, + lower_value_helper, obj); + } + + lower_resolved_helper(lu, decl); + lower_copy_helper(lu, decl); + lower_new_helper(lu, decl); + } break; case T_FUNC_DECL: @@ -8647,35 +8630,48 @@ static void lower_decls(lower_unit_t *lu, tree_t scope) for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(scope, i); const tree_kind_t kind = tree_kind(d); - if (mode == LOWER_THUNK && kind == T_SIGNAL_DECL) - continue; - else if (is_subprogram(d) || kind == T_PROT_BODY) - continue; - else - lower_decl(lu, d); - } - - for (int i = 0; i < ndecls; i++) { - tree_t d = tree_decl(scope, i); - const tree_kind_t kind = tree_kind(d); - if (!is_subprogram(d) && kind != T_PROT_BODY) - continue; - - vcode_block_t bb = vcode_active_block(); - 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, + tree_to_object(d)); + break; case T_PROC_INST: - case T_PROC_BODY: lower_proc_body(lu, d); break; + case T_PROC_BODY: + { + const bool never_waits = !!(tree_flags(d) & TREE_F_NEVER_WAITS); + unit_registry_defer(lu->registry, tree_ident2(d), lu, + never_waits ? emit_function : emit_procedure, + lower_proc_body, tree_to_object(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_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; - vcode_select_unit(lu->vunit); - vcode_select_block(bb); + unit_registry_defer(lu->registry, tree_ident2(d), + lu, emit_function, lower_predef, + tree_to_object(d)); + } + break; + case T_SIGNAL_DECL: + if (mode == LOWER_THUNK) + continue; + // Fall-through + default: + lower_decl(lu, d); + break; + } } + } static bool lower_has_subprograms(tree_t scope) @@ -9721,33 +9717,19 @@ 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; - - ident_t name = tree_ident2(decl); - if (unit_registry_query(parent->registry, name)) - return; - + tree_t decl = tree_from_object(obj); 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)) { + const subprogram_kind_t kind = tree_subkind(decl); + switch (kind) { case S_ARRAY_EQ: lower_predef_array_cmp(lu, decl, VCODE_CMP_EQ); break; @@ -9824,44 +9806,23 @@ static void lower_predef(lower_unit_t *parent, tree_t decl) break; } - lower_unit_free(lu); + lower_finished(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); - - 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(); - - 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); + vcode_type_t vcontext = vtype_context(lu->parent->name); emit_param(vcontext, vcontext, ident_new("context")); if (tree_kind(body) == T_PROC_INST) lower_generics(lu, body); const bool has_subprograms = lower_has_subprograms(body); - lower_subprogram_ports(lu, body, has_subprograms || !never_waits); + const bool is_procedure = vcode_unit_kind() == VCODE_UNIT_PROCEDURE; + lower_subprogram_ports(lu, body, has_subprograms || is_procedure); lower_decls(lu, body); @@ -9874,36 +9835,25 @@ 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); + //lower_unit_free(lu); + lower_finished(lu); } -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); + printf("@@@ %p\n", lu->parent); + printf("---> %s\n", istr(lu->parent->name)); + 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) @@ -10026,6 +9976,8 @@ void lower_process(lower_unit_t *parent, tree_t proc) ident_t name = ident_prefix(vcode_unit_name(), label, '.'); vcode_unit_t vu = emit_process(name, tree_to_object(proc), parent->vunit); + unit_registry_put(parent->registry, name, vu); + // The code generator assumes the first state starts at block number // one. Allocate it here in case lowering the declarations generates // additional basic blocks. @@ -11324,6 +11276,8 @@ lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, vcode_unit_t vu = emit_instance(name, tree_to_object(block), parent ? parent->vunit : NULL); + unit_registry_put(ur, name, vu); + lower_unit_t *lu = lower_unit_new(ur, parent, vu, cover, block); cover_push_scope(cover, block); @@ -11393,9 +11347,6 @@ 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; } @@ -11518,36 +11469,36 @@ vcode_unit_t unit_registry_get(unit_registry_t *ur, ident_t ident) { void *ptr = hash_get(ur->map, ident); if (ptr == NULL) { - ident_t it = ident; - ident_t lname = ident_walk_selected(&it); - ident_t uname = ident_walk_selected(&it); + tree_t pack = lib_get_qualified(ident); + if (pack == NULL) + return NULL; - lib_t lib = lib_require(lname); + printf("got unit %p %s\n", pack, tree_kind_str(tree_kind(pack))); - ident_t unit_name = ident_prefix(lname, uname, '.'); - tree_t unit = lib_get(lib, unit_name); - if (unit == NULL) - 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) - return NULL; - } - else if (!is_package(unit)) - return NULL; + assert(is_package(pack)); + assert(!is_uninstantiated_package(pack)); - vcode_unit_t root = lib_get_vcode(lib, unit); - if (root == NULL) - return NULL; + tree_t body = NULL; + if (tree_kind(pack) == T_PACKAGE && package_needs_body(pack)) + body = body_of(pack); - unit_registry_put_all(ur, root); + object_t *obj = tree_to_object(pack); + vcode_unit_t vu = emit_package(tree_ident(pack), obj, NULL); + lower_unit_t *lu = lower_unit_new(ur, NULL, vu, NULL, body ?: pack); - if ((ptr = hash_get(ur->map, ident)) == NULL) - return NULL; + lower_dependencies(pack, NULL); + lower_generics(lu, pack); + lower_decls(lu, pack); + + if (body != NULL) + lower_decls(lu, body); + + emit_return(VCODE_INVALID_REG); + + lower_finished(lu); + + hash_put(ur->map, ident, tag_pointer(lu, UNIT_GENERATED)); + return vu; } switch (pointer_tag(ptr)) { -- 2.39.2