1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

native: initial support for typeof() expressions (#13730)

This commit is contained in:
pancake 2022-03-14 14:15:06 +01:00 committed by GitHub
parent a8f6574471
commit a1d0db792e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 120 additions and 36 deletions

View File

@ -641,6 +641,31 @@ pub fn (mut g Gen) gen_amd64_exit(expr ast.Expr) {
g.trap() // should never be reached, just in case g.trap() // should never be reached, just in case
} }
fn (mut g Gen) relpc(dst Register, src Register) {
// 488d1d 00000000 lea 0(%rip),%dst
// 4801d8 add %dst, %src
match dst {
.rax {
match src {
.rsi {
g.write([byte(0x48), 0x8d, 0x35, 0x00, 0x00, 0x00, 0x00]) // lea rsi, rip
g.write([byte(0x48), 0x01, 0xf0]) // add rax, rsi
}
.rbx {
g.write([byte(0x48), 0x8d, 0x1d, 0x00, 0x00, 0x00, 0x00])
g.write([byte(0x48), 0x01, 0xd8])
}
else {
panic('relpc requires .rax, {.rsi,.rbx}')
}
}
}
else {
panic('relpc requires .rax, {.rsi,.rbx}')
}
}
}
fn (mut g Gen) learel(reg Register, val int) { fn (mut g Gen) learel(reg Register, val int) {
g.write8(0x48) g.write8(0x48)
g.write8(0x8d) g.write8(0x8d)
@ -848,7 +873,9 @@ fn (mut g Gen) add_reg(a Register, b Register) {
} }
fn (mut g Gen) mov_reg(a Register, b Register) { fn (mut g Gen) mov_reg(a Register, b Register) {
if a == .rbp && b == .rsp { if a == .rax && b == .rsi {
g.write([byte(0x48), 0x89, 0xf0])
} else if a == .rbp && b == .rsp {
g.write8(0x48) g.write8(0x48)
g.write8(0x89) g.write8(0x89)
} else if a == .rdx && b == .rax { } else if a == .rdx && b == .rax {
@ -1130,6 +1157,7 @@ g.v_error('oops', node.pos)
pos += 8 pos += 8
} }
ast.StringLiteral { ast.StringLiteral {
// TODO: use learel
g.mov64(.rsi, g.allocate_string('$e.val', 2, .abs64)) // for rsi its 2 g.mov64(.rsi, g.allocate_string('$e.val', 2, .abs64)) // for rsi its 2
g.mov_reg_to_var(pos, .rsi) g.mov_reg_to_var(pos, .rsi)
pos += 8 pos += 8
@ -1169,7 +1197,7 @@ g.v_error('oops', node.pos)
ast.StringLiteral { ast.StringLiteral {
dest := g.allocate_var(name, 4, 0) dest := g.allocate_var(name, 4, 0)
ie := node.right[i] as ast.StringLiteral ie := node.right[i] as ast.StringLiteral
g.mov64(.rsi, g.allocate_string(ie.str(), 2, .abs64)) // for rsi its 2 g.learel(.rsi, g.allocate_string(ie.val.str(), 3, .rel32))
g.mov_reg_to_var(dest, .rsi) g.mov_reg_to_var(dest, .rsi)
} }
ast.CallExpr { ast.CallExpr {
@ -1178,6 +1206,9 @@ g.v_error('oops', node.pos)
g.mov_reg_to_var(dest, .rax) g.mov_reg_to_var(dest, .rax)
g.mov_var_to_reg(.rsi, dest) g.mov_var_to_reg(.rsi, dest)
} }
ast.SelectorExpr {
g.v_error('unhandled selectors', node.pos)
}
ast.GoExpr { ast.GoExpr {
g.v_error('threads not implemented for the native backend', node.pos) g.v_error('threads not implemented for the native backend', node.pos)
} }
@ -1195,6 +1226,14 @@ g.v_error('oops', node.pos)
} }
} }
} }
ast.FloatLiteral {
g.v_error('floating point arithmetic not yet implemented for the native backend',
node.pos)
}
ast.TypeOf {
g.gen_typeof_expr(node.right[i] as ast.TypeOf, true)
g.mov_reg(.rsi, .rax)
}
else { else {
// dump(node) // dump(node)
g.v_error('unhandled assign_stmt expression: $right.type_name()', right.pos()) g.v_error('unhandled assign_stmt expression: $right.type_name()', right.pos())
@ -1286,9 +1325,11 @@ fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
} }
ast.AsmDisp { ast.AsmDisp {
} }
ast.FloatLiteral {
}
*/ */
ast.FloatLiteral {
g.v_error('floating point arithmetic is not yet implemented for the native backend',
asm_node.pos)
}
string { string {
// XXX // XXX
g.v_error('no strings allowed in this context', asm_node.pos) g.v_error('no strings allowed in this context', asm_node.pos)
@ -1630,6 +1671,6 @@ pub fn (mut g Gen) allocate_var(name string, size int, initial_val int) int {
// Generate the value assigned to the variable // Generate the value assigned to the variable
g.write32(initial_val) g.write32(initial_val)
// println('allocate_var(size=$size, initial_val=$initial_val)') // println('allocate_var(size=$size, initial_val=$initial_val)')
g.println('mov [rbp-$n.hex2()], $initial_val (Allocate var `$name`)') g.println('mov [rbp-$n.hex2()], $initial_val ; Allocate var `$name`')
return g.stack_var_pos return g.stack_var_pos
} }

View File

@ -157,7 +157,7 @@ pub fn (mut g Gen) create_executable() {
os.write_file_array(g.out_name, g.buf) or { panic(err) } os.write_file_array(g.out_name, g.buf) or { panic(err) }
os.chmod(g.out_name, 0o775) or { panic(err) } // make it executable os.chmod(g.out_name, 0o775) or { panic(err) } // make it executable
if g.pref.is_verbose { if g.pref.is_verbose {
println('\n$g.out_name: native binary has been successfully generated') eprintln('\n$g.out_name: native binary has been successfully generated')
} }
} }
@ -277,14 +277,28 @@ fn (mut g Gen) write_string_with_padding(s string, max int) {
} }
} }
fn (mut g Gen) get_var_offset(var_name string) int { fn (mut g Gen) try_var_offset(var_name string) int {
offset := g.var_offset[var_name] offset := g.var_offset[var_name] or { return -1 }
if offset == 0 { if offset == 0 {
g.n_error('unknown variable `$var_name`') return -1
} }
return offset return offset
} }
fn (mut g Gen) get_var_offset(var_name string) int {
r := g.try_var_offset(var_name)
if r == -1 {
g.n_error('unknown variable `$var_name`')
}
return r
}
fn (mut g Gen) gen_typeof_expr(it ast.TypeOf, newline bool) {
nl := if newline { '\n' } else { '' }
r := g.typ(it.expr_type).name
g.learel(.rax, g.allocate_string('$r$nl', 3, .rel32))
}
pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) { pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
newline := name in ['println', 'eprintln'] newline := name in ['println', 'eprintln']
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 } fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
@ -301,13 +315,17 @@ pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
g.gen_print_reg(.rax, 3, fd) g.gen_print_reg(.rax, 3, fd)
} }
ast.Ident { ast.Ident {
vo := g.try_var_offset(expr.name)
if vo != -1 {
g.n_error('Printing idents is not yet supported in the native backend') g.n_error('Printing idents is not yet supported in the native backend')
/* // g.mov_var_to_reg(.rsi, vo)
vo := g.get_var_offset(expr.name) // g.mov_reg(.rax, .rsi)
g.mov_var_to_reg(.rax, vo) // g.learel(.rax, vo * 8)
// g.relpc(.rax, .rsi)
// g.learel(.rax, g.allocate_string('$vo\n', 3, .rel32))
// g.expr(expr) // g.expr(expr)
}
g.gen_print_reg(.rax, 3, fd) g.gen_print_reg(.rax, 3, fd)
*/
} }
ast.IntegerLiteral { ast.IntegerLiteral {
g.learel(.rax, g.allocate_string('$expr.val\n', 3, .rel32)) g.learel(.rax, g.allocate_string('$expr.val\n', 3, .rel32))
@ -394,8 +412,10 @@ g.expr
ast.SelectExpr {} ast.SelectExpr {}
ast.SqlExpr {} ast.SqlExpr {}
ast.TypeNode {} ast.TypeNode {}
ast.TypeOf {}
*/ */
ast.TypeOf {
g.gen_typeof_expr(expr, newline)
}
ast.LockExpr { ast.LockExpr {
// passthru // passthru
eprintln('Warning: locks not implemented yet in the native backend') eprintln('Warning: locks not implemented yet in the native backend')
@ -728,7 +748,10 @@ fn (mut g Gen) expr(node ast.Expr) {
} }
ast.FloatLiteral {} ast.FloatLiteral {}
ast.Ident { ast.Ident {
offset := g.get_var_offset(node.obj.name) // i := 0 offset := g.try_var_offset(node.obj.name) // i := 0
if offset == -1 {
g.n_error('invalid ident $node.obj.name')
}
// offset := g.get_var_offset(node.name) // offset := g.get_var_offset(node.name)
// XXX this is intel specific // XXX this is intel specific
g.mov_var_to_reg(.rax, offset) g.mov_var_to_reg(.rax, offset)

View File

@ -0,0 +1,16 @@
fn main() {
a := 'string'
t := typeof(a)
println(t)
t2 := typeof('another string')
println(t2)
n := 123
t3 := typeof(n)
println(t3)
t4 := typeof(123)
println(t4)
// id := 'hello world'
// println(id)
}

View File

@ -0,0 +1,4 @@
string
string
int
int literal