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

native: enable printing for all supported expressions (#16270)

This commit is contained in:
Spydr 2022-10-31 16:43:02 +01:00 committed by GitHub
parent 339bd0c4b5
commit 1b721250e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 104 deletions

View File

@ -1225,9 +1225,8 @@ pub fn (mut g Gen) inline_strlen(r Register) {
// TODO: strlen of string at runtime
pub fn (mut g Gen) gen_print_reg(r Register, n int, fd int) {
mystrlen := true // if n < 0 maybe?
g.mov_reg(.rsi, r)
if mystrlen {
if n < 0 {
g.inline_strlen(.rsi)
g.mov_reg(.rdx, .rax)
} else {
@ -2621,14 +2620,6 @@ fn (mut g Gen) trap() {
g.println('trap')
}
fn (mut g Gen) gen_asm_stmt(asm_node ast.AsmStmt) {
if g.pref.arch == .arm64 {
g.gen_asm_stmt_arm64(asm_node)
} else {
g.gen_asm_stmt_amd64(asm_node)
}
}
fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
// inline assembly using vasm
g.println('// asm inline')

View File

@ -660,11 +660,11 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
// skip \
i++
match str[i] {
`\\` {
buffer << `\\`
`\\`, `'`, `"` {
buffer << str[i]
i++
}
`a` | `b` | `f` {
`a`, `b`, `f` {
buffer << str[i] - u8(90)
i++
}
@ -720,6 +720,33 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
return buffer.bytestr()
}
fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) {
if typ.is_int() {
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
g.lea_var_to_reg(g.get_builtin_arg_reg('int_to_string', 1), buffer)
arg0_reg := g.get_builtin_arg_reg('int_to_string', 0)
if arg0_reg != reg {
g.mov_reg(arg0_reg, reg)
}
g.call_builtin('int_to_string')
g.lea_var_to_reg(.rax, buffer)
} else if typ.is_bool() {
arg_reg := g.get_builtin_arg_reg('bool_to_string', 0)
if arg_reg != reg {
g.mov_reg(arg_reg, reg)
}
g.call_builtin('bool_to_string')
} else if typ.is_string() {
if reg != .rax {
g.mov_reg(.rax, reg)
}
} else {
g.n_error('int-to-string conversion not implemented for type $typ')
}
}
fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
typ := g.get_type_from_var(var)
if typ.is_int() {
@ -738,7 +765,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
}
}
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, typ ast.Type, name string) {
newline := name in ['println', 'eprintln']
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
match expr {
@ -750,70 +777,66 @@ pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
g.gen_print(str, fd)
}
}
ast.CallExpr {
g.call_fn(expr)
g.gen_print_reg(.rax, 3, fd)
}
ast.Ident {
vo := g.try_var_offset(expr.name)
if vo != -1 {
g.gen_var_to_string(.rax, expr as ast.Ident)
g.gen_print_reg(.rax, 3, fd)
g.gen_print_reg(.rax, -1, fd)
if newline {
g.gen_print('\n', fd)
}
} else {
g.gen_print_reg(.rax, 3, fd)
g.gen_print_reg(.rax, -1, fd)
}
}
ast.IntegerLiteral {
g.learel(.rax, g.allocate_string('$expr.val\n', 3, .rel32))
g.gen_print_reg(.rax, 3, fd)
if newline {
g.gen_print('$expr.val\n', fd)
} else {
g.gen_print('$expr.val', fd)
}
}
ast.BoolLiteral {
// register 'true' and 'false' strings // g.expr(expr)
// XXX mov64 shuoldnt be used for addressing
nl := if newline { '\n' } else { '' }
if expr.val {
g.learel(.rax, g.allocate_string('true', 3, .rel32))
g.gen_print('true' + nl, fd)
} else {
g.learel(.rax, g.allocate_string('false', 3, .rel32))
g.gen_print('false' + nl, fd)
}
}
ast.SizeOf {
size := g.get_type_size(expr.typ)
if newline {
g.gen_print('$size\n', fd)
} else {
g.gen_print('$size', fd)
}
g.gen_print_reg(.rax, 3, fd)
}
ast.SizeOf {}
ast.OffsetOf {
styp := g.typ(expr.struct_type)
field_name := expr.field
if styp.kind == .struct_ {
off := g.get_field_offset(expr.struct_type, field_name)
g.learel(.rax, g.allocate_string('$off\n', 3, .rel32))
g.gen_print_reg(.rax, 3, fd)
if newline {
g.gen_print('$off\n', fd)
} else {
g.gen_print('$off', fd)
}
} else {
g.v_error('_offsetof expects a struct Type as first argument', expr.pos)
}
}
ast.None {}
ast.EmptyExpr {
g.n_error('unhandled EmptyExpr')
}
ast.PostfixExpr {}
ast.PrefixExpr {}
ast.SelectorExpr {
// struct.field
g.expr(expr)
g.gen_print_reg(.rax, 3, fd)
/*
field_name := expr.field_name
g.expr
if expr.is_mut {
// mutable field access (rw)
ast.None {
if newline {
g.gen_print('<none>\n', fd)
} else {
g.gen_print('<none>', fd)
}
*/
dump(expr)
g.v_error('struct.field selector not yet implemented for this backend', expr.pos)
}
ast.NodeError {}
ast.AtExpr {
if newline {
g.gen_print(g.comptime_at(expr) + '\n', fd)
@ -821,54 +844,6 @@ g.expr
g.gen_print(g.comptime_at(expr), fd)
}
}
/*
ast.AnonFn {}
ast.ArrayDecompose {}
ast.ArrayInit {}
ast.AsCast {}
ast.Assoc {}
ast.CTempVar {}
ast.CastExpr {}
ast.ChanInit {}
ast.CharLiteral {}
ast.Comment {}
ast.ComptimeCall {}
ast.ComptimeSelector {}
ast.ConcatExpr {}
ast.DumpExpr {}
ast.EnumVal {}
ast.GoExpr {}
ast.IfGuardExpr {}
ast.IndexExpr {}
ast.InfixExpr {}
ast.IsRefType {}
ast.MapInit {}
ast.OrExpr {}
ast.ParExpr {}
ast.RangeExpr {}
ast.SelectExpr {}
ast.SqlExpr {}
ast.TypeNode {}
*/
ast.MatchExpr {
g.gen_match_expr(expr)
}
ast.TypeOf {
g.gen_typeof_expr(expr, newline)
}
ast.LockExpr {
// passthru
eprintln('Warning: locks not implemented yet in the native backend')
g.expr(expr)
}
ast.Likely {
// passthru
g.expr(expr)
}
ast.UnsafeExpr {
// passthru
g.expr(expr)
}
ast.StringInterLiteral {
g.n_error('Interlaced string literals are not yet supported in the native backend.') // , expr.pos)
}
@ -877,7 +852,7 @@ g.expr
if stmts := g.comptime_conditional(expr) {
for i, stmt in stmts {
if i + 1 == stmts.len && stmt is ast.ExprStmt {
g.gen_print_from_expr(stmt.expr, name)
g.gen_print_from_expr(stmt.expr, stmt.typ, name)
} else {
g.stmt(stmt)
}
@ -886,14 +861,16 @@ g.expr
g.n_error('nothing to print')
}
} else {
g.n_error('non-comptime if exprs not yet implemented')
g.n_error('non-comptime conditionals are not implemented yet.')
}
}
else {
dump(typeof(expr).name)
dump(expr)
// g.v_error('expected string as argument for print', expr.pos)
g.n_error('expected string as argument for print') // , expr.pos)
g.expr(expr)
g.gen_to_string(.rax, typ)
g.gen_print_reg(.rax, -1, fd)
if newline {
g.gen_print('\n', fd)
}
}
}
}
@ -1244,6 +1221,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
}
}
fn (mut g Gen) gen_asm_stmt(asm_node ast.AsmStmt) {
if g.pref.arch == .arm64 {
g.gen_asm_stmt_arm64(asm_node)
} else {
g.gen_asm_stmt_amd64(asm_node)
}
}
fn C.strtol(str &char, endptr &&char, base int) int
fn (mut g Gen) gen_syscall(node ast.CallExpr) {
@ -1321,7 +1306,8 @@ fn (mut g Gen) expr(node ast.Expr) {
g.gen_exit(node.args[0].expr)
} else if node.name in ['println', 'print', 'eprintln', 'eprint'] {
expr := node.args[0].expr
g.gen_print_from_expr(expr, node.name)
typ := node.args[0].typ
g.gen_print_from_expr(expr, typ, node.name)
} else {
g.call_fn(node)
}

View File

@ -31,7 +31,7 @@ fn test_stderr() {
fn test_idents() {
// signed integer
x := 0
println(x)
@ -70,10 +70,36 @@ fn test_idents() {
println(r'hello\tworld\n')
}
fn test_exprs() {
t := true
print(t == false)
print(' ')
println(t == true)
i := 123
println(i + 456)
j := 2
println(j + j * j)
println(none)
}
fn test_sizeof() {
i := 0
print('sizeof: ')
print(sizeof(i))
print(', ')
println(sizeof(Foo))
}
fn main() {
test_stdout()
test_stderr()
test_numbers()
test_oof()
test_idents()
test_exprs()
test_sizeof()
}

View File

@ -13,4 +13,9 @@ false
string blah blah blah
😀😆😎💻🌎
こんにちは
hello\tworld\n
hello\tworld\n
false true
579
6
<none>
sizeof: 4, 12