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:
parent
a8f6574471
commit
a1d0db792e
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
16
vlib/v/gen/native/tests/typeof.vv
Normal file
16
vlib/v/gen/native/tests/typeof.vv
Normal 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)
|
||||||
|
}
|
4
vlib/v/gen/native/tests/typeof.vv.out
Normal file
4
vlib/v/gen/native/tests/typeof.vv.out
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
string
|
||||||
|
string
|
||||||
|
int
|
||||||
|
int literal
|
Loading…
Reference in New Issue
Block a user