From 431568faadad8f3f831db9ba1e3fbac7ecab2e50 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 29 Nov 2019 12:33:04 +0300 Subject: [PATCH] x64: fix off by one error in for loops --- examples/x64/hello_world.v | 6 ++--- vlib/compiler/x64/gen.v | 46 +++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/x64/hello_world.v b/examples/x64/hello_world.v index 6bda7a20f3..6ebcf145e6 100644 --- a/examples/x64/hello_world.v +++ b/examples/x64/hello_world.v @@ -1,6 +1,6 @@ fn test_fn() { println('test fn') -} +} fn main() { println('x64 test') @@ -8,7 +8,7 @@ fn main() { println('Hello world from V x64 machine code generator!') } println('Hello again!') - test_fn() - println('dne') + //test_fn() + println('done') } diff --git a/vlib/compiler/x64/gen.v b/vlib/compiler/x64/gen.v index 35016c07c0..699bfa2a88 100644 --- a/vlib/compiler/x64/gen.v +++ b/vlib/compiler/x64/gen.v @@ -17,7 +17,7 @@ mut: code_start_pos i64 // location of the start of the assembly instructions fn_addr map[string]i64 //string_addr map[string]i64 -} +} enum Register { eax @@ -35,31 +35,31 @@ enum Size { _16 _32 _64 -} +} pub fn new_gen(out_name string) &Gen { return &Gen{ sect_header_name_pos : 0 buf: [] out_name: out_name - } -} + } +} pub fn (g &Gen) pos() i64 { return g.buf.len -} +} fn (g mut Gen) write8(n int) { // write 1 byte g.buf << byte(n) -} +} fn (g mut Gen) write16(n int) { // write 2 bytes g.buf << byte(n) g.buf << byte(n >> 8) -} +} fn (g mut Gen) write32(n int) { // write 4 bytes @@ -67,7 +67,7 @@ fn (g mut Gen) write32(n int) { g.buf << byte(n >> 8) g.buf << byte(n >> 16) g.buf << byte(n >> 24) -} +} fn (g mut Gen) write64(n i64) { // write 8 bytes @@ -79,7 +79,7 @@ fn (g mut Gen) write64(n i64) { g.buf << byte(n >> 40) g.buf << byte(n >> 48) g.buf << byte(n >> 56) -} +} fn (g mut Gen) write64_at(n i64, at i64) { // write 8 bytes @@ -91,12 +91,12 @@ fn (g mut Gen) write64_at(n i64, at i64) { g.buf[at+5] = byte(n >> 40) g.buf[at+6] = byte(n >> 48) g.buf[at+7] = byte(n >> 56) -} +} fn (g mut Gen) write_string(s string) { for c in s { g.write8(int(c)) - } + } } fn (g mut Gen) inc(reg Register) { @@ -104,8 +104,8 @@ fn (g mut Gen) inc(reg Register) { match reg { .r12 { g.write8(0xc4) } else { panic('unhandled inc $reg') } - } -} + } +} fn (g mut Gen) cmp(reg Register, size Size, val i64) { g.write8(0x49) @@ -114,12 +114,12 @@ fn (g mut Gen) cmp(reg Register, size Size, val i64) { ._8 { g.write8(0x83) } ._32 { g.write8(0x81) } else { panic('unhandled cmp') } - } + } // Third byte depends on the register being compared to match reg { .r12 { g.write8(0xfc) } else { panic('unhandled cmp') } - } + } g.write8(int(val)) } @@ -141,7 +141,7 @@ fn (g mut Gen) jl(addr i64) { fn (g &Gen) abs_to_rel_addr(addr i64) int { return int(abs(addr - g.buf.len))-1 -} +} fn (g mut Gen) jmp (addr i64) { offset := 0xff - g.abs_to_rel_addr(addr) @@ -163,7 +163,7 @@ fn (g mut Gen) mov64(reg Register, val i64) { fn (g mut Gen) call(addr int) { //rel := g.abs_to_rel_addr(addr) rel := 0xffffffff - int(abs(addr - g.buf.len))-1 - + println('call addr=$addr rel_addr=$addr pos=$g.buf.len') g.write8(0xe8) g.write32(addr) @@ -189,7 +189,7 @@ pub fn (g mut Gen) gen_loop_start(from int) int { pub fn (g mut Gen) gen_loop_end(to int, label int) { g.cmp(.r12, ._8, to) - g.jle(label) + g.jl(label) } pub fn (g mut Gen) save_main_fn_addr() { @@ -206,7 +206,7 @@ pub fn (g mut Gen) gen_print(s string) { g.mov64(.rsi, 0) //segment_start + 0x9f) // str pos // PLACEHOLDER g.mov(.edx, s.len+1) // len g.syscall() -} +} pub fn (g mut Gen) gen_exit() { // Return 0 @@ -227,11 +227,11 @@ fn (g mut Gen) mov(reg Register, val int) { .r12 { g.write8(0x41) g.write8(0xbc) // r11 is 0xbb etc - } + } else { panic('unhandled mov $reg') - } - + } + } g.write32(val) } @@ -245,7 +245,7 @@ pub fn (g mut Gen) register_function_address(name string) { pub fn (g mut Gen) call_fn(name string) { if !name.contains('__') { return - } + } addr := g.fn_addr[name] g.call(int(addr)) println('call $name $addr')