Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

native: fix int prints #23747

Merged
merged 3 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions vlib/v/gen/native/amd64.v
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,7 @@ fn (mut c Amd64) gen_print(s string, fd i32) {
c.g.println('; print }')
}

// write a string of size n stored in r to fd
pub fn (mut c Amd64) gen_print_reg(r Register, n i32, fd i32) {
c.g.println('; print_reg: (reg:${r} fd:${fd} len:${n}) {')
str_reg := if c.g.pref.os == .windows { Amd64Register.rdx } else { Amd64Register.rsi }
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/native/builtins.v
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn (mut g Gen) init_builtins() {
body: fn (builtin BuiltinFn, mut g Gen) {
g.code_gen.convert_int_to_string(builtin.arg_regs[0], builtin.arg_regs[1])
}
arg_regs: [Amd64Register.rcx, Amd64Register.rdi]
arg_regs: [Amd64Register.rcx, Amd64Register.rdi] // rcx: int to convert, rdi: end of 32byte buffer (with 4 bytes at the beggining for len) see allocate_array
}
.bool_to_string: BuiltinFn{
body: fn (builtin BuiltinFn, mut g Gen) {
Expand Down
12 changes: 7 additions & 5 deletions vlib/v/gen/native/gen.v
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ fn (mut g Gen) allocate_string(s string, opsize i32, typ RelocType) i32 {
// allocates a buffer variable: name, size of stored type (nb of bytes), nb of items
fn (mut g Gen) allocate_array(name string, size i32, items i32) i32 {
g.println('; allocate array `${name}` item-size:${size} items:${items}:')
pos := g.code_gen.allocate_var(name, size, items) // store the lenght of the array on the stack
pos := g.code_gen.allocate_var(name, 4, items) // store the lenght of the array on the stack in a 4 byte var
g.stack_var_pos += (size * items) // reserve space on the stack for the items
return pos
}
Expand Down Expand Up @@ -950,15 +950,16 @@ fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) {
g.println('; to_string (reg:${reg}) {')
if typ.is_int() {
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
g.code_gen.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), buffer)
end_of_buffer := buffer + 4 + 32 - 1 // 4 bytes for the size and 32 for the chars, -1 to not go out of array
g.code_gen.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), end_of_buffer)

arg0_reg := g.get_builtin_arg_reg(.int_to_string, 0)
if arg0_reg != reg {
g.code_gen.mov_reg(arg0_reg, reg)
}

g.call_builtin(.int_to_string)
g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), buffer)
g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), end_of_buffer) // the (int) string starts at the end of the buffer
} else if typ.is_bool() {
arg_reg := g.get_builtin_arg_reg(.bool_to_string, 0)
if arg_reg != reg {
Expand All @@ -983,10 +984,11 @@ fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config Va
g.code_gen.convert_rune_to_string(reg, buffer, var, config)
} else if typ.is_int() {
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
end_of_buffer := buffer + 4 + 32 - 1 // 4 bytes for the size and 32 for the chars, -1 to not go out of array
g.code_gen.mov_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 0), var, config)
g.code_gen.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), buffer)
g.code_gen.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), end_of_buffer)
g.call_builtin(.int_to_string)
g.code_gen.lea_var_to_reg(reg, buffer)
g.code_gen.lea_var_to_reg(reg, end_of_buffer) // the (int) string starts at the end of the buffer
} else if typ.is_bool() {
g.code_gen.mov_var_to_reg(g.get_builtin_arg_reg(.bool_to_string, 0), var, config)
g.call_builtin(.bool_to_string)
Expand Down
14 changes: 14 additions & 0 deletions vlib/v/gen/native/tests/print.vv
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ fn test_intermediate() {
println(c)
}

fn test_for_range() {
for i in 0 .. 10 {
println(i)
}
}

fn test_2_in_a_row() {
a := 12345
println(a)
println(a)
}

fn main() {
test_stdout()
test_stderr()
Expand All @@ -120,4 +132,6 @@ fn main() {
test_sizeof()
test_interpolated()
test_intermediate()
test_for_range()
test_2_in_a_row()
}
12 changes: 12 additions & 0 deletions vlib/v/gen/native/tests/print.vv.out
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,15 @@ sizeof: 4, 12
this is an interpolated string
num: 42; bool: true
0
0
1
2
3
4
5
6
7
8
9
12345
12345
Loading