From 43cc1a753b87c28c065b21ea1521fe45ba36cdf0 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 27 Jun 2026 02:33:17 +0300 Subject: [PATCH] v3: fix self host --- vlib/v3/gen/c/struct.v | 5 +++- vlib/v3/markused/markused.v | 44 +++++++++++++++++++----------- vlib/v3/tests/parallel_cgen_test.v | 26 ++++++++++++++++++ 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/vlib/v3/gen/c/struct.v b/vlib/v3/gen/c/struct.v index 1208db772..15647e741 100644 --- a/vlib/v3/gen/c/struct.v +++ b/vlib/v3/gen/c/struct.v @@ -1066,7 +1066,10 @@ fn (g &FlatGen) struct_init_resolved_decl_name(type_name string) string { return info.full_name } qname := g.tc.qualify_name(type_name) - return if qname in g.tc.structs { qname } else { type_name } + if qname in g.tc.structs { + return qname + } + return type_name } // struct_field_type supports struct field type handling for FlatGen. diff --git a/vlib/v3/markused/markused.v b/vlib/v3/markused/markused.v index 6bea2c4f1..7569eb4d5 100644 --- a/vlib/v3/markused/markused.v +++ b/vlib/v3/markused/markused.v @@ -154,11 +154,12 @@ fn mark_used_with_test_files(a &flat.FlatAst, tc &types.TypeChecker, test_files 'sync.Channel.close', 'sync.Channel.len', 'sync.Channel.closed', 'new_channel_st', 'Channel.push', 'Channel.pop', 'Channel.close', 'Channel.len', 'Channel.closed', 'panic', 'u8.is_letter', 'u8.is_capital', 'string.is_capital', 'string.to_lower_ascii', - 'rune.to_lower', 'data_to_hex_string', 'map_hash_string', 'map_hash_int_1', 'map_hash_int_2', - 'map_hash_int_4', 'map_hash_int_8', 'map_eq_string', 'map_eq_int_1', 'map_eq_int_2', - 'map_eq_int_4', 'map_eq_int_8', 'map_clone_string', 'map_clone_int_1', 'map_clone_int_2', - 'map_clone_int_4', 'map_clone_int_8', 'map_free_string', 'map_free_nop', '[]string.join', - 'Array_string__join', 'exit', 'v_exit'] { + 'rune.to_lower', 'Array_u8__bytestr', 'Array_u8__hex', 'data_to_hex_string', + 'map_hash_string', 'map_hash_int_1', 'map_hash_int_2', 'map_hash_int_4', 'map_hash_int_8', + 'map_eq_string', 'map_eq_int_1', 'map_eq_int_2', 'map_eq_int_4', 'map_eq_int_8', + 'map_clone_string', 'map_clone_int_1', 'map_clone_int_2', 'map_clone_int_4', + 'map_clone_int_8', 'map_free_string', 'map_free_nop', '[]string.join', 'Array_string__join', + 'exit', 'v_exit'] { queue << seed used[seed] = true } @@ -433,6 +434,17 @@ fn valid_symbol_name(name string) bool { return name.len > 0 && name.len < 512 } +// markused_clone_bool_map returns a value clone even when the source is passed +// from a `mut map` parameter. v3 self-host cgen otherwise infers a `map*` local +// for `param.clone()` in a few recursive markused scanners. +fn markused_clone_bool_map(src map[string]bool) map[string]bool { + return src.clone() +} + +fn markused_clone_string_map(src map[string]string) map[string]string { + return src.clone() +} + // enqueue_initializer_calls supports enqueue initializer calls handling for markused. fn enqueue_initializer_calls(a &flat.FlatAst, collector CallCollector, imports map[string]string, fn_decls map[string]FnDeclInfo, mut used map[string]bool, mut queue []string) { mut cur_module := '' @@ -1505,7 +1517,7 @@ fn markused_scan_prior_local_value(a &flat.FlatAst, node &flat.Node, target flat continue } .block, .if_expr, .match_stmt, .for_stmt, .for_in_stmt { - mut scoped := locals.clone() + mut scoped := markused_clone_bool_map(locals) if found := markused_scan_prior_local_value(a, child, target, name, mut scoped) { return found } @@ -1578,8 +1590,8 @@ fn (c &CallCollector) collect_top_level_stmt_calls(id flat.NodeId, cur_module st local_types, mut calls) } .block, .for_stmt, .for_in_stmt { - mut nested_values := local_values.clone() - mut nested_types := local_types.clone() + mut nested_values := markused_clone_bool_map(local_values) + mut nested_types := markused_clone_string_map(local_types) c.collect_top_level_child_calls(node, cur_module, imports, mut nested_values, mut nested_types, mut calls) } @@ -1622,13 +1634,13 @@ fn (c &CallCollector) collect_top_level_assign_calls(node &flat.Node, cur_module return } mut i := 0 - pre_values := local_values.clone() - pre_types := local_types.clone() + pre_values := markused_clone_bool_map(local_values) + pre_types := markused_clone_string_map(local_types) for i + 1 < node.children_count { rhs_id := c.a.child(node, i + 1) if int(rhs_id) >= 0 { - mut rhs_values := pre_values.clone() - mut rhs_types := pre_types.clone() + mut rhs_values := markused_clone_bool_map(pre_values) + mut rhs_types := markused_clone_string_map(pre_types) c.collect_top_level_stmt_calls(rhs_id, cur_module, imports, mut rhs_values, mut rhs_types, mut calls) } @@ -1656,8 +1668,8 @@ fn (c &CallCollector) collect_top_level_global_decl_calls(node &flat.Node, cur_m if node.kind != .global_decl { return } - pre_values := local_values.clone() - pre_types := local_types.clone() + pre_values := markused_clone_bool_map(local_values) + pre_types := markused_clone_string_map(local_types) for i in 0 .. node.children_count { field := c.a.child_node(node, i) if field.children_count == 0 { @@ -1665,8 +1677,8 @@ fn (c &CallCollector) collect_top_level_global_decl_calls(node &flat.Node, cur_m } expr_id := c.a.child(field, 0) if int(expr_id) >= 0 { - mut rhs_values := pre_values.clone() - mut rhs_types := pre_types.clone() + mut rhs_values := markused_clone_bool_map(pre_values) + mut rhs_types := markused_clone_string_map(pre_types) c.collect_top_level_stmt_calls(expr_id, cur_module, imports, mut rhs_values, mut rhs_types, mut calls) } diff --git a/vlib/v3/tests/parallel_cgen_test.v b/vlib/v3/tests/parallel_cgen_test.v index 1d6d253b1..641707552 100644 --- a/vlib/v3/tests/parallel_cgen_test.v +++ b/vlib/v3/tests/parallel_cgen_test.v @@ -17,6 +17,16 @@ fn build_parallel_v3() string { return v3_bin } +fn build_parallel_prod_v3() string { + vexe := @VEXE + v3_bin := os.join_path(os.temp_dir(), 'v3_parallel_prod_cgen_test_${os.getpid()}') + os.rm(v3_bin) or {} + build := + os.execute('${vexe} -d parallel -gc none -prod -path "${parallel_vlib_dir}|@vlib|@vmodules" -o ${v3_bin} ${parallel_v3_src}') + assert build.exit_code == 0, build.output + return v3_bin +} + // write_parallel_module_init_project writes parallel module init project output for v3 tests. fn write_parallel_module_init_project(name string) string { project_dir := os.join_path(os.temp_dir(), 'v3_${name}') @@ -260,3 +270,19 @@ fn test_parallel_transform_lowers_top_level_stmts_without_main_once() { c_code := os.read_file(bin_out + '.c') or { panic(err) } assert c_code.all_after('int main').count('map__get_check') == 1, c_code } + +fn test_parallel_transform_selfhost_builds_v3() { + v3_bin := build_parallel_prod_v3() + bin_out := os.join_path(os.temp_dir(), 'v3_parallel_selfhost_out_${os.getpid()}') + os.rm(bin_out) or {} + os.rm(bin_out + '.c') or {} + compile := + os.execute('VJOBS=2 ${v3_bin} -building-v -parallel-transform -parallel -o ${bin_out} ${parallel_v3_src}') + assert compile.exit_code == 0, compile.output + assert compile.output.contains('transform (parallel)'), compile.output + assert compile.output.contains('cgen (parallel)'), compile.output + assert os.exists(bin_out), compile.output + c_code := os.read_file(bin_out + '.c') or { panic(err) } + assert c_code.contains('Array_u8__bytestr'), c_code + assert c_code.contains('Array_u8__hex'), c_code +} -- 2.39.5