From 5b1581daeeaff74b0121b2be7e9a73fb3cc9f38e Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 3 Oct 2024 13:59:57 -0300 Subject: [PATCH] cgen: fix global decl type default generation for fixed array (fix #22402) (#22403) --- vlib/v/gen/c/cgen.v | 44 ++++++++++++++++++++- vlib/v/tests/global_fixed_arr_init_test.v | 47 +++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/global_fixed_arr_init_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 864972ebc35ddc..d08152c5a5d758 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -64,6 +64,7 @@ mut: channel_definitions strings.Builder // channel related code thread_definitions strings.Builder // thread defines comptime_definitions strings.Builder // custom defines, given by -d/-define flags on the CLI + type_default_vars strings.Builder // type_default() var declarations cleanup strings.Builder cleanups map[string]strings.Builder // contents of `void _vcleanup(){}` gowrappers strings.Builder // all go callsite wrappers @@ -6374,14 +6375,19 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) { } } } else if !g.pref.translated { // don't zero globals from C code + g.type_default_vars.clear() default_initializer := g.type_default(field.typ) if default_initializer == '{0}' && should_init { def_builder.write_string(' = {0}') } else if default_initializer == '{EMPTY_STRUCT_INITIALIZATION}' && should_init { - init = '\tmemcpy(${field.name}, (${styp}){${g.type_default(field.typ)}}, sizeof(${styp})); // global' + init = '\tmemcpy(${field.name}, (${styp}){${default_initializer}}, sizeof(${styp})); // global' } else { if field.name !in ['as_cast_type_indexes', 'g_memory_block', 'global_allocator'] { - init = '\t${field.name} = *(${styp}*)&((${styp}[]){${g.type_default(field.typ)}}[0]); // global' + decls := g.type_default_vars.str() + if decls != '' { + init = '\t${decls}' + } + init += '\t${field.name} = *(${styp}*)&((${styp}[]){${default_initializer}}[0]); // global' } } } @@ -7380,6 +7386,40 @@ fn (mut g Gen) type_default(typ_ ast.Type) string { if field_sym.kind in [.sum_type, .interface_] { expr_str = g.expr_string_with_cast(field.default_expr, field.default_expr_typ, field.typ) + } else if field_sym.is_array_fixed() && g.inside_global_decl { + array_info := field_sym.array_fixed_info() + match field.default_expr { + ast.CallExpr { + ret_typ := g.typ(field.default_expr.return_type) + tmp_var := g.new_tmp_var() + g.type_default_vars.writeln('${ret_typ} ${tmp_var} = {0};') + g.type_default_vars.writeln('memcpy(${tmp_var}, ${g.expr_string(field.default_expr)}, sizeof(${ret_typ}));') + expr_str += '{' + for i in 0 .. array_info.size { + expr_str += '${tmp_var}[${i}]' + if i != array_info.size - 1 { + expr_str += ', ' + } + } + expr_str += '}' + } + ast.ArrayInit { + ret_typ := g.typ(field.default_expr.typ) + tmp_var := g.new_tmp_var() + g.type_default_vars.writeln('${ret_typ} ${tmp_var} = ${g.expr_string(field.default_expr)};') + expr_str += '{' + for i in 0 .. array_info.size { + expr_str += '${tmp_var}[${i}]' + if i != array_info.size - 1 { + expr_str += ', ' + } + } + expr_str += '}' + } + else { + expr_str = g.expr_string(field.default_expr) + } + } } else { expr_str = g.expr_string(field.default_expr) } diff --git a/vlib/v/tests/global_fixed_arr_init_test.v b/vlib/v/tests/global_fixed_arr_init_test.v new file mode 100644 index 00000000000000..3fbf36467b4e81 --- /dev/null +++ b/vlib/v/tests/global_fixed_arr_init_test.v @@ -0,0 +1,47 @@ +module main + +type Mat4 = [16]f32 + +pub fn mat4(x0 f32, x1 f32, x2 f32, x3 f32, x4 f32, x5 f32, x6 f32, x7 f32, x8 f32, x9 f32, x10 f32, x11 f32, x12 f32, x13 f32, x14 f32, x15 f32) Mat4 { + return [ + x0, + x1, + x2, + x3, + x4, + x5, + x6, + x7, + x8, + x9, + x10, + x11, + x12, + x13, + x14, + x15, + ]! +} + +pub fn unit_m4() Mat4 { + return mat4(f32(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) +} + +struct GameObject { +mut: + rot Mat4 = unit_m4() + transform Mat4 = [f32(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]! +} + +__global ( + p GameObject +) + +fn test_main() { + println(p) + assert p.rot[0] == f32(1) + assert p.rot[15] == f32(1) + + assert p.transform[0] == f32(1) + assert p.transform[15] == f32(1) +}