From a602673adb441d34f5ef6051a2ed0d2ff8b4911d Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 17 Jun 2020 20:18:48 +0200 Subject: [PATCH] x64: pass variables to functions --- vlib/orm/orm_test.v | 6 ++ vlib/sqlite/sqlite.v | 4 ++ vlib/v/ast/ast.v | 3 + vlib/v/gen/cgen.v | 2 +- vlib/v/gen/sql.v | 9 ++- vlib/v/gen/x64/gen.v | 97 +++++++++++++++++++++-------- vlib/v/gen/x64/tests/general.vv | 6 ++ vlib/v/gen/x64/tests/general.vv.out | 2 + 8 files changed, 100 insertions(+), 29 deletions(-) diff --git a/vlib/orm/orm_test.v b/vlib/orm/orm_test.v index 0558f1e597..ec6682b1dc 100644 --- a/vlib/orm/orm_test.v +++ b/vlib/orm/orm_test.v @@ -80,6 +80,12 @@ fn test_orm_sqlite() { assert users3.len == 2 assert users3[0].age == 29 assert users3[1].age == 31 + + //user2 := User{} + //x := sql db { + //insert user2 into User + //} + //db.insert(user2) } diff --git a/vlib/sqlite/sqlite.v b/vlib/sqlite/sqlite.v index 8e9e490b7c..53697f237a 100644 --- a/vlib/sqlite/sqlite.v +++ b/vlib/sqlite/sqlite.v @@ -118,3 +118,7 @@ pub fn (db DB) exec_none(query string) int { pub fn (db DB) exec_param(query string, param string) []Row { } */ + +pub fn (db DB) insert(x T) { +} + diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index a8b43dcd2b..5f3f5ea506 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -819,6 +819,9 @@ pub: is_array bool } +pub struct SqlInsertExpr { +} + [inline] pub fn (expr Expr) is_blank_ident() bool { match expr { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index caedad1108..434b85ee8a 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1573,7 +1573,7 @@ fn (mut g Gen) expr(node ast.Expr) { g.write('sizeof($styp)') } ast.SqlExpr { - g.sql_expr(it) + g.sql_select_expr(it) } ast.StringLiteral { if it.is_raw { diff --git a/vlib/v/gen/sql.v b/vlib/v/gen/sql.v index bde355bce0..fb9d6ea6af 100644 --- a/vlib/v/gen/sql.v +++ b/vlib/v/gen/sql.v @@ -12,7 +12,10 @@ const ( dbtype = 'sqlite' ) -fn (mut g Gen) sql_expr(node ast.SqlExpr) { +fn (mut g Gen) sql_insert_expr(node ast.SqlInsertExpr) { +} + +fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { g.sql_i = 0 /* `nr_users := sql db { ... }` => @@ -68,11 +71,11 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) { styp := g.typ(node.typ) mut elem_type_str := '' if node.is_array { + // array_User array_tmp; + // for { User tmp; ... array_tmp << tmp; } sym := g.table.get_type_symbol(node.typ) info := sym.info as table.Array elem_type_str = g.typ(info.elem_type) - // array_User array_tmp; - // for { User tmp; ... array_tmp << tmp; } g.writeln('$styp ${tmp}_array = __new_array(0, 10, sizeof($elem_type_str));') g.writeln('while (1) {') g.writeln('\t$elem_type_str $tmp;') diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index 32ab915523..5414b17f24 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -58,7 +58,7 @@ enum Register { } const ( - fn_arg_registers = [x64.Register.rdi, .rsi, .rdx, .rcx, .r8, .r9] + fn_arg_registers = [Register.rdi, .rsi, .rdx, .rcx, .r8, .r9] ) /* @@ -263,7 +263,8 @@ fn (mut g Gen) println(comment string) { addr := g.debug_pos.hex() // println('$g.debug_pos "$addr"') print(term.red(strings.repeat(`0`, 6 - addr.len) + addr + ' ')) - for i := g.debug_pos; i < g.buf.len; i++ { + for i := g.debug_pos; i < g.buf.len; i++ + { s := g.buf[i].hex() if s.len == 1 { print(term.blue('0')) @@ -318,7 +319,21 @@ fn (mut g Gen) mov_from_reg(var_offset int, reg Register) { else { verror('mov_from_reg $reg') } } g.write8(0xff - var_offset + 1) - g.println('mov from reg') + g.println('mov DWORD PTR[rbp-$var_offset.hex()],$reg') +} + +fn (mut g Gen) mov_rbp_offset(reg Register, var_offset int) { + // 8b 7d f8 mov edi,DWORD PTR [rbp-0x8] + g.write8(0x8b) + match reg { + .edi, .rdi { g.write8(0x7d) } + .rsi { g.write8(0x75) } + .rdx { g.write8(0x55) } + .rcx { g.write8(0x4d) } + else { verror('mov_rbp_offset $reg') } + } + g.write8(0xff - var_offset + 1) + g.println('mov $reg,DWORD PTR[rbp-$var_offset]') } fn (mut g Gen) call(addr int) { @@ -372,7 +387,15 @@ pub fn (mut g Gen) sub32(reg Register, val int) { g.write8(0x81) g.write8(0xe8 + reg) // TODO rax is different? g.write32(val) - g.println('sub $reg,0x$val.hex()') + g.println('sub32 $reg,0x$val.hex()') +} + +pub fn (mut g Gen) sub8(reg Register, val int) { + g.write8(0x48) + g.write8(0x83) + g.write8(0xe8 + reg) // TODO rax is different? + g.write8(val) + g.println('sub8 $reg,0x$val.hex()') } pub fn (mut g Gen) add(reg Register, val int) { @@ -383,6 +406,15 @@ pub fn (mut g Gen) add(reg Register, val int) { g.println('add $reg,0x$val.hex()') } +pub fn (mut g Gen) add8(reg Register, val int) { + g.write8(0x48) + g.write8(0x83) + // g.write8(0xe8 + reg) // TODO rax is different? + g.write8(0xc4) + g.write8(val) + g.println('add8 $reg,0x$val.hex()') +} + fn (mut g Gen) leave() { g.write8(0xc9) g.println('leave') @@ -502,8 +534,23 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) { // g.mov(.eax, 0) for i in 0 .. node.args.len { expr := node.args[i].expr - int_lit := expr as ast.IntegerLiteral - g.mov(fn_arg_registers[i], int_lit.val.int()) + match expr { + ast.IntegerLiteral { + // `foo(2)` => `mov edi,0x2` + int_lit := expr as ast.IntegerLiteral + g.mov(fn_arg_registers[i], int_lit.val.int()) + } + ast.Ident { + // `foo(x)` => `mov edi,DWORD PTR [rbp-0x8]` + offset := g.get_var_offset(it.name) + println('i=$i fn name= $name offset=$offset') + println(int(fn_arg_registers[i])) + g.mov_rbp_offset(fn_arg_registers[i], offset) + } + else { + verror('unhandled call_fn node: ' + typeof(expr)) + } + } } if node.args.len > 6 { verror('more than 6 args not allowed for now') @@ -620,7 +667,7 @@ fn (mut g Gen) allocate_var(name string, size, initial_val int) { // Generate the value assigned to the variable g.write32(initial_val) // println('allocate_var(size=$size, initial_val=$initial_val)') - g.println('mov DWORD [rbp-0x$n],$initial_val (Aallocate var `$name`)') + g.println('mov DWORD [rbp-0x$n],$initial_val (Allocate var `$name`)') } fn (mut g Gen) assign_stmt(node ast.AssignStmt) { @@ -629,19 +676,19 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) { right := node.right[i] name := left.str() // if left is ast.Ident { - // ident := left as ast.Ident - match right { - ast.IntegerLiteral { - g.allocate_var(name, 4, it.val.int()) - } - ast.InfixExpr { - g.infix_expr(it) - g.allocate_var(name, 4, 0) - } - else { - g.error_with_pos('assign_stmt unhandled expr: ' + typeof(right), right.position()) - } + // ident := left as ast.Ident + match right { + ast.IntegerLiteral { + g.allocate_var(name, 4, it.val.int()) } + ast.InfixExpr { + g.infix_expr(it) + g.allocate_var(name, 4, 0) + } + else { + g.error_with_pos('assign_stmt unhandled expr: ' + typeof(right), right.position()) + } + } // } } } @@ -712,9 +759,9 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) { } g.push(.rbp) g.mov_rbp_rsp() - if !is_main { - g.sub32(.rsp, 0x20) - } + // if !is_main { + g.sub8(.rsp, 0x10) + // } if node.args.len > 0 { // g.mov(.r12, 0x77777777) } @@ -736,9 +783,9 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) { // return } if !is_main { - g.leave() - // g.add(.rsp, 0x20) - // g.pop(.rbp) + // g.leave() + g.add8(.rsp, 0x10) + g.pop(.rbp) } g.ret() } diff --git a/vlib/v/gen/x64/tests/general.vv b/vlib/v/gen/x64/tests/general.vv index b1b5e4a25b..f750d690ab 100644 --- a/vlib/v/gen/x64/tests/general.vv +++ b/vlib/v/gen/x64/tests/general.vv @@ -39,11 +39,17 @@ fn foo(a int) { if a == 3 { println('a == 3') } + if a == 7 { + println('a == 7') + } + } fn args() { + x := 7 println('===args===') foo(1) + foo(x) foo(2) } diff --git a/vlib/v/gen/x64/tests/general.vv.out b/vlib/v/gen/x64/tests/general.vv.out index 4fac90b910..4ae114d341 100644 --- a/vlib/v/gen/x64/tests/general.vv.out +++ b/vlib/v/gen/x64/tests/general.vv.out @@ -11,5 +11,7 @@ foo: a == 1 a == 2 foo: +a == 7 +foo: a == 3