tests: fix mut_test; x64: sub32()
parent
be40de331d
commit
9278a0cfba
|
@ -20,7 +20,6 @@ const (
|
||||||
'vlib/v/tests/enum_bitfield_test.v',
|
'vlib/v/tests/enum_bitfield_test.v',
|
||||||
'vlib/v/tests/fixed_array_test.v',
|
'vlib/v/tests/fixed_array_test.v',
|
||||||
'vlib/v/tests/fn_variadic_test.v',
|
'vlib/v/tests/fn_variadic_test.v',
|
||||||
'vlib/v/tests/mut_test.v',
|
|
||||||
'vlib/v/tests/num_lit_call_method_test.v',
|
'vlib/v/tests/num_lit_call_method_test.v',
|
||||||
'vlib/v/tests/option_test.v',
|
'vlib/v/tests/option_test.v',
|
||||||
'vlib/v/tests/pointers_test.v',
|
'vlib/v/tests/pointers_test.v',
|
||||||
|
|
|
@ -30,10 +30,14 @@ const (
|
||||||
const (
|
const (
|
||||||
segment_start = 0x400000
|
segment_start = 0x400000
|
||||||
PLACEHOLDER = 0
|
PLACEHOLDER = 0
|
||||||
|
SEVENS = 0x77777777
|
||||||
)
|
)
|
||||||
|
|
||||||
pub fn (var g Gen) generate_elf_header() {
|
pub fn (mut g Gen) generate_elf_header() {
|
||||||
g.buf << [byte(mag0), mag1, mag2, mag3]
|
g.buf << [byte(mag0), mag1
|
||||||
|
mag2
|
||||||
|
mag3
|
||||||
|
]
|
||||||
g.buf << elfclass64 // file class
|
g.buf << elfclass64 // file class
|
||||||
g.buf << elfdata2lsb // data encoding
|
g.buf << elfdata2lsb // data encoding
|
||||||
g.buf << ev_current // file version
|
g.buf << ev_current // file version
|
||||||
|
@ -71,7 +75,7 @@ pub fn (var g Gen) generate_elf_header() {
|
||||||
g.call(PLACEHOLDER) // call main function, it's not guaranteed to be the first, we don't know its address yet
|
g.call(PLACEHOLDER) // call main function, it's not guaranteed to be the first, we don't know its address yet
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) generate_elf_footer() {
|
pub fn (mut g Gen) generate_elf_footer() {
|
||||||
// Return 0
|
// Return 0
|
||||||
/*
|
/*
|
||||||
g.mov(.edi, 0) // ret value
|
g.mov(.edi, 0) // ret value
|
||||||
|
@ -96,7 +100,7 @@ pub fn (var g Gen) generate_elf_footer() {
|
||||||
// -5 is for "e8 00 00 00 00"
|
// -5 is for "e8 00 00 00 00"
|
||||||
g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5)
|
g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5)
|
||||||
// Create the binary
|
// Create the binary
|
||||||
var f := os.create(g.out_name) or {
|
mut f := os.create(g.out_name) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
os.chmod(g.out_name, 0o775) // make it an executable
|
os.chmod(g.out_name, 0o775) // make it an executable
|
||||||
|
|
|
@ -64,7 +64,7 @@ enum Size {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(files []ast.File, out_name string) {
|
pub fn gen(files []ast.File, out_name string) {
|
||||||
var g := Gen{
|
mut g := Gen{
|
||||||
sect_header_name_pos: 0
|
sect_header_name_pos: 0
|
||||||
out_name: out_name
|
out_name: out_name
|
||||||
}
|
}
|
||||||
|
@ -91,18 +91,18 @@ pub fn (g &Gen) pos() i64 {
|
||||||
return g.buf.len
|
return g.buf.len
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write8(n int) {
|
fn (mut g Gen) write8(n int) {
|
||||||
// write 1 byte
|
// write 1 byte
|
||||||
g.buf << byte(n)
|
g.buf << byte(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write16(n int) {
|
fn (mut g Gen) write16(n int) {
|
||||||
// write 2 bytes
|
// write 2 bytes
|
||||||
g.buf << byte(n)
|
g.buf << byte(n)
|
||||||
g.buf << byte(n >> 8)
|
g.buf << byte(n >> 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write32(n int) {
|
fn (mut g Gen) write32(n int) {
|
||||||
// write 4 bytes
|
// write 4 bytes
|
||||||
g.buf << byte(n)
|
g.buf << byte(n)
|
||||||
g.buf << byte(n >> 8)
|
g.buf << byte(n >> 8)
|
||||||
|
@ -110,7 +110,7 @@ fn (var g Gen) write32(n int) {
|
||||||
g.buf << byte(n >> 24)
|
g.buf << byte(n >> 24)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write64(n i64) {
|
fn (mut g Gen) write64(n i64) {
|
||||||
// write 8 bytes
|
// write 8 bytes
|
||||||
g.buf << byte(n)
|
g.buf << byte(n)
|
||||||
g.buf << byte(n >> 8)
|
g.buf << byte(n >> 8)
|
||||||
|
@ -122,7 +122,7 @@ fn (var g Gen) write64(n i64) {
|
||||||
g.buf << byte(n >> 56)
|
g.buf << byte(n >> 56)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write64_at(n, at i64) {
|
fn (mut g Gen) write64_at(n, at i64) {
|
||||||
// write 8 bytes
|
// write 8 bytes
|
||||||
g.buf[at] = byte(n)
|
g.buf[at] = byte(n)
|
||||||
g.buf[at + 1] = byte(n >> 8)
|
g.buf[at + 1] = byte(n >> 8)
|
||||||
|
@ -134,7 +134,7 @@ fn (var g Gen) write64_at(n, at i64) {
|
||||||
g.buf[at + 7] = byte(n >> 56)
|
g.buf[at + 7] = byte(n >> 56)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write32_at(at i64, n int) {
|
fn (mut g Gen) write32_at(at i64, n int) {
|
||||||
// write 4 bytes
|
// write 4 bytes
|
||||||
g.buf[at] = byte(n)
|
g.buf[at] = byte(n)
|
||||||
g.buf[at + 1] = byte(n >> 8)
|
g.buf[at + 1] = byte(n >> 8)
|
||||||
|
@ -142,13 +142,13 @@ fn (var g Gen) write32_at(at i64, n int) {
|
||||||
g.buf[at + 3] = byte(n >> 24)
|
g.buf[at + 3] = byte(n >> 24)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) write_string(s string) {
|
fn (mut g Gen) write_string(s string) {
|
||||||
for c in s {
|
for c in s {
|
||||||
g.write8(int(c))
|
g.write8(int(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) inc(reg Register) {
|
fn (mut g Gen) inc(reg Register) {
|
||||||
g.write16(0xff49)
|
g.write16(0xff49)
|
||||||
match reg {
|
match reg {
|
||||||
.r12 { g.write8(0xc4) }
|
.r12 { g.write8(0xc4) }
|
||||||
|
@ -156,7 +156,7 @@ fn (var g Gen) inc(reg Register) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) cmp(reg Register, size Size, val i64) {
|
fn (mut g Gen) cmp(reg Register, size Size, val i64) {
|
||||||
g.write8(0x49)
|
g.write8(0x49)
|
||||||
// Second byte depends on the size of the value
|
// Second byte depends on the size of the value
|
||||||
match size {
|
match size {
|
||||||
|
@ -180,7 +180,7 @@ fn abs(a i64) i64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) jle(addr i64) {
|
fn (mut g Gen) jle(addr i64) {
|
||||||
// Calculate the relative offset to jump to
|
// Calculate the relative offset to jump to
|
||||||
// (`addr` is absolute address)
|
// (`addr` is absolute address)
|
||||||
offset := 0xff - int(abs(addr - g.buf.len)) - 1
|
offset := 0xff - int(abs(addr - g.buf.len)) - 1
|
||||||
|
@ -188,7 +188,7 @@ fn (var g Gen) jle(addr i64) {
|
||||||
g.write8(offset)
|
g.write8(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) jl(addr i64) {
|
fn (mut g Gen) jl(addr i64) {
|
||||||
offset := 0xff - int(abs(addr - g.buf.len)) - 1
|
offset := 0xff - int(abs(addr - g.buf.len)) - 1
|
||||||
g.write8(0x7c)
|
g.write8(0x7c)
|
||||||
g.write8(offset)
|
g.write8(offset)
|
||||||
|
@ -198,13 +198,13 @@ fn (g &Gen) abs_to_rel_addr(addr i64) int {
|
||||||
return int(abs(addr - g.buf.len)) - 1
|
return int(abs(addr - g.buf.len)) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) jmp(addr i64) {
|
fn (mut g Gen) jmp(addr i64) {
|
||||||
offset := 0xff - g.abs_to_rel_addr(addr)
|
offset := 0xff - g.abs_to_rel_addr(addr)
|
||||||
g.write8(0xe9)
|
g.write8(0xe9)
|
||||||
g.write8(offset)
|
g.write8(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) mov64(reg Register, val i64) {
|
fn (mut g Gen) mov64(reg Register, val i64) {
|
||||||
match reg {
|
match reg {
|
||||||
.rsi {
|
.rsi {
|
||||||
g.write8(0x48)
|
g.write8(0x48)
|
||||||
|
@ -217,7 +217,7 @@ fn (var g Gen) mov64(reg Register, val i64) {
|
||||||
g.write64(val)
|
g.write64(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) call(addr int) {
|
fn (mut g Gen) call(addr int) {
|
||||||
// Need to calculate the difference between current position (position after the e8 call)
|
// Need to calculate the difference between current position (position after the e8 call)
|
||||||
// and the function to call.
|
// and the function to call.
|
||||||
// +5 is to get the posistion "e8 xx xx xx xx"
|
// +5 is to get the posistion "e8 xx xx xx xx"
|
||||||
|
@ -228,17 +228,17 @@ fn (var g Gen) call(addr int) {
|
||||||
g.write32(rel)
|
g.write32(rel)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) syscall() {
|
fn (mut g Gen) syscall() {
|
||||||
// g.write(0x050f)
|
// g.write(0x050f)
|
||||||
g.write8(0x0f)
|
g.write8(0x0f)
|
||||||
g.write8(0x05)
|
g.write8(0x05)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) ret() {
|
pub fn (mut g Gen) ret() {
|
||||||
g.write8(0xc3)
|
g.write8(0xc3)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) push(reg Register) {
|
pub fn (mut g Gen) push(reg Register) {
|
||||||
if reg < .r8 {
|
if reg < .r8 {
|
||||||
g.write8(0x50 + reg)
|
g.write8(0x50 + reg)
|
||||||
} else {
|
} else {
|
||||||
|
@ -253,40 +253,48 @@ pub fn (var g Gen) push(reg Register) {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) pop(reg Register) {
|
pub fn (mut g Gen) pop(reg Register) {
|
||||||
g.write8(0x58 + reg)
|
g.write8(0x58 + reg)
|
||||||
// TODO r8...
|
// TODO r8...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) sub32(reg Register, val int) {
|
||||||
|
g.write8(0x48)
|
||||||
|
g.write8(0x81)
|
||||||
|
g.write8(0xe8 + reg) // TODO rax is different?
|
||||||
|
}
|
||||||
|
|
||||||
// returns label's relative address
|
// returns label's relative address
|
||||||
pub fn (var g Gen) gen_loop_start(from int) int {
|
pub fn (mut g Gen) gen_loop_start(from int) int {
|
||||||
g.mov(.r12, from)
|
g.mov(.r12, from)
|
||||||
label := g.buf.len
|
label := g.buf.len
|
||||||
g.inc(.r12)
|
g.inc(.r12)
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) gen_loop_end(to, label int) {
|
pub fn (mut g Gen) gen_loop_end(to, label int) {
|
||||||
g.cmp(.r12, ._8, to)
|
g.cmp(.r12, ._8, to)
|
||||||
g.jl(label)
|
g.jl(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) save_main_fn_addr() {
|
pub fn (mut g Gen) save_main_fn_addr() {
|
||||||
g.main_fn_addr = g.buf.len
|
g.main_fn_addr = g.buf.len
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) gen_print_from_expr(expr ast.Expr, newline bool) {
|
pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, newline bool) {
|
||||||
match expr {
|
match expr {
|
||||||
ast.StringLiteral { if newline {
|
ast.StringLiteral {
|
||||||
|
if newline {
|
||||||
g.gen_print(it.val + '\n')
|
g.gen_print(it.val + '\n')
|
||||||
} else {
|
} else {
|
||||||
g.gen_print(it.val)
|
g.gen_print(it.val)
|
||||||
} }
|
}
|
||||||
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) gen_print(s string) {
|
pub fn (mut g Gen) gen_print(s string) {
|
||||||
//
|
//
|
||||||
// qq := s + '\n'
|
// qq := s + '\n'
|
||||||
//
|
//
|
||||||
|
@ -301,14 +309,14 @@ pub fn (var g Gen) gen_print(s string) {
|
||||||
g.syscall()
|
g.syscall()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) gen_exit() {
|
pub fn (mut g Gen) gen_exit() {
|
||||||
// Return 0
|
// Return 0
|
||||||
g.mov(.edi, 0) // ret value
|
g.mov(.edi, 0) // ret value
|
||||||
g.mov(.eax, 60)
|
g.mov(.eax, 60)
|
||||||
g.syscall()
|
g.syscall()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) mov(reg Register, val int) {
|
fn (mut g Gen) mov(reg Register, val int) {
|
||||||
match reg {
|
match reg {
|
||||||
.eax, .rax {
|
.eax, .rax {
|
||||||
g.write8(0xb8)
|
g.write8(0xb8)
|
||||||
|
@ -334,7 +342,7 @@ fn (var g Gen) mov(reg Register, val int) {
|
||||||
g.write32(val)
|
g.write32(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) register_function_address(name string) {
|
pub fn (mut g Gen) register_function_address(name string) {
|
||||||
addr := g.pos()
|
addr := g.pos()
|
||||||
// println('reg fn addr $name $addr')
|
// println('reg fn addr $name $addr')
|
||||||
g.fn_addr[name] = addr
|
g.fn_addr[name] = addr
|
||||||
|
@ -346,7 +354,7 @@ pub fn (g &Gen) write(s string) {
|
||||||
pub fn (g &Gen) writeln(s string) {
|
pub fn (g &Gen) writeln(s string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (var g Gen) call_fn(name string) {
|
pub fn (mut g Gen) call_fn(name string) {
|
||||||
println('call fn $name')
|
println('call fn $name')
|
||||||
if !name.contains('__') {
|
if !name.contains('__') {
|
||||||
// return
|
// return
|
||||||
|
@ -359,7 +367,7 @@ pub fn (var g Gen) call_fn(name string) {
|
||||||
println('call $name $addr')
|
println('call $name $addr')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) stmt(node ast.Stmt) {
|
fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
match node {
|
match node {
|
||||||
ast.AssignStmt {
|
ast.AssignStmt {
|
||||||
g.assign_stmt(it)
|
g.assign_stmt(it)
|
||||||
|
@ -383,7 +391,7 @@ fn (var g Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) expr(node ast.Expr) {
|
fn (mut g Gen) expr(node ast.Expr) {
|
||||||
// println('cgen expr()')
|
// println('cgen expr()')
|
||||||
match node {
|
match node {
|
||||||
ast.AssignExpr {}
|
ast.AssignExpr {}
|
||||||
|
@ -416,13 +424,13 @@ fn (var g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) assign_stmt(node ast.AssignStmt) {
|
fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
// `a := 1` | `a,b := 1,2`
|
// `a := 1` | `a,b := 1,2`
|
||||||
for i, ident in node.left {
|
for i, ident in node.left {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var g Gen) fn_decl(it ast.FnDecl) {
|
fn (mut g Gen) fn_decl(it ast.FnDecl) {
|
||||||
is_main := it.name == 'main'
|
is_main := it.name == 'main'
|
||||||
println('saving addr $it.name $g.buf.len.hex()')
|
println('saving addr $it.name $g.buf.len.hex()')
|
||||||
if is_main {
|
if is_main {
|
||||||
|
@ -430,6 +438,8 @@ fn (var g Gen) fn_decl(it ast.FnDecl) {
|
||||||
} else {
|
} else {
|
||||||
g.register_function_address(it.name)
|
g.register_function_address(it.name)
|
||||||
g.push(.rbp)
|
g.push(.rbp)
|
||||||
|
// g.write32(SEVENS)
|
||||||
|
g.sub32(.rsp, 0x10)
|
||||||
}
|
}
|
||||||
for arg in it.args {
|
for arg in it.args {
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn foo(b int, a mut []int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mut() {
|
fn test_mut() {
|
||||||
var numbers := [1, 2, 3]
|
mut numbers := [1, 2, 3]
|
||||||
foo(7, mut numbers)
|
foo(7, mut numbers)
|
||||||
assert numbers.len == 3
|
assert numbers.len == 3
|
||||||
// TODO bring back once << works with mutable args
|
// TODO bring back once << works with mutable args
|
||||||
|
@ -23,7 +23,7 @@ fn test_mut() {
|
||||||
// assert numbers[3] == 4
|
// assert numbers[3] == 4
|
||||||
println(numbers)
|
println(numbers)
|
||||||
n := 1
|
n := 1
|
||||||
var b := &n
|
mut b := (&n)
|
||||||
//
|
//
|
||||||
(*b) = 10
|
(*b) = 10
|
||||||
// mut b := mut a
|
// mut b := mut a
|
||||||
|
@ -32,14 +32,14 @@ fn test_mut() {
|
||||||
|
|
||||||
fn test_mut_2() {
|
fn test_mut_2() {
|
||||||
zero := 0
|
zero := 0
|
||||||
var b := B{}
|
mut b := B{}
|
||||||
b.a << A{}
|
b.a << A{}
|
||||||
b.a[0].v = [9, 8, 7]
|
b.a[0].v = [9, 8, 7]
|
||||||
b.a[0].v << 6
|
b.a[0].v << 6
|
||||||
b.a[zero].v << 5
|
b.a[zero].v << 5
|
||||||
b.a[0].v[zero] = 3
|
b.a[0].v[zero] = 3
|
||||||
b.a[0].v[b.a[zero].v[zero]] += 2 - 1 // TODO
|
b.a[0].v[b.a[zero].v[zero]] += 2 - 1 // TODO
|
||||||
b.a[0].v[b.a[0].v[zero]] += 2 - 1 // TODO
|
b.a[0].v[b.a[0].v[zero]] += 2 - 1 // TODO
|
||||||
assert b.a[0].v.len == 5
|
assert b.a[0].v.len == 5
|
||||||
assert b.a[0].v[0] == 3
|
assert b.a[0].v[0] == 3
|
||||||
assert b.a[0].v[1] == 8
|
assert b.a[0].v[1] == 8
|
||||||
|
|
Loading…
Reference in New Issue