Skip to content

Commit

Permalink
cgen: fix codegen for a fixed array init with different node types (fix
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Jan 22, 2025
1 parent b036a6a commit 6b0c272
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
17 changes: 15 additions & 2 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -2768,10 +2768,23 @@ fn (mut g Gen) expr_with_fixed_array(expr ast.Expr, got_type_raw ast.Type, expec
g.writeln('${styp} ${tmp_var};')
// [ foo(), foo() ]!
val_typ := g.table.value_type(got_type_raw)
val_styp := g.styp(val_typ)
val_sym := g.table.final_sym(val_typ)
prefix := if val_sym.kind !in [.array, .array_fixed] { '&' } else { '' }
for i, item_expr in expr.exprs {
g.write('memcpy(${tmp_var}[${i}], ')
g.write('memcpy(${prefix}${tmp_var}[${i}], ')
needs_addr := (item_expr is ast.CallExpr && !item_expr.return_type.is_ptr()
&& g.table.final_sym(item_expr.return_type).kind !in [.array, .array_fixed])
|| (item_expr is ast.InfixExpr && !item_expr.promoted_type.is_ptr())
|| item_expr is ast.StructInit
if needs_addr {
g.write('ADDR(${val_styp}, ')
}
g.expr(item_expr)
g.writeln(', sizeof(${g.styp(val_typ)}));')
if needs_addr {
g.write(')')
}
g.writeln(', sizeof(${val_styp}));')
}
} else if expr is ast.CallExpr {
// return var.call() where returns is option/result fixed array
Expand Down
50 changes: 50 additions & 0 deletions vlib/v/tests/builtin_arrays/array_fixed_init_node_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module main

import math.vec

pub struct Bezier {
pub mut:
points [4]vec.Vec2[f32]
}

pub fn (b Bezier) h3() vec.Vec2[f32] {
return b.points[2]
}

pub fn (b Bezier) h4() vec.Vec2[f32] {
return b.points[3]
}

pub fn (b Bezier) end() vec.Vec2[f32] {
return b.h4()
}

pub struct Path {
pub mut:
segments [1024]Bezier
len int // should be read-only
}

pub fn (mut p Path) add(b Bezier) {
assert p.len + 1 < 1024
p.segments[p.len] = b
p.len++
}

fn test_main() {
b1 := Bezier{
points: [vec.Vec2[f32]{100, 100}, vec.Vec2[f32]{120, 80},
vec.Vec2[f32]{200, 70}, vec.Vec2[f32]{400, 200}]!
}
b2 := Bezier{
points: [b1.end(), b1.h3() + vec.Vec2[f32]{0, 2 * 80}, vec.Vec2[f32]{200, 70},
b1.end() + vec.Vec2[f32]{400, 200}]!
}

mut path := Path{}

path.add(b1)
path.add(b2)

assert sizeof(path) == 32772
}

0 comments on commit 6b0c272

Please sign in to comment.