Skip to content

Commit 515d78d

Browse files
authored
native: cleanup assign, fix nested struct (#23778)
1 parent b766900 commit 515d78d

12 files changed

Lines changed: 524 additions & 274 deletions

File tree

‎vlib/v/gen/native/amd64.v‎

Lines changed: 320 additions & 225 deletions
Large diffs are not rendered by default.

‎vlib/v/gen/native/expr.v‎

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn (mut g Gen) expr(node ast.Expr) {
5151
g.local_var_ident(node, var)
5252
}
5353
else {
54-
g.n_error('Unsupported variable kind')
54+
g.n_error('${@LOCATION} Unsupported variable kind')
5555
}
5656
}
5757
}
@@ -90,7 +90,7 @@ fn (mut g Gen) expr(node ast.Expr) {
9090
for i, v in bytes {
9191
val |= v << (i * 8)
9292
if i >= sizeof(rune) {
93-
g.n_error('runes are only 4 bytes wide')
93+
g.n_error('${@LOCATION} runes are only 4 bytes wide')
9494
}
9595
}
9696
g.code_gen.movabs(g.code_gen.main_reg(), i64(val))
@@ -129,7 +129,7 @@ fn (mut g Gen) expr(node ast.Expr) {
129129
g.gen_sizeof_expr(node)
130130
}
131131
else {
132-
g.n_error('expr: unhandled node type: ${node.type_name()}')
132+
g.n_error('${@LOCATION} expr: unhandled node type: ${node.type_name()}')
133133
}
134134
}
135135
}
@@ -151,7 +151,7 @@ fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) {
151151
)
152152
}
153153
else {
154-
g.n_error('Unsupported variable type')
154+
g.n_error('${@LOCATION} Unsupported variable type')
155155
}
156156
}
157157
}
@@ -273,7 +273,7 @@ fn (mut g Gen) gen_typeof_expr(node ast.TypeOf, newline bool) {
273273

274274
match ts.kind {
275275
.sum_type {
276-
g.n_error('`typeof()` is not implemented for sum types yet')
276+
g.n_error('${@LOCATION} `typeof()` is not implemented for sum types yet')
277277
}
278278
.array_fixed {
279279
fixed_info := ts.info as ast.ArrayFixed
@@ -427,10 +427,10 @@ fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) {
427427
}
428428
}
429429
} else {
430-
g.n_error('nothing to print')
430+
g.n_error('${@LOCATION} nothing to print')
431431
}
432432
} else {
433-
g.n_error('non-comptime conditionals are not implemented yet.')
433+
g.n_error('${@LOCATION} non-comptime conditionals are not implemented yet.')
434434
}
435435
}
436436
else {
@@ -445,11 +445,17 @@ fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) {
445445
}
446446

447447
fn (mut g Gen) gen_selector_expr(expr ast.SelectorExpr) {
448+
g.println('; .${expr.field_name} {')
448449
main_reg := g.code_gen.main_reg()
449450
g.expr(expr.expr)
450451
offset := g.get_field_offset(expr.expr_type, expr.field_name)
451-
g.code_gen.add(main_reg, offset)
452-
g.code_gen.mov_deref(main_reg, main_reg, expr.typ)
452+
if offset != 0 {
453+
g.code_gen.add(main_reg, offset)
454+
}
455+
if expr.next_token != .dot { // the deref needs to be on the last selector (that has no . after it)
456+
g.code_gen.mov_deref(main_reg, main_reg, expr.typ)
457+
}
458+
g.println('; .${expr.field_name} {')
453459
}
454460

455461
fn (mut g Gen) gen_left_value(node ast.Expr) {
@@ -465,18 +471,23 @@ fn (mut g Gen) gen_left_value(node ast.Expr) {
465471
g.code_gen.add(Amd64Register.rax, offset)
466472
}
467473
}
468-
ast.StructInit, ast.ArrayInit {
474+
ast.StructInit {
469475
g.expr(node)
470476
}
471-
ast.IndexExpr {} // TODO
477+
ast.ArrayInit {
478+
g.expr(node) // TODO: add a test that uses this
479+
}
480+
ast.IndexExpr { // TODO
481+
g.n_error('${@LOCATION} Unsupported IndexExpr left value')
482+
}
472483
ast.PrefixExpr {
473484
if node.op != .mul {
474-
g.n_error('Unsupported left value')
485+
g.n_error('${@LOCATION} Unsupported left value')
475486
}
476487
g.expr(node.right)
477488
}
478489
else {
479-
g.n_error('Unsupported left value')
490+
g.n_error('${@LOCATION} Unsupported left value')
480491
}
481492
}
482493
}

‎vlib/v/gen/native/gen.v‎

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,9 @@ fn byt(n i32, s i32) u8 {
265265
fn (mut g Gen) get_var_from_ident(ident ast.Ident) IdentVar {
266266
mut obj := ident.obj
267267
if obj !in [ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister] {
268-
obj = ident.scope.find(ident.name) or { g.n_error('unknown variable ${ident.name}') }
268+
obj = ident.scope.find(ident.name) or {
269+
g.n_error('${@LOCATION} unknown variable ${ident.name}')
270+
}
269271
}
270272
match obj {
271273
ast.Var {
@@ -277,7 +279,7 @@ fn (mut g Gen) get_var_from_ident(ident ast.Ident) IdentVar {
277279
}
278280
}
279281
else {
280-
g.n_error('unsupported variable type type:${obj} name:${ident.name}')
282+
g.n_error('${@LOCATION} unsupported variable type type:${obj} name:${ident.name}')
281283
}
282284
}
283285
}
@@ -291,7 +293,7 @@ fn (mut g Gen) get_type_from_var(var Var) ast.Type {
291293
return var.typ
292294
}
293295
GlobalVar {
294-
g.n_error('cannot get type from GlobalVar yet')
296+
g.n_error('${@LOCATION} cannot get type from GlobalVar yet')
295297
}
296298
}
297299
}
@@ -452,7 +454,7 @@ pub fn (mut g Gen) generate_header() {
452454
}
453455
}
454456
else {
455-
g.n_error('only `raw`, `linux`, `windows` and `macos` are supported for -os in -native')
457+
g.n_error('${@LOCATION} only `raw`, `linux`, `windows` and `macos` are supported for -os in -native')
456458
}
457459
}
458460
}
@@ -517,7 +519,7 @@ pub fn (mut g Gen) link(obj_name string) {
517519
// TODO: implement linking for macos!
518520
}
519521
else {
520-
g.n_error('native linking is not implemented for ${g.pref.os}')
522+
g.n_error('${@LOCATION} native linking is not implemented for ${g.pref.os}')
521523
}
522524
}
523525
}
@@ -681,15 +683,17 @@ fn (mut g Gen) try_var_offset(var_name string) i32 {
681683
fn (mut g Gen) get_var_offset(var_name string) i32 {
682684
r := g.try_var_offset(var_name)
683685
if r == -1 {
684-
g.n_error('unknown variable `${var_name}`')
686+
g.n_error('${@LOCATION} unknown variable `${var_name}`')
685687
}
686688
return r
687689
}
688690

689691
fn (mut g Gen) get_field_offset(in_type ast.Type, name string) i32 {
690692
typ := g.unwrap(in_type)
691693
ts := g.table.sym(typ)
692-
field := ts.find_field(name) or { g.n_error('Could not find field `${name}` on init') }
694+
field := ts.find_field(name) or {
695+
g.n_error('${@LOCATION} Could not find field `${name}` on init')
696+
}
693697
return g.structs[typ.idx()].offsets[field.i]
694698
}
695699

@@ -724,7 +728,7 @@ fn (mut g Gen) get_type_size(raw_type ast.Type) i32 {
724728
ast.float_literal_type_idx { 8 }
725729
ast.char_type_idx { 1 }
726730
ast.rune_type_idx { 4 }
727-
else { g.n_error('unknown type size ${typ}') }
731+
else { g.n_error('${@LOCATION} unknown type size ${typ}') }
728732
}
729733
}
730734
if typ.is_bool() {
@@ -835,7 +839,7 @@ fn (mut g Gen) get_sizeof_ident(ident ast.Ident) i32 {
835839
return g.get_type_size(typ)
836840
}
837841
size := g.var_alloc_size[ident.name] or {
838-
g.n_error('unknown variable `${ident}`')
842+
g.n_error('${@LOCATION} unknown variable `${ident}`')
839843
return 0
840844
}
841845
return size
@@ -911,7 +915,7 @@ fn (mut g Gen) eval_escape_codes(str string) string {
911915
`u` {
912916
i++
913917
utf8 := strconv.parse_int(str[i..i + 4], 16, 16) or {
914-
g.n_error('invalid \\u escape code (${str[i..i + 4]})')
918+
g.n_error('${@LOCATION} invalid \\u escape code (${str[i..i + 4]})')
915919
0
916920
}
917921
i += 4
@@ -925,22 +929,22 @@ fn (mut g Gen) eval_escape_codes(str string) string {
925929
`x` {
926930
i++
927931
c := strconv.parse_int(str[i..i + 2], 16, 8) or {
928-
g.n_error('invalid \\x escape code (${str[i..i + 2]})')
932+
g.n_error('${@LOCATION} invalid \\x escape code (${str[i..i + 2]})')
929933
0
930934
}
931935
i += 2
932936
buffer << u8(c)
933937
}
934938
`0`...`7` {
935939
c := strconv.parse_int(str[i..i + 3], 8, 8) or {
936-
g.n_error('invalid escape code \\${str[i..i + 3]}')
940+
g.n_error('${@LOCATION} invalid escape code \\${str[i..i + 3]}')
937941
0
938942
}
939943
i += 3
940944
buffer << u8(c)
941945
}
942946
else {
943-
g.n_error('invalid escape code \\${str[i]}')
947+
g.n_error('${@LOCATION} invalid escape code \\${str[i]}')
944948
}
945949
}
946950
}
@@ -973,7 +977,7 @@ fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) {
973977
g.code_gen.mov_reg(g.code_gen.main_reg(), reg)
974978
}
975979
} else {
976-
g.n_error('int-to-string conversion not implemented for type ${typ}')
980+
g.n_error('${@LOCATION} int-to-string conversion not implemented for type ${typ}')
977981
}
978982
g.println('; to_string }')
979983
}
@@ -986,7 +990,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config Va
986990
g.code_gen.convert_rune_to_string(reg, buffer, var, config)
987991
} else if typ.is_int() {
988992
if typ.is_unsigned() {
989-
g.n_error('Unsigned integer print is not supported')
993+
g.n_error('${@LOCATION} Unsigned integer print is not supported')
990994
} else {
991995
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
992996
end_of_buffer := buffer + 4 + 32 - 1 // 4 bytes for the size and 32 for the chars, -1 to not go out of array
@@ -1001,7 +1005,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config Va
10011005
} else if typ.is_string() {
10021006
g.code_gen.mov_var_to_reg(reg, var, config)
10031007
} else {
1004-
g.n_error('int-to-string conversion not implemented for type ${typ}')
1008+
g.n_error('${@LOCATION} int-to-string conversion not implemented for type ${typ}')
10051009
}
10061010
g.println('; var_to_string }')
10071011
}
@@ -1019,7 +1023,7 @@ fn (mut g Gen) patch_calls() {
10191023
for c in g.callpatches {
10201024
addr := g.fn_addr[c.name]
10211025
if addr == 0 {
1022-
g.n_error('fn addr of `${c.name}` = 0')
1026+
g.n_error('${@LOCATION} fn addr of `${c.name}` = 0')
10231027
return
10241028
}
10251029
last := i32(g.buf.len)
@@ -1038,7 +1042,7 @@ fn (mut g Gen) patch_labels() {
10381042
for label in g.labels.patches {
10391043
addr := g.labels.addrs[label.id]
10401044
if addr == 0 {
1041-
g.n_error('label addr = 0')
1045+
g.n_error('${@LOCATION} label addr = 0')
10421046
return
10431047
}
10441048

‎vlib/v/gen/native/stmt.c.v‎

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ pub fn (mut g Gen) stmts(stmts []ast.Stmt) {
1717
fn (mut g Gen) stmt(node ast.Stmt) {
1818
match node {
1919
ast.AssignStmt {
20-
g.code_gen.assign_stmt(node)
20+
g.assign_stmt(node)
2121
}
2222
ast.Block {
2323
g.stmts(node.stmts)
2424
}
2525
ast.BranchStmt {
2626
label_name := node.label
27+
// break / continue statements in for loops
2728
for i := g.labels.branches.len - 1; i >= 0; i-- {
2829
branch := g.labels.branches[i]
2930
if label_name == '' || label_name == branch.name {
@@ -110,11 +111,15 @@ fn (mut g Gen) stmt(node ast.Stmt) {
110111
ast.TypeDecl {}
111112
ast.InterfaceDecl {}
112113
else {
113-
g.n_error('native.stmt(): bad node: ' + node.type_name())
114+
g.n_error('${@LOCATION} bad node: ' + node.type_name())
114115
}
115116
}
116117
}
117118

119+
fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
120+
g.code_gen.assign_stmt(node)
121+
}
122+
118123
fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
119124
if node.has_init {
120125
g.stmts([node.init])
@@ -144,12 +149,12 @@ fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
144149
jump_addr = g.code_gen.cjmp(.jg)
145150
}
146151
else {
147-
g.n_error('unsupported conditional in for-c loop')
152+
g.n_error('${@LOCATION} unsupported conditional in for-c loop')
148153
}
149154
}
150155
}
151156
else {
152-
g.n_error('unhandled infix.left')
157+
g.n_error('${@LOCATION} unhandled infix.left')
153158
}
154159
}
155160
}
@@ -245,6 +250,7 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
245250
if node.is_range {
246251
g.println('; for ${node.val_var} in range {')
247252
// for a in node.cond .. node.high {
253+
248254
i := g.code_gen.allocate_var(node.val_var, 8, 0) // iterator variable
249255
g.println('; evaluate node.cond for lower bound:')
250256
g.expr(node.cond) // outputs the lower loop bound (initial value) to the main reg
@@ -253,7 +259,6 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
253259
g.code_gen.mov_reg_to_var(LocalVar{i, ast.i64_type_idx, node.val_var}, main_reg) // i = node.cond // initial value
254260

255261
start := g.pos() // label-begin:
256-
start_label := g.labels.new_label()
257262

258263
g.println('; check iterator against upper loop bound')
259264
g.code_gen.mov_var_to_reg(main_reg, LocalVar{i, ast.i64_type_idx, node.val_var})
@@ -267,18 +272,22 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
267272
pos: jump_addr
268273
}
269274
g.println('; jump to label ${end_label} (end_label)')
275+
276+
start_label := g.labels.new_label() // used for continue
270277
g.labels.branches << BranchLabel{
271278
name: node.label
272279
start: start_label
273280
end: end_label
274281
}
275-
276282
g.stmts(node.stmts) // writes the actual body of the loop
277-
g.labels.addrs[start_label] = g.pos()
278-
g.println('; label ${start_label} (start_label)')
283+
284+
g.labels.addrs[start_label] = g.pos() // used for continue (continue: jump before the inc)
285+
g.println('; label ${start_label} (continue_label)')
286+
279287
g.code_gen.inc_var(LocalVar{i, ast.i64_type_idx, node.val_var})
280288
g.labels.branches.pop()
281289
g.code_gen.jmp_back(start) // loops
290+
282291
g.labels.addrs[end_label] = g.pos()
283292
g.println('; label ${end_label} (end_label)')
284293
g.println('; for ${node.val_var} in range }')
@@ -292,11 +301,12 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
292301
} else if it.kind == .map {
293302
*/
294303
} else {
295-
g.n_error('for-in ${node.kind} statement is not yet implemented')
304+
g.n_error('${@LOCATION} for-in ${node.kind} statement is not yet implemented')
296305
}
297306
}
298307

299308
fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
309+
g.println('; gen_assert {')
300310
mut cjmp_addr := i32(0)
301311
ane := assert_node.expr
302312
label := g.labels.new_label()
@@ -306,10 +316,10 @@ fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
306316
pos: cjmp_addr
307317
}
308318
g.println('; jump to label ${label}')
309-
g.expr(assert_node.expr)
310319
g.code_gen.trap()
311320
g.labels.addrs[label] = g.pos()
312321
g.println('; label ${label}')
322+
g.println('; gen_assert }')
313323
}
314324

315325
fn (mut g Gen) gen_flag_hash_stmt(node ast.HashStmt) {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
assert [1, 2, 3] != []
3+
}

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

Whitespace-only changes.

0 commit comments

Comments
 (0)