cgen: fix array fixed code generation for more than 1 dimension (fix #22866) (#22876)

This commit is contained in:
Felipe Pena 2024-11-17 05:12:43 -03:00 committed by GitHub
parent e234a2d37e
commit 864845bccd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 92 additions and 27 deletions

View File

@ -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)
@ -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)
@ -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
}
}
@ -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}];')
}
}

View File

@ -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)
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 {
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)
}
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)
}
}

View File

@ -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)
}