Skip to content

Commit abfd857

Browse files
authored
native: generalize cmp_to_stack_top and gen_index_expr (#25493)
1 parent 6cbd1e3 commit abfd857

6 files changed

Lines changed: 72 additions & 79 deletions

File tree

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

Lines changed: 14 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,8 @@ fn (mut c Amd64) mov_reg_to_var(var Var, reg Amd64Register, config VarConfig) {
914914
}
915915
}
916916

917+
// does not support 64bits
918+
// TODO: remove and replace by a more general function (like mov_reg_to_var)
917919
fn (mut c Amd64) cg_mov_int_to_var(var Var, integer i32, config VarConfig) {
918920
match var {
919921
ast.Ident {
@@ -2410,7 +2412,7 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
24102412
fn (mut c Amd64) assign_ident_int_lit(node ast.AssignStmt, i i32, int_lit ast.IntegerLiteral, left ast.Ident) {
24112413
match node.op {
24122414
.decl_assign {
2413-
c.cg_allocate_var(left.name, 8, i64(int_lit.val.int()))
2415+
c.cg_allocate_stack_var(left.name, 8, i64(int_lit.val.int()))
24142416
}
24152417
.assign {
24162418
c.mov64(.rax, i64(int_lit.val.int()))
@@ -2518,7 +2520,7 @@ fn (mut c Amd64) mov_float_xmm0_var(reg Amd64Register, var_type ast.Type) {
25182520
}
25192521

25202522
fn (mut c Amd64) cg_create_string_struct(typ ast.Type, name string, str string) i32 {
2521-
dest := c.cg_allocate_var(name, c.g.get_type_size(typ), i64(0))
2523+
dest := c.cg_allocate_stack_var(name, c.g.get_type_size(typ), i64(0))
25222524
c.learel(.rax, c.g.allocate_string(str, 3, .rel32))
25232525
c.cg_mov_reg_to_var(LocalVar{dest, ast.u64_type_idx, name}, .reg0)
25242526
offset := c.g.get_field_offset(typ, 'len')
@@ -2547,7 +2549,7 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
25472549
match val {
25482550
Number {
25492551
if node.op == .decl_assign {
2550-
c.cg_allocate_var(ident.name, enum_info.size, val)
2552+
c.cg_allocate_stack_var(ident.name, enum_info.size, val)
25512553
} else {
25522554
c.mov64(.rax, val)
25532555
c.cg_mov_reg_to_var(ident, .reg0)
@@ -2695,7 +2697,7 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
26952697
return
26962698
}
26972699
ast.AtExpr {
2698-
dest := c.cg_allocate_var(name, 8, i64(0))
2700+
dest := c.cg_allocate_stack_var(name, 8, i64(0))
26992701
c.learel(.rsi, c.g.allocate_string(c.g.comptime_at(right), 3, .rel32))
27002702
c.mov_reg_to_var(LocalVar{dest, ast.u64_type_idx, name}, .rsi)
27012703
}
@@ -2814,7 +2816,7 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
28142816
/*
28152817
ast.IndexExpr {
28162818
// a := arr[0]
2817-
offset := c.cg_allocate_var(name, c.g.get_sizeof_ident(ident), 0)
2819+
offset := c.cg_allocate_stack_var(name, c.g.get_sizeof_ident(ident), 0)
28182820
if c.g.pref.is_verbose {
28192821
println('infix assignment ${name} offset=${offset.hex2()}')
28202822
}
@@ -2843,43 +2845,6 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
28432845
}*/
28442846
}
28452847

2846-
fn (mut c Amd64) cg_gen_index_expr(node ast.IndexExpr) {
2847-
if node.left_type.is_string() {
2848-
c.g.expr(node.index)
2849-
c.push(.rax)
2850-
2851-
c.g.expr(node.left) // load address of string struct
2852-
c.mov_deref(.rax, .rax, ast.u64_type_idx) // load value of the str pointer
2853-
2854-
c.pop(.rdx) // index
2855-
c.add_reg(.rax, .rdx) // add the offset to the address
2856-
} else if node.left_type.is_any_kind_of_pointer() {
2857-
// load the pointer
2858-
c.g.expr(node.left)
2859-
c.mov_reg(.rcx, .rax)
2860-
// add the index times the size (bytes) of the type
2861-
c.g.expr(node.index)
2862-
c.mov(.rbx, i32(c.g.get_type_size(node.typ)))
2863-
c.mul_reg_rax(.rbx)
2864-
c.add_reg(.rax, .rcx)
2865-
} else if node.is_array {
2866-
// TODO: use functions from builtin instead (array.set, array.get...)
2867-
c.g.expr(node.left)
2868-
offset := c.g.get_field_offset(ast.array_type, 'data')
2869-
if offset != 0 {
2870-
c.add(.rax, offset)
2871-
}
2872-
c.mov_deref(.rcx, .rax, ast.u64_type)
2873-
// add the index times the size (bytes) of the type
2874-
c.g.expr(node.index)
2875-
c.mov(.rbx, i32(c.g.get_type_size(node.typ)))
2876-
c.mul_reg_rax(.rbx)
2877-
c.add_reg(.rax, .rcx)
2878-
} else {
2879-
c.g.n_error('${@LOCATION} index expr: unhandled node type {node}')
2880-
}
2881-
}
2882-
28832848
// /!\ for div, mul, mod the left value should always be .rax
28842849
fn (mut c Amd64) apply_op_int(left_value Amd64Register, right_value Amd64Register, op token.Kind) {
28852850
match op {
@@ -4044,7 +4009,7 @@ fn (mut c Amd64) cg_fn_decl(node ast.FnDecl) {
40444009
// define defer vars
40454010
for i in 0 .. node.defer_stmts.len {
40464011
name := '_defer${i}'
4047-
c.cg_allocate_var(name, 8, i64(0))
4012+
c.cg_allocate_stack_var(name, 8, i64(0))
40484013
}
40494014
// body
40504015
c.g.stmts(node.stmts)
@@ -4084,14 +4049,14 @@ pub fn (mut c Amd64) cg_builtin_decl(builtin BuiltinFn) {
40844049
c.cg_leave()
40854050
}
40864051

4087-
pub fn (mut c Amd64) allocate_var_two_step(name string, size i32, initial_val Number) i32 {
4088-
c.cg_allocate_var(name, size - 8, i64(0))
4089-
return c.cg_allocate_var(name, 8, initial_val)
4052+
pub fn (mut c Amd64) allocate_stack_var_two_step(name string, size i32, initial_val Number) i32 {
4053+
c.cg_allocate_stack_var(name, size - 8, i64(0))
4054+
return c.cg_allocate_stack_var(name, 8, initial_val)
40904055
}
40914056

4092-
pub fn (mut c Amd64) cg_allocate_var(name string, size i32, initial_val Number) i32 {
4057+
pub fn (mut c Amd64) cg_allocate_stack_var(name string, size i32, initial_val Number) i32 {
40934058
if size > 8 {
4094-
return c.allocate_var_two_step(name, size, initial_val)
4059+
return c.allocate_stack_var_two_step(name, size, initial_val)
40954060
}
40964061

40974062
padding := (size - c.g.stack_var_pos % size) % size
@@ -4605,6 +4570,7 @@ fn (mut c Amd64) cg_gen_match_expr(expr ast.MatchExpr) {
46054570
for cond in branch.exprs {
46064571
match cond {
46074572
ast.RangeExpr {
4573+
// TODO: clean up
46084574
c.pop(.rdx)
46094575
c.g.expr(cond.low)
46104576
c.cmp_reg(.rax, .rdx)
@@ -5084,16 +5050,6 @@ fn (mut c Amd64) cg_gen_cast_expr(expr ast.CastExpr) {
50845050
}
50855051
}
50865052

5087-
fn (mut c Amd64) cg_cmp_to_stack_top(reg Register) {
5088-
second_reg := if reg.amd64() == Amd64Register.rbx {
5089-
Amd64Register.rax
5090-
} else {
5091-
Amd64Register.rbx
5092-
}
5093-
c.pop(second_reg)
5094-
c.cmp_reg(second_reg, reg.amd64())
5095-
}
5096-
50975053
// Temporary!
50985054
fn (mut c Amd64) adr(r Arm64Register, delta i32) {
50995055
c.g.n_error('`adr` instruction not supported with amd64')

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ mut:
5454
// arm64 specific stuff for code generation
5555
}
5656

57-
fn (mut x Arm64) cg_allocate_var(name string, size i32, initial_val Number) i32 {
57+
fn (mut x Arm64) cg_allocate_stack_var(name string, size i32, initial_val Number) i32 {
5858
eprintln('TODO: allocating var on arm64 (${name}) = ${size} = ${initial_val}')
5959
return 0
6060
}
@@ -522,10 +522,6 @@ fn (mut c Arm64) cg_call_addr_at(addr i32, at i64) i64 {
522522
panic('Arm64.cg_call_addr_at() not implemented')
523523
}
524524

525-
fn (mut c Arm64) cg_cmp_to_stack_top(reg Register) {
526-
panic('Arm64.cg_cmp_to_stack_top() not implemented')
527-
}
528-
529525
fn (mut c Arm64) cg_push(r Register) {
530526
panic('Arm64.cg_push() not implemented')
531527
}
@@ -561,7 +557,3 @@ fn (mut c Arm64) cg_patch_relative_jmp(pos i32, addr i64) {
561557
fn (mut c Arm64) cg_mul_reg(a Register, b Register) {
562558
panic('Arm64.cg_mul_reg() not implemented')
563559
}
564-
565-
fn (mut c Arm64) cg_gen_index_expr(node ast.IndexExpr) {
566-
panic('Arm64.cg_gen_index_expr{) not implemented')
567-
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module native
77
import v.ast
88
99
fn (mut g Gen) allocate_raw_array(name string, size i32, items i32) i32 {
10-
pos := g.cg.cg_allocate_var(name, size, items)
10+
pos := g.cg.cg_allocate_stack_var(name, size, items)
1111
g.stack_var_pos += (size * items)
1212
return pos
1313
}

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

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn (mut g Gen) expr(node ast.Expr) {
150150
g.gen_sizeof_expr(node)
151151
}
152152
ast.IndexExpr {
153-
g.cg.cg_gen_index_expr(node)
153+
g.gen_index_expr(node)
154154
if node.left_type.is_string() {
155155
g.cg.cg_mov_deref(.reg0, .reg0, ast.u8_type_idx)
156156
} else {
@@ -556,7 +556,7 @@ fn (mut g Gen) gen_left_value(node ast.Expr) {
556556
g.expr(node) // TODO: add a test that uses this
557557
}
558558
ast.IndexExpr {
559-
g.cg.cg_gen_index_expr(node)
559+
g.gen_index_expr(node)
560560
}
561561
ast.PrefixExpr {
562562
if node.op != .mul {
@@ -569,3 +569,40 @@ fn (mut g Gen) gen_left_value(node ast.Expr) {
569569
}
570570
}
571571
}
572+
573+
fn (mut g Gen) gen_index_expr(node ast.IndexExpr) {
574+
if node.left_type.is_string() {
575+
g.expr(node.index)
576+
g.cg.cg_push(.reg0)
577+
578+
g.expr(node.left) // load address of string struct
579+
g.cg.cg_mov_deref(.reg0, .reg0, ast.u64_type_idx) // load value of the str pointer
580+
581+
g.cg.cg_pop(.reg2) // index
582+
g.cg.cg_add_reg(.reg0, .reg2) // add the offset to the address
583+
} else if node.left_type.is_any_kind_of_pointer() {
584+
// load the pointer
585+
g.expr(node.left)
586+
g.cg.cg_mov_reg(.reg1, .reg0)
587+
// add the index times the size (bytes) of the type
588+
g.expr(node.index)
589+
g.cg.cg_mov(.reg3, i32(g.get_type_size(node.typ)))
590+
g.cg.cg_mul_reg(.reg0, .reg3)
591+
g.cg.cg_add_reg(.reg0, .reg1)
592+
} else if node.is_array {
593+
// TODO: use functions from builtin instead (array.set, array.get...)
594+
g.expr(node.left)
595+
offset := g.get_field_offset(ast.array_type, 'data')
596+
if offset != 0 {
597+
g.cg.cg_add(.reg0, offset)
598+
}
599+
g.cg.cg_mov_deref(.reg1, .reg0, ast.u64_type)
600+
// add the index times the size (bytes) of the type
601+
g.expr(node.index)
602+
g.cg.cg_mov(.reg3, i32(g.get_type_size(node.typ)))
603+
g.cg.cg_mul_reg(.reg0, .reg3)
604+
g.cg.cg_add_reg(.reg0, .reg1)
605+
} else {
606+
g.n_error('${@LOCATION} index expr: unhandled node type {node}')
607+
}
608+
}

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,14 @@ mut:
9797
cg_add(r Register, val i32)
9898
cg_add_reg(r Register, r2 Register)
9999
cg_address_size() i32
100-
cg_allocate_var(name string, size i32, initial_val Number) i32
100+
cg_allocate_stack_var(name string, size i32, initial_val Number) i32
101101
cg_assign_stmt(node ast.AssignStmt)
102102
cg_builtin_decl(builtin BuiltinFn)
103103
cg_call_addr_at(addr i32, at i64) i64
104104
cg_call_builtin(name Builtin) i64
105105
cg_call_fn(node ast.CallExpr)
106106
cg_call(addr i32) i64
107107
cg_cjmp(op JumpOp) i32
108-
cg_cmp_to_stack_top(r Register)
109108
cg_cmp_var_reg(var Var, reg Register, config VarConfig)
110109
cg_cmp_var(var Var, val i32, config VarConfig)
111110
cg_cmp_reg(reg Register, reg2 Register)
@@ -119,7 +118,6 @@ mut:
119118
cg_gen_asm_stmt(asm_node ast.AsmStmt)
120119
cg_gen_cast_expr(expr ast.CastExpr)
121120
cg_gen_exit(expr ast.Expr)
122-
cg_gen_index_expr(ast.IndexExpr)
123121
cg_gen_match_expr(expr ast.MatchExpr)
124122
cg_gen_print_reg(r Register, n i32, fd i32)
125123
cg_gen_print(s string, fd i32)
@@ -1046,7 +1044,7 @@ fn (mut g Gen) allocate_string(s string, opsize i32, typ RelocType) i32 {
10461044
// allocates a buffer variable: name, size of stored type (nb of bytes), nb of items
10471045
fn (mut g Gen) allocate_array(name string, size i32, items i32) i32 {
10481046
g.println('; allocate array `${name}` item-size:${size} items:${items}:')
1049-
pos := g.cg.cg_allocate_var(name, 4, i64(items)) // store the length of the array on the stack in a 4 byte var
1047+
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
10501048
g.stack_var_pos += (size * items) // reserve space on the stack for the items
10511049
return pos
10521050
}
@@ -1167,7 +1165,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config Va
11671165
g.println('; var_to_string {')
11681166
typ := g.get_type_from_var(var)
11691167
if typ == ast.rune_type_idx {
1170-
buffer := g.cg.cg_allocate_var('rune-buffer', 8, i64(0))
1168+
buffer := g.cg.cg_allocate_stack_var('rune-buffer', 8, i64(0))
11711169
g.cg.cg_convert_rune_to_string(reg, buffer, var, config)
11721170
} else if typ.is_int() {
11731171
if typ.is_unsigned() {
@@ -1437,3 +1435,13 @@ pub fn escape_string(s string) string {
14371435
}
14381436
return out.bytestr()
14391437
}
1438+
1439+
fn (mut g Gen) cmp_to_stack_top(reg Register) {
1440+
second_reg := if reg == .reg3 {
1441+
Register.reg0
1442+
} else {
1443+
Register.reg3
1444+
}
1445+
g.cg.cg_pop(second_reg)
1446+
g.cg.cg_cmp_reg(second_reg, reg)
1447+
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
266266
g.println('; for ${node.val_var} in range {')
267267
// for a in node.cond .. node.high {
268268

269-
i := g.cg.cg_allocate_var(node.val_var, 8, i64(0)) // iterator variable
269+
i := g.cg.cg_allocate_stack_var(node.val_var, 8, i64(0)) // iterator variable
270270
g.println('; evaluate node.cond for lower bound:')
271271
g.expr(node.cond) // outputs the lower loop bound (initial value) to the main reg
272272
g.println('; move the result to i')
@@ -278,7 +278,7 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
278278
g.cg.cg_mov_var_to_reg(.reg0, LocalVar{i, ast.i64_type_idx, node.val_var})
279279
g.cg.cg_push(.reg0) // put the iterator on the stack
280280
g.expr(node.high) // final value (upper bound) to the main reg
281-
g.cg.cg_cmp_to_stack_top(.reg0)
281+
g.cmp_to_stack_top(.reg0)
282282
jump_addr := g.cg.cg_cjmp(.jge) // leave loop i >= upper bound
283283
end_label := g.labels.new_label()
284284
g.labels.patches << LabelPatch{
@@ -310,8 +310,8 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
310310
// for c in my_string {
311311

312312
key_var := if node.key_var == '' { 'i' } else { node.key_var }
313-
i := g.cg.cg_allocate_var(key_var, 8, i64(0)) // iterator variable
314-
c := g.cg.cg_allocate_var(node.val_var, 1, i64(0)) // char variable
313+
i := g.cg.cg_allocate_stack_var(key_var, 8, i64(0)) // iterator variable
314+
c := g.cg.cg_allocate_stack_var(node.val_var, 1, i64(0)) // char variable
315315

316316
g.expr(node.cond) // get the address of the string variable
317317
g.cg.cg_mov_deref(.reg2, .reg0, ast.charptr_type)

0 commit comments

Comments
 (0)