Skip to content

Commit

Permalink
cgen: fix array fixed code generation for more than 1 dimension (fix v…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Nov 17, 2024
1 parent e234a2d commit 864845b
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 27 deletions.
23 changes: 21 additions & 2 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,7 @@ fn (mut g Gen) expr_with_var(expr ast.Expr, got_type_raw ast.Type, expected_type
g.empty_line = true
tmp_var := g.new_tmp_var()
styp := g.styp(expected_type)

g.writeln('${styp} ${tmp_var};')
g.write('memcpy(&${tmp_var}, ')
g.expr(expr)
Expand All @@ -2567,6 +2568,24 @@ fn (mut g Gen) expr_with_var(expr ast.Expr, got_type_raw ast.Type, expected_type
return tmp_var
}

// expr_with_fixed_array generates code for fixed array initialization with expr which requires tmp var
fn (mut g Gen) expr_with_fixed_array(expr ast.ArrayInit, got_type_raw ast.Type, expected_type ast.Type) string {
stmt_str := g.go_before_last_stmt().trim_space()
g.empty_line = true
tmp_var := g.new_tmp_var()
styp := g.styp(expected_type)
g.writeln('${styp} ${tmp_var};')
// [ foo(), foo() ]!
val_typ := g.table.value_type(got_type_raw)
for i, item_expr in expr.exprs {
g.write('memcpy(${tmp_var}[${i}], ')
g.expr(item_expr)
g.writeln(', sizeof(${g.styp(val_typ)}));')
}
g.write(stmt_str)
return tmp_var
}

// use instead of expr() when you need to cast to a different type
fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_type ast.Type) {
got_type := ast.mktyp(got_type_raw)
Expand Down Expand Up @@ -2620,7 +2639,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
// Do not allocate for `Interface(unsafe{nil})` casts
is_nil_cast := expr is ast.UnsafeExpr && expr.expr is ast.Nil
if is_nil_cast {
g.write2('/*nili*/', '((void*)0)')
g.write2('/*nil*/', '((void*)0)')
return
}
}
Expand Down Expand Up @@ -6901,7 +6920,7 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
base)};')
}
}
} else {
} else if !(elem_sym.info is ast.ArrayFixed && elem_sym.info.is_fn_ret) {
g.type_definitions.writeln('typedef ${fixed_elem_name} ${styp} [${len}];')
}
}
Expand Down
74 changes: 49 additions & 25 deletions vlib/v/gen/c/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -680,33 +680,57 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua

field_unwrap_typ := g.unwrap_generic(sfield.typ)
field_unwrap_sym := g.table.final_sym(field_unwrap_typ)
if field_unwrap_sym.kind == .array_fixed && sfield.expr in [ast.Ident, ast.SelectorExpr] {
info := field_unwrap_sym.info as ast.ArrayFixed
g.fixed_array_var_init(g.expr_string(sfield.expr), sfield.expr.is_auto_deref_var(),
info.elem_type, info.size)
} else if field_unwrap_sym.kind == .array_fixed && (sfield.expr is ast.CallExpr
|| (sfield.expr is ast.ArrayInit && sfield.expr.has_index)) {
info := field_unwrap_sym.info as ast.ArrayFixed
tmp_var := g.expr_with_var(sfield.expr, sfield.typ, sfield.expected_type)
g.fixed_array_var_init(tmp_var, false, info.elem_type, info.size)
} else {
if field_unwrap_typ != ast.voidptr_type && field_unwrap_typ != ast.nil_type
&& (sfield.expected_type.is_ptr() && !sfield.expected_type.has_flag(.shared_f))
&& !sfield.expected_type.has_flag(.option)
&& !field_unwrap_typ.is_any_kind_of_pointer() && !field_unwrap_typ.is_number() {
g.write('/* autoref */&')
}

if (sfield.expected_type.has_flag(.option) && !field_unwrap_typ.has_flag(.option))
|| (sfield.expected_type.has_flag(.result) && !field_unwrap_typ.has_flag(.result)) {
g.expr_with_opt(sfield.expr, field_unwrap_typ, sfield.expected_type)
} else if sfield.expr is ast.LambdaExpr && sfield.expected_type.has_flag(.option) {
g.expr_opt_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
} else {
g.left_is_opt = true
g.expr_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
is_auto_deref_var := sfield.expr.is_auto_deref_var()
if field_unwrap_sym.info is ast.ArrayFixed {
match sfield.expr {
ast.Ident, ast.SelectorExpr {
g.fixed_array_var_init(g.expr_string(sfield.expr), is_auto_deref_var,
field_unwrap_sym.info.elem_type, field_unwrap_sym.info.size)
}
ast.CallExpr {
tmp_var := g.expr_with_var(sfield.expr, sfield.typ, sfield.expected_type)
g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type,
field_unwrap_sym.info.size)
}
ast.ArrayInit {
if sfield.expr.has_index {
tmp_var := g.expr_with_var(sfield.expr, sfield.typ, sfield.expected_type)
g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type,
field_unwrap_sym.info.size)
} else if sfield.expr.exprs.len > 0 && sfield.expr.exprs.any(it is ast.CallExpr) {
tmp_var := g.expr_with_fixed_array(sfield.expr, sfield.typ, sfield.expected_type)
g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type,
field_unwrap_sym.info.size)
} else {
g.struct_init_field_default(field_unwrap_typ, sfield)
}
}
else {
g.struct_init_field_default(field_unwrap_typ, sfield)
}
}
} else {
g.struct_init_field_default(field_unwrap_typ, sfield)
}
g.inside_cast_in_heap = inside_cast_in_heap // restore value for further struct inits
}
}

fn (mut g Gen) struct_init_field_default(field_unwrap_typ ast.Type, sfield &ast.StructInitField) {
if field_unwrap_typ != ast.voidptr_type && field_unwrap_typ != ast.nil_type
&& (sfield.expected_type.is_ptr() && !sfield.expected_type.has_flag(.shared_f))
&& !sfield.expected_type.has_flag(.option) && !field_unwrap_typ.is_any_kind_of_pointer()
&& !field_unwrap_typ.is_number() {
g.write('/* autoref */&')
}

if (sfield.expected_type.has_flag(.option) && !field_unwrap_typ.has_flag(.option))
|| (sfield.expected_type.has_flag(.result) && !field_unwrap_typ.has_flag(.result)) {
g.expr_with_opt(sfield.expr, field_unwrap_typ, sfield.expected_type)
} else if sfield.expr is ast.LambdaExpr && sfield.expected_type.has_flag(.option) {
g.expr_opt_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
} else {
g.left_is_opt = true
g.expr_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
}
}
22 changes: 22 additions & 0 deletions vlib/v/tests/fixed_array_2_dims_init_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module main

struct Uniforms {
lights [2][4]f32
}

fn r() [4]f32 {
return [f32(1.1), 1.2, 1.3, 1.4]!
}

fn test_main() {
v := Uniforms{
lights: [
r(),
r(),
]!
}
assert v.lights[0][0] == f32(1.1)
assert v.lights[0][1] == f32(1.2)
assert v.lights[0][2] == f32(1.3)
assert v.lights[0][3] == f32(1.4)
}

0 comments on commit 864845b

Please sign in to comment.