Skip to content

Commit 996f0fe

Browse files
authored
native: fixed array, -new-transformer dynamic array (#25817)
1 parent b17ac33 commit 996f0fe

File tree

10 files changed

+140
-112
lines changed

10 files changed

+140
-112
lines changed

vlib/v/gen/native/amd64.v

Lines changed: 16 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,6 +1962,10 @@ fn (mut c Amd64) mod_reg_rax(b Amd64Register) {
19621962
c.mov_reg(.rax, .rdx)
19631963
}
19641964

1965+
fn (mut c Amd64) cg_sub_reg(a Register, b Register) {
1966+
c.sub_reg(a.amd64(), b.amd64())
1967+
}
1968+
19651969
fn (mut c Amd64) sub_reg(a Amd64Register, b Amd64Register) {
19661970
if i32(a) <= i32(Amd64Register.r15) && i32(b) <= i32(Amd64Register.r15) {
19671971
c.g.write8(0x48 + if i32(a) >= i32(Amd64Register.r8) { i32(1) } else { i32(0) } +
@@ -2086,7 +2090,7 @@ pub fn (mut c Amd64) cg_call_fn(node ast.CallExpr) {
20862090
return_size := c.g.get_type_size(node.return_type)
20872091
mut return_pos := i32(-1)
20882092
mut is_struct_return := false
2089-
if ts.kind in [.struct, .multi_return] {
2093+
if ts.kind in [.struct, .multi_return, .array] {
20902094
return_pos = c.g.allocate_by_type('', node.return_type)
20912095
if return_size > 16 {
20922096
is_struct_return = true
@@ -2361,7 +2365,7 @@ fn (mut c Amd64) assign_struct_var(ident_var IdentVar, typ ast.Type, s i32) {
23612365
assert size == 0
23622366
}
23632367

2364-
fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
2368+
fn (mut c Amd64) cg_assign_var(var IdentVar, raw_type ast.Type) {
23652369
typ := c.g.unwrap(raw_type)
23662370
info := c.g.table.sym(typ).info
23672371
size := c.g.get_type_size(typ)
@@ -2381,6 +2385,9 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
23812385
} else if info is ast.Struct && !typ.is_any_kind_of_pointer()
23822386
&& !raw_type.is_any_kind_of_pointer() {
23832387
c.assign_struct_var(var, typ, size)
2388+
} else if info is ast.Array && !typ.is_any_kind_of_pointer()
2389+
&& !raw_type.is_any_kind_of_pointer() {
2390+
c.assign_struct_var(var, typ, size)
23842391
} else if int(size) in [1, 2, 4, 8] {
23852392
match var {
23862393
LocalVar {
@@ -2593,8 +2600,12 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
25932600
match node.op {
25942601
.decl_assign {
25952602
if right.is_fixed {
2596-
c.g.n_error('${@LOCATION} Unsupported ${node} ${right}')
2603+
dest := c.g.allocate_by_type(name, ast.voidptr_type_idx)
2604+
c.g.expr(right)
2605+
c.cg_mov_reg_to_var(LocalVar{dest, ast.voidptr_type_idx, name},
2606+
.reg0)
25972607
} else if right.exprs.len == 0 {
2608+
// TODO: remove when ArrayInit for dynarrays will be solved in the transformer
25982609
// `[]int{len: 6, cap:10, init:22}`
25992610
c.g.allocate_by_type(ident.name, ast.array_type)
26002611
len := ast.CallArg{
@@ -2728,7 +2739,7 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
27282739

27292740
if node.op in [.assign, .decl_assign] {
27302741
var := c.g.get_var_from_ident(ident)
2731-
c.assign_var(var, left_type)
2742+
c.cg_assign_var(var, left_type)
27322743
} else if left_type.is_pure_float() {
27332744
c.mov_var_to_ssereg(.xmm1, ident)
27342745

@@ -2775,7 +2786,7 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
27752786

27762787
if node.op in [.assign, .decl_assign] {
27772788
var := c.g.get_var_from_ident(ident)
2778-
c.assign_var(var, left_type)
2789+
c.cg_assign_var(var, left_type)
27792790
} else if left_type.is_pure_float() {
27802791
c.mov_var_to_ssereg(.xmm1, ident)
27812792

@@ -4293,55 +4304,6 @@ fn (mut c Amd64) copy_struct_to_struct(field ast.StructField, f_offset i32, data
42934304
}
42944305
}
42954306

4296-
fn (mut c Amd64) cg_init_array(var Var, node ast.ArrayInit) {
4297-
match var {
4298-
ast.Ident {
4299-
var_object := c.g.get_var_from_ident(var)
4300-
match var_object {
4301-
LocalVar {
4302-
c.cg_init_array(var_object as LocalVar, node)
4303-
}
4304-
GlobalVar {
4305-
c.cg_init_array(var_object as GlobalVar, node)
4306-
}
4307-
Register {
4308-
// TODO
4309-
// c.g.cmp()
4310-
}
4311-
ExternVar {
4312-
c.cg_init_array(var_object as ExternVar, node)
4313-
}
4314-
PreprocVar {
4315-
c.cg_init_array(var_object as PreprocVar, node)
4316-
}
4317-
ConstVar {
4318-
c.cg_init_array(var_object as ConstVar, node)
4319-
}
4320-
}
4321-
}
4322-
LocalVar {
4323-
mut offset := var.offset
4324-
for expr in node.exprs {
4325-
c.g.expr(expr)
4326-
c.cg_mov_reg_to_var(LocalVar{offset, ast.i64_type_idx, ''}, .reg0)
4327-
offset += 8
4328-
}
4329-
}
4330-
GlobalVar {
4331-
c.g.n_error('${@LOCATION} unsupported var type ${var}')
4332-
}
4333-
ExternVar {
4334-
c.g.n_error('${@LOCATION} unsupported var type ${var}')
4335-
}
4336-
PreprocVar {
4337-
c.g.n_error('${@LOCATION} unsupported var type ${var}')
4338-
}
4339-
ConstVar {
4340-
c.g.n_error('${@LOCATION} unsupported var type ${var}')
4341-
}
4342-
}
4343-
}
4344-
43454307
// TODO: replace with .str()
43464308
fn (mut c Amd64) cg_convert_bool_to_string(r Register) {
43474309
reg := r.amd64()

vlib/v/gen/native/arm64.v

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,6 @@ fn (mut c Arm64) cg_init_struct(var Var, init ast.StructInit) {
446446
panic('Arm64.cg_init_struct() not implemented')
447447
}
448448

449-
fn (mut c Arm64) cg_init_array(var Var, init ast.ArrayInit) {
450-
panic('Arm64.cg_init_array() not implemented')
451-
}
452-
453449
fn (mut c Arm64) cg_load_fp_var(var Var, config VarConfig) {
454450
panic('Arm64.cg_load_fp_var() not implemented')
455451
}
@@ -557,3 +553,11 @@ fn (mut c Arm64) cg_patch_relative_jmp(pos i32, addr i64) {
557553
fn (mut c Arm64) cg_mul_reg(a Register, b Register) {
558554
panic('Arm64.cg_mul_reg() not implemented')
559555
}
556+
557+
fn (mut c Arm64) cg_assign_var(var IdentVar, raw_type ast.Type) {
558+
panic('Arm64.cg_assign_var() not implemented')
559+
}
560+
561+
fn (mut c Arm64) cg_sub_reg(a Register, b Register) {
562+
panic('Arm64.cg_sub_reg() not implemented')
563+
}

vlib/v/gen/native/blacklist.v

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -29,53 +29,54 @@ already compiling functions:
2929
// false: whitelist function
3030
// true: blacklist function
3131
const blacklist = {
32-
'main.main': false
33-
'c_error_number_str': false
34-
'exit': false
35-
'gc_is_enabled': false
36-
'int_max': false
37-
'int_min': false
38-
'flush_stdout': false
39-
'flush_stderr': false
40-
'print_character': false
41-
'u8.is_alnum': false
42-
'u8.is_bin_digit': false
43-
'u8.is_capital': false
44-
'u8.is_digit': false
45-
'u8.is_hex_digit': false
46-
'u8.is_letter': false
47-
'u8.is_oct_digit': false
48-
'u8.is_space': false
49-
'string.is_capital': false
50-
'string.is_ascii': false
51-
'string.is_identifier': false
52-
'string.is_blank': false
53-
'string.indent_width': false
54-
'string.index_u8': false
55-
'string.last_index': true
56-
'string.last_index_u8': false
57-
'string.contains_u8': false
58-
'malloc_noscan': false
59-
'malloc': false
60-
'is_nil': false
61-
'memdup': false
62-
'vcalloc': false
63-
'vmemcpy': false
64-
'eprint': false
65-
'eprintln': false
66-
'_write_buf_to_fd': false
67-
'_writeln_to_fd': false
68-
'_memory_panic': false
69-
'panic': false
70-
'vcurrent_hash': false
71-
'__new_array': false
72-
'panic_on_negative_len': false
73-
'panic_on_negative_cap': false
74-
'panic_n': false
75-
'impl_i64_to_string': false
76-
'vmemmove': false
77-
'tos': false
78-
'strings.new_builder': true
32+
'main.main': false
33+
'c_error_number_str': false
34+
'exit': false
35+
'gc_is_enabled': false
36+
'int_max': false
37+
'int_min': false
38+
'flush_stdout': false
39+
'flush_stderr': false
40+
'print_character': false
41+
'u8.is_alnum': false
42+
'u8.is_bin_digit': false
43+
'u8.is_capital': false
44+
'u8.is_digit': false
45+
'u8.is_hex_digit': false
46+
'u8.is_letter': false
47+
'u8.is_oct_digit': false
48+
'u8.is_space': false
49+
'string.is_capital': false
50+
'string.is_ascii': false
51+
'string.is_identifier': false
52+
'string.is_blank': false
53+
'string.indent_width': false
54+
'string.index_u8': false
55+
'string.last_index': true
56+
'string.last_index_u8': false
57+
'string.contains_u8': false
58+
'malloc_noscan': false
59+
'malloc': false
60+
'is_nil': false
61+
'memdup': false
62+
'vcalloc': false
63+
'vmemcpy': false
64+
'eprint': false
65+
'eprintln': false
66+
'_write_buf_to_fd': false
67+
'_writeln_to_fd': false
68+
'_memory_panic': false
69+
'panic': false
70+
'vcurrent_hash': false
71+
'__new_array': false
72+
'panic_on_negative_len': false
73+
'panic_on_negative_cap': false
74+
'panic_n': false
75+
'impl_i64_to_string': false
76+
'vmemmove': false
77+
'tos': false
78+
'strings.new_builder': true
79+
'new_array_from_c_array': false
7980
}
8081

8182
const windows_blacklist = {

vlib/v/gen/native/expr.v

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ fn (mut g Gen) expr(node ast.Expr) {
1616
g.expr(node.expr)
1717
}
1818
ast.ArrayInit {
19-
pos := g.allocate_array('_anonarray', 8, i32(node.exprs.len))
20-
g.cg.cg_init_array(LocalVar{ offset: pos, typ: node.typ }, node)
21-
g.cg.cg_lea_var_to_reg(.reg0, pos)
19+
if node.is_fixed {
20+
pos := g.allocate_fixed_array(node.elem_type, i32(node.exprs.len))
21+
g.init_array(LocalVar{ offset: pos, typ: node.elem_type }, node)
22+
g.cg.cg_lea_var_to_reg(.reg0, pos)
23+
} else { // TODO: remove, it should not be on the stack
24+
pos := g.allocate_array('_anonarray', 8, i32(node.exprs.len))
25+
g.init_array(LocalVar{ offset: pos, typ: node.typ }, node)
26+
g.cg.cg_lea_var_to_reg(.reg0, pos)
27+
}
2228
}
2329
ast.BoolLiteral {
2430
g.cg.cg_mov64(.reg0, i64(node.val))
@@ -168,6 +174,18 @@ fn (mut g Gen) expr(node ast.Expr) {
168174
}
169175
}
170176

177+
fn (mut g Gen) init_array(var LocalVar, node ast.ArrayInit) {
178+
mut pos := var.offset
179+
size := g.get_type_size(node.elem_type)
180+
align := g.get_type_align(node.elem_type)
181+
padding := (align - g.stack_var_pos % align) % align
182+
for expr in node.exprs {
183+
g.expr(expr)
184+
g.cg.cg_assign_var(LocalVar{pos, node.elem_type, ''}, node.elem_type)
185+
pos -= size + padding
186+
}
187+
}
188+
171189
fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) {
172190
if g.is_register_type(var.typ) {
173191
g.cg.cg_mov_var_to_reg(.reg0, ident)
@@ -185,6 +203,12 @@ fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) {
185203
ast.Array {
186204
g.cg.cg_lea_var_to_reg(.reg0, g.get_var_offset(ident.name))
187205
}
206+
ast.ArrayFixed {
207+
g.cg.cg_mov_var_to_reg(.reg0, LocalVar{
208+
offset: g.get_var_offset(ident.name)
209+
typ: ast.voidptr_type_idx
210+
})
211+
}
188212
else {
189213
g.n_error('${@LOCATION} Unsupported variable type ${ts.info}')
190214
}
@@ -602,6 +626,14 @@ fn (mut g Gen) gen_index_expr(node ast.IndexExpr) {
602626
g.cg.cg_mov(.reg3, i32(g.get_type_size(node.typ)))
603627
g.cg.cg_mul_reg(.reg0, .reg3)
604628
g.cg.cg_add_reg(.reg0, .reg1)
629+
} else if node.is_farray {
630+
g.expr(node.left)
631+
g.cg.cg_mov_reg(.reg1, .reg0)
632+
// add the index times the size (bytes) of the type
633+
g.expr(node.index)
634+
g.cg.cg_mov(.reg3, i32(g.get_type_size(node.typ)))
635+
g.cg.cg_mul_reg(.reg0, .reg3)
636+
g.cg.cg_add_reg(.reg0, .reg1)
605637
} else {
606638
g.n_error('${@LOCATION} index expr: unhandled node type {node}')
607639
}

vlib/v/gen/native/gen.v

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ mut:
9898
cg_add_reg(r Register, r2 Register)
9999
cg_address_size() i32
100100
cg_allocate_stack_var(name string, size i32, initial_val Number) i32
101+
cg_assign_var(var IdentVar, raw_type ast.Type)
101102
cg_assign_stmt(node ast.AssignStmt)
102103
cg_builtin_decl(builtin BuiltinFn)
103104
cg_call_addr_at(addr i32, at i64) i64
@@ -126,7 +127,6 @@ mut:
126127
cg_infix_expr(node ast.InfixExpr)
127128
cg_infloop()
128129
cg_init_struct(var Var, init ast.StructInit)
129-
cg_init_array(var Var, init ast.ArrayInit)
130130
cg_jmp_back(start i64)
131131
cg_jmp(addr i32) i32
132132
cg_lea_var_to_reg(r Register, var_offset i32)
@@ -150,6 +150,7 @@ mut:
150150
cg_ret()
151151
cg_return_stmt(node ast.Return)
152152
cg_reverse_string(r Register)
153+
cg_sub_reg(a Register, b Register)
153154
cg_syscall() // unix syscalls
154155
cg_trap()
155156
cg_zero_fill(size i32, var LocalVar)
@@ -826,6 +827,9 @@ fn (mut g Gen) unwrap(typ ast.Type) ast.Type {
826827

827828
// get type size, and calculate size and align and store them to the cache when the type is struct
828829
fn (mut g Gen) get_type_size(raw_type ast.Type) i32 {
830+
if raw_type == ast.no_type_idx {
831+
g.n_error('${@LOCATION}: unknown type (0)')
832+
}
829833
// TODO: type flags
830834
typ := g.unwrap(raw_type)
831835
if raw_type.is_any_kind_of_pointer() || typ.is_any_kind_of_pointer() {
@@ -1042,13 +1046,22 @@ fn (mut g Gen) allocate_string(s string, opsize i32, typ RelocType) i32 {
10421046
}
10431047

10441048
// allocates a buffer variable: name, size of stored type (nb of bytes), nb of items
1045-
fn (mut g Gen) allocate_array(name string, size i32, items i32) i32 {
1049+
fn (mut g Gen) allocate_array(name string, size i32, items i32) i32 { // TODO: remove when proper strings are implemented, should not be used
10461050
g.println('; allocate array `${name}` item-size:${size} items:${items}:')
10471051
pos := g.cg.cg_allocate_stack_var(name, 4, i64(items)) // store the length of the array on the stack in a 4 byte var
10481052
g.stack_var_pos += (size * items) // reserve space on the stack for the items
10491053
return pos
10501054
}
10511055

1056+
fn (mut g Gen) allocate_fixed_array(typ ast.Type, nb_items i32) i32 {
1057+
g.println('; allocate fixed array type:${typ} nb_items:${nb_items}:')
1058+
size := g.get_type_size(typ)
1059+
align := g.get_type_align(typ)
1060+
padding := (align - g.stack_var_pos % align) % align
1061+
g.stack_var_pos += (size + padding) * nb_items // reserve space on the stack for the items
1062+
return g.stack_var_pos
1063+
}
1064+
10521065
fn (mut g Gen) eval_str_lit_escape_codes(str_lit ast.StringLiteral) string {
10531066
if str_lit.is_raw {
10541067
return str_lit.val

vlib/v/gen/native/tests/arrays.vv

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ fn main() {
22
assert [1, 2, 3] != []
33
array_with_len()
44
array_with_values()
5+
fixed_array()
6+
}
7+
8+
fn fixed_array() {
9+
f := [1, 2, 3]!
10+
assert f[0] == 1
11+
assert f[1] == 2
12+
assert f[2] == 3
513
}
614

715
fn array_with_len() {

0 commit comments

Comments
 (0)