diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index e87b54f8356238..03a8370696b3fc 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -457,7 +457,7 @@ fn (op JumpOp) amd64() u16 { fn (mut c Amd64) cjmp(op JumpOp) i32 { c.g.write16(op.amd64()) pos := c.g.pos() - c.g.write32(placeholder) + c.g.write32(placeholder) // will get replaced by the right address c.g.println('${op}') return i32(pos) } @@ -466,7 +466,7 @@ fn (mut c Amd64) jmp(addr i32) i32 { c.g.write8(0xe9) pos := c.g.pos() c.g.write32(addr) // 0xffffff - c.g.println('jmp') + c.g.println('jmp ${int(pos + addr).hex2()}') // return the position of jump address for placeholder return i32(pos) } @@ -603,7 +603,7 @@ fn (mut c Amd64) mov_store(regptr Amd64Register, reg Amd64Register, size Size) { } c.g.write8(if size == ._8 { i32(0x88) } else { i32(0x89) }) c.g.write8(i32(reg) % 8 * 8 + i32(regptr) % 8) - c.g.println('mov [${regptr}], ${reg}') + c.g.println('mov [${regptr}], ${reg} ; size:${size}bits') } fn (mut c Amd64) mov_reg_to_var(var Var, r Register, config VarConfig) { @@ -885,7 +885,7 @@ fn (mut c Amd64) mov_var_to_reg(reg Register, var Var, config VarConfig) { } else { c.g.write8((0xff - offset + 1) % 0x100) } - c.g.println('${instruction} ${reg}, ${size_str} PTR [rbp-${int(offset).hex2()}]') + c.g.println('${instruction} ${reg}, ${size_str} PTR [rbp-${int(offset).hex2()}] ; `${var.name}`') } GlobalVar { // TODO @@ -1263,6 +1263,7 @@ pub fn (mut c Amd64) test_reg(r Amd64Register) { // return length in .rax of string pointed by given register pub fn (mut c Amd64) inline_strlen(r Amd64Register) { + c.g.println('; inline_strlen: (reg:${r}) {') c.mov_reg(Amd64Register.rdi, r) c.mov(Amd64Register.rcx, -1) c.mov(Amd64Register.eax, 0) @@ -1271,6 +1272,7 @@ pub fn (mut c Amd64) inline_strlen(r Amd64Register) { c.dec(.rcx) c.mov_reg(Amd64Register.rax, Amd64Register.rcx) c.g.println('strlen rax, ${r}') + c.g.println('; inline_strlen }') } pub fn (mut c Amd64) get_dllcall_addr(import_addr i64) i64 { @@ -1296,6 +1298,7 @@ pub fn (mut c Amd64) dllcall(symbol string) { } fn (mut c Amd64) gen_print(s string, fd i32) { + c.g.println('; print: (fd:${fd} s:\'${s}\') {') if c.g.pref.os == .windows { c.sub(.rsp, 0x38) c.mov(Amd64Register.rcx, -10 - fd) @@ -1317,9 +1320,11 @@ fn (mut c Amd64) gen_print(s string, fd i32) { c.mov(Amd64Register.edx, i32(s.len)) // len c.syscall() } + c.g.println('; print }') } 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 } len_reg := if c.g.pref.os == .windows { Amd64Register.r8 } else { Amd64Register.rdx } c.mov_reg(str_reg, r) @@ -1347,6 +1352,7 @@ pub fn (mut c Amd64) gen_print_reg(r Register, n i32, fd i32) { c.mov(Amd64Register.edi, fd) c.syscall() } + c.g.println('; print_reg }') } pub fn (mut c Amd64) gen_exit(expr ast.Expr) { @@ -1590,10 +1596,9 @@ fn (mut c Amd64) div_reg(a Amd64Register, b Amd64Register) { c.g.write8(0xf8) } .rbx { - c.mov(Amd64Register.edx, 0) c.g.write8(0x48) c.g.write8(0xf7) - c.g.write8(0xfb) // idiv ebx + c.g.write8(0xfb) } .rdx { c.g.write8(0x48) @@ -1937,8 +1942,8 @@ pub fn (mut c Amd64) call_fn(node ast.CallExpr) { } fn (mut c Amd64) call_builtin(name Builtin) i64 { - call_addr := c.call(0) - c.g.println('call builtin `${name}`') + c.g.println('; call builtin `${name}`: (the 0 will get replaced)') + call_addr := c.call(0) // the 0 will get replaced by the right addr when the function will be generated return call_addr } @@ -3478,6 +3483,13 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) { c.g.write8(0x30) c.g.println("mov BYTE PTR [rdi], '0'") + // null terminate the string + c.inc(.rdi) + c.g.write8(0xc6) + c.g.write8(0x07) + c.g.write8(0x0) + c.g.println('mov BYTE PTR [rdi], `\0`') + end_label := c.g.labels.new_label() end_jmp_addr := c.jmp(0) c.g.labels.patches << LabelPatch{ @@ -3513,32 +3525,18 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) { c.g.labels.addrs[skip_minus_label] = c.g.pos() c.g.println('; label ${skip_minus_label}') - c.mov_reg(Amd64Register.r12, Amd64Register.rdi) // copy the buffer position to r12 + c.mov_reg(Amd64Register.r12, Amd64Register.rdi) // copy the buffer position (start of the number without `-`) to r12 loop_label := c.g.labels.new_label() loop_start := c.g.pos() c.g.println('; label ${loop_label}') - c.push(Amd64Register.rax) - - c.mov(Amd64Register.rdx, 0) + c.mov(Amd64Register.rdx, 0) // upperhalf of the dividend c.mov(Amd64Register.rbx, 10) - c.div_reg(.rax, .rbx) - c.add8(.rdx, '0'[0]) + c.div_reg(.rax, .rbx) // rax will be the result of the division + c.add8(.rdx, i32(`0`)) // rdx is the remainder, add 48 to convert it into it's ascii representation - c.g.write8(0x66) - c.g.write8(0x89) - c.g.write8(0x17) - c.g.println('mov BYTE PTR [rdi], rdx') - - // divide the integer in rax by 10 for next iteration - c.pop(.rax) - c.mov(Amd64Register.rbx, 10) - c.cdq() - c.g.write8(0x48) - c.g.write8(0xf7) - c.g.write8(0xfb) - c.g.println('idiv rbx') + c.mov_store(.rdi, .rdx, ._8) // go to the next character c.inc(.rdi) @@ -3550,9 +3548,15 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) { id: loop_label pos: loop_cjmp_addr } - c.g.println('; jump to label ${skip_minus_label}') + c.g.println('; jump to label ${loop_label}') c.g.labels.addrs[loop_label] = loop_start + // null terminate the string + c.g.write8(0xc6) + c.g.write8(0x07) + c.g.write8(0x0) + c.g.println('mov BYTE PTR [rdi], `\0`') + // after all was converted, reverse the string reg := c.g.get_builtin_arg_reg(.reverse_string, 0) as Amd64Register c.mov_reg(reg, Amd64Register.r12) @@ -3569,8 +3573,6 @@ fn (mut c Amd64) reverse_string(r Register) { c.mov_reg(Amd64Register.rdi, reg) } - c.mov(Amd64Register.eax, 0) - c.g.write8(0x48) c.g.write8(0x8d) c.g.write8(0x48) @@ -3579,9 +3581,9 @@ fn (mut c Amd64) reverse_string(r Register) { c.mov_reg(Amd64Register.rsi, Amd64Register.rdi) - c.g.write8(0xf2) - c.g.write8(0xae) - c.g.println('repnz scas al, BYTE PTR es:[rdi]') + // search for null at end of string + c.mov(Amd64Register.eax, 0) + c.cld_repne_scasb() c.sub8(.rdi, 0x2) c.cmp_reg(.rdi, .rsi) diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index 458fd63a2d1358..27c78e35e5d38b 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -856,9 +856,11 @@ fn (mut g Gen) allocate_string(s string, opsize i32, typ RelocType) i32 { return str_pos } +// 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 { - pos := g.code_gen.allocate_var(name, size, items) - g.stack_var_pos += (size * items) + 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 + g.stack_var_pos += (size * items) // reserve space on the stack for the items return pos } @@ -945,6 +947,7 @@ fn (mut g Gen) eval_escape_codes(str string) string { } 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) @@ -969,9 +972,11 @@ fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) { } else { g.n_error('int-to-string conversion not implemented for type ${typ}') } + g.println('; to_string }') } fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config VarConfig) { + g.println('; var_to_string {') typ := g.get_type_from_var(var) if typ == ast.rune_type_idx { buffer := g.code_gen.allocate_var('rune-buffer', 8, 0) @@ -990,6 +995,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config Va } else { g.n_error('int-to-string conversion not implemented for type ${typ}') } + g.println('; var_to_string }') } fn (mut g Gen) is_used_by_main(node ast.FnDecl) bool { diff --git a/vlib/v/gen/native/tests/print.vv b/vlib/v/gen/native/tests/print.vv index 9dde6f34d7d5b3..f86639d60e9a5e 100644 --- a/vlib/v/gen/native/tests/print.vv +++ b/vlib/v/gen/native/tests/print.vv @@ -104,6 +104,12 @@ fn test_interpolated() { println('num: ${num}; bool: ${boool}') } +fn test_intermediate() { + c := 0 + a := 'a' + println(c) +} + fn main() { test_stdout() test_stderr() @@ -113,4 +119,5 @@ fn main() { test_exprs() test_sizeof() test_interpolated() + test_intermediate() } diff --git a/vlib/v/gen/native/tests/print.vv.out b/vlib/v/gen/native/tests/print.vv.out index 9653ce9a200dc7..740ada47b83200 100644 --- a/vlib/v/gen/native/tests/print.vv.out +++ b/vlib/v/gen/native/tests/print.vv.out @@ -21,3 +21,4 @@ false true sizeof: 4, 12 this is an interpolated string num: 42; bool: true +0