Skip to content

Commit

Permalink
native: fix inc and improve support for i32 (#23753)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eliyaan authored Feb 17, 2025
1 parent f2672b1 commit dbc96b2
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 17 deletions.
40 changes: 32 additions & 8 deletions vlib/v/gen/native/amd64.v
Original file line number Diff line number Diff line change
Expand Up @@ -400,26 +400,51 @@ fn (mut c Amd64) inc_var(var Var, config VarConfig) {
c.inc_var(var_object as GlobalVar, config)
}
Register {
c.g.n_error('Register incrementation is not supported yet')
// TODO
// g.inc()
}
}
}
LocalVar {
// TODO: size
c.g.write8(0x81) // 83 for 1 byte
typ := c.g.unwrap(var.typ)
mut size_str := 'UNKNOWN'
offset := var.offset - config.offset
is_far_var := offset > 0x80 || offset < -0x7f
match typ {
ast.i64_type_idx, ast.u64_type_idx, ast.isize_type_idx, ast.usize_type_idx,
ast.int_literal_type_idx {
c.g.write16(0xFF48)
size_str = 'QWORD'
}
ast.i32_type_idx, ast.int_type_idx, ast.u32_type_idx, ast.rune_type_idx {
c.g.write8(0xFF)
size_str = 'DWORD'
}
ast.i16_type_idx, ast.u16_type_idx {
c.g.write8(0xFF)
size_str = 'WORD'
}
ast.i8_type_idx, ast.u8_type_idx, ast.char_type_idx {
c.g.write8(0xFE)
size_str = 'BYTE'
}
else {
ts := c.g.table.sym(typ.idx_type())
c.g.n_error('unsupported type for inc_var ${ts.info}')
}
}

c.g.write8(if is_far_var { i32(0x85) } else { i32(0x45) })
if is_far_var {
c.g.write32(i32((0xffffffff - i64(offset) + 1) % 0x100000000))
} else {
c.g.write8((0xff - offset + 1) % 0x100)
}
c.g.write32(1)
c.g.println('inc_var `${var.name}`')
c.g.println('inc_var ${size_str} `${var.name}`')
}
GlobalVar {
c.g.n_error('Global variables incrementation is not supported yet')
// TODO
}
}
Expand Down Expand Up @@ -643,7 +668,7 @@ fn (mut c Amd64) mov_reg_to_var(var Var, r Register, config VarConfig) {
c.g.write16(0x8948 + if is_extended_register { i32(4) } else { i32(0) })
size_str = 'QWORD'
}
ast.int_type_idx, ast.u32_type_idx, ast.rune_type_idx {
ast.i32_type_idx, ast.int_type_idx, ast.u32_type_idx, ast.rune_type_idx {
if is_extended_register {
c.g.write8(0x44)
}
Expand Down Expand Up @@ -694,7 +719,7 @@ fn (mut c Amd64) mov_reg_to_var(var Var, r Register, config VarConfig) {
} else {
c.g.write8((0xff - offset + 1) % 0x100)
}
c.g.println('mov ${size_str} PTR [rbp-${int(offset).hex2()}],${reg}')
c.g.println('mov ${size_str} PTR [rbp-${int(offset).hex2()}],${reg} ; `${var.name}`')
}
GlobalVar {
// TODO
Expand Down Expand Up @@ -746,7 +771,7 @@ fn (mut c Amd64) mov_int_to_var(var Var, integer i32, config VarConfig) {
c.g.write16(u16(integer))
c.g.println('mov WORD PTR[rbp-${int(offset).hex2()}], ${integer}')
}
ast.int_type_idx, ast.u32_type_idx, ast.rune_type_idx {
ast.i32_type_idx, ast.int_type_idx, ast.u32_type_idx, ast.rune_type_idx {
c.g.write8(0xc7)
c.g.write8(if is_far_var { i32(0x85) } else { i32(0x45) })
if is_far_var {
Expand Down Expand Up @@ -832,7 +857,6 @@ fn (mut c Amd64) mov_var_to_reg(reg Register, var Var, config VarConfig) {
typ := if config.typ == 0 { var.typ } else { config.typ }
size := c.g.get_type_size(typ)
is_signed := !typ.is_any_kind_of_pointer() && typ.is_signed()

instruction, size_str := match true {
size == 4 && is_signed {
// movsxd rax, DWORD PTR [rbp-0x8]
Expand Down
5 changes: 3 additions & 2 deletions vlib/v/gen/native/gen.v
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,8 @@ fn (mut g Gen) get_type_size(raw_type ast.Type) i32 {
ast.u8_type_idx { 1 }
ast.i16_type_idx { 2 }
ast.u16_type_idx { 2 }
ast.int_type_idx { 4 }
ast.int_type_idx { 4 } // TODO: change when V will have changed
ast.i32_type_idx { 4 }
ast.u32_type_idx { 4 }
ast.i64_type_idx { 8 }
ast.u64_type_idx { 8 }
Expand All @@ -722,7 +723,7 @@ fn (mut g Gen) get_type_size(raw_type ast.Type) i32 {
ast.float_literal_type_idx { 8 }
ast.char_type_idx { 1 }
ast.rune_type_idx { 4 }
else { 8 }
else { g.n_error('unknown type size ${typ}') }
}
}
if typ.is_bool() {
Expand Down
20 changes: 13 additions & 7 deletions vlib/v/gen/native/stmt.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -243,50 +243,56 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {

fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
if node.is_range {
g.println('; for ${node.val_var} in range {')
// for a in node.cond .. node.high {
i := g.code_gen.allocate_var(node.val_var, 8, 0) // iterator variable
g.println('; evaluate node.cond for lower bound:')
g.expr(node.cond) // outputs the lower loop bound (initial value) to the main reg
main_reg := g.code_gen.main_reg()
g.println('; move the result to i')
g.code_gen.mov_reg_to_var(LocalVar{i, ast.i64_type_idx, node.val_var}, main_reg) // i = node.cond // initial value

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

g.println('; check iterator against upper loop bound')
g.code_gen.mov_var_to_reg(main_reg, LocalVar{i, ast.i64_type_idx, node.val_var})
g.code_gen.push(main_reg) // put the iterator on the stack
g.expr(node.high) // final value (upper bound) to the main reg
g.code_gen.cmp_to_stack_top(main_reg)
jump_addr := g.code_gen.cjmp(.jge) // leave loop i >= upper bound

end_label := g.labels.new_label()
g.labels.patches << LabelPatch{
id: end_label
pos: jump_addr
}
g.println('; jump to label ${end_label}')
g.println('; jump to label ${end_label} (end_label)')
g.labels.branches << BranchLabel{
name: node.label
start: start_label
end: end_label
}

g.stmts(node.stmts) // writes the actual body of the loop
g.labels.addrs[start_label] = g.pos()
g.println('; label ${start_label}')
g.println('; label ${start_label} (start_label)')
g.code_gen.inc_var(LocalVar{i, ast.i64_type_idx, node.val_var})
g.labels.branches.pop()
g.code_gen.jmp_back(start) // loops
g.labels.addrs[end_label] = g.pos()
g.println('; label ${end_label}')
g.println('; label ${end_label} (end_label)')
g.println('; for ${node.val_var} in range }')
/*
} else if node.kind == .array {
} else if node.kind == .array {
} else if node.kind == .array_fixed {
} else if node.kind == .map {
} else if node.kind == .string {
} else if node.kind == .struct {
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
} else if it.kind == .map {
*/
*/
} else {
g.v_error('for-in statement is not yet implemented', node.pos)
g.n_error('for-in ${node.kind} statement is not yet implemented')
}
}

Expand Down
48 changes: 48 additions & 0 deletions vlib/v/gen/native/tests/inc.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
fn signed_inc_test() {
mut a := i64(1)
println(a)
a++
println(a)
mut b := i32(1)
println(b)
b++
println(b)
mut c := i16(1)
println(c)
c++
println(c)
mut d := i8(1)
println(d)
d++
println(d)
mut e := int(1)
println(e)
e++
println(e)

// TODO: negative inc test (when negative ints will be supported)
}

fn unsigned_inc_test() {
mut f := u64(1)
println(f)
f++
println(f)
mut g := u32(1)
println(g)
g++
println(g)
mut h := u16(1)
println(h)
h++
println(h)
mut i := u8(1)
println(i)
i++
println(i)
}

fn main() {
signed_inc_test()
unsigned_inc_test()
}
18 changes: 18 additions & 0 deletions vlib/v/gen/native/tests/inc.vv.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
1
2
1
2
1
2
1
2
1
2
1
2
1
2
1
2
1
2
1 change: 1 addition & 0 deletions vlib/v/gen/native/tests/native_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ fn test_native() {
eprintln('------------------------------------------------')
eprintln('> tmperrfile: ${tmperrfile}, exists: ${os.exists(tmperrfile)}, content:')
errstr := os.read_file(tmperrfile) or { '' }
eprintln('------------------------------------------------')
eprintln(errstr)
eprintln('------------------------------------------------')
eprintln('')
Expand Down

0 comments on commit dbc96b2

Please sign in to comment.