fmt: single line match fix; x64: minor fixes

pull/4534/head^2
Alexander Medvednikov 2020-04-21 04:51:50 +02:00
parent 4ea4d1c8c4
commit cc0e0ed281
3 changed files with 118 additions and 49 deletions

View File

@ -863,6 +863,18 @@ fn (var f Fmt) match_expr(it ast.MatchExpr) {
single_line = false single_line = false
break break
} }
if branch.stmts.len == 0 {
continue
}
stmt := branch.stmts[0]
if stmt is ast.ExprStmt {
// If expressions inside match branches can't be one a single line
expr_stmt := stmt as ast.ExprStmt
if !expr_is_single_line(expr_stmt.expr) {
single_line = false
break
}
}
} }
for i, branch in it.branches { for i, branch in it.branches {
if branch.comment.text != '' { if branch.comment.text != '' {
@ -933,3 +945,11 @@ fn (var f Fmt) mark_module_as_used(name string) {
f.used_imports << mod f.used_imports << mod
// println('marking module $mod as used') // println('marking module $mod as used')
} }
fn expr_is_single_line(expr ast.Expr) bool {
match expr {
ast.IfExpr { return false }
else {}
}
return true
}

View File

@ -21,9 +21,12 @@ const (
'extern' 'extern'
'float' 'float'
'inline' 'inline'
'int', 'long', 'register', 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch' 'int'
'typedef' 'long'
'union', 'unsigned', 'void', 'volatile', 'while'] 'register'
'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned'
'void'
'volatile', 'while']
) )
fn foo(t token.Token) { fn foo(t token.Token) {
@ -435,9 +438,11 @@ fn (var g Gen) stmt(node ast.Stmt) {
// no ; after an if expression } // no ; after an if expression }
match expr { match expr {
ast.IfExpr {} ast.IfExpr {}
else { if !g.inside_ternary { else {
if !g.inside_ternary {
g.writeln(';') g.writeln(';')
} } }
}
} }
} }
ast.FnDecl { ast.FnDecl {
@ -1340,7 +1345,8 @@ fn (var g Gen) infix_expr(node ast.InfixExpr) {
g.write(' })') g.write(' })')
} }
} else if (node.left_type == node.right_type) && node.left_type in [table.f32_type_idx, } else if (node.left_type == node.right_type) && node.left_type in [table.f32_type_idx,
table.f64_type_idx] && node.op in [.eq, .ne] { table.f64_type_idx
] && node.op in [.eq, .ne] {
// floats should be compared with epsilon // floats should be compared with epsilon
if node.left_type == table.f64_type_idx { if node.left_type == table.f64_type_idx {
if node.op == .eq { if node.op == .eq {
@ -1649,15 +1655,9 @@ fn (var g Gen) index_expr(node ast.IndexExpr) {
} else if sym.kind == .array { } else if sym.kind == .array {
info := sym.info as table.Array info := sym.info as table.Array
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
var is_selector := false // `vals[i].field = x` is an exception and requires `array_get`:
match node.left { // `(*(Val*)array_get(vals, i)).field = x;`
ast.SelectorExpr { is_selector := node.left is ast.SelectorExpr
// `vals[i].field = x` is an exception and requires `array_get`:
// `(*(Val*)array_get(vals, i)).field = x;`
is_selector = true
}
else {}
}
if g.is_assign_lhs && !is_selector && node.is_setter { if g.is_assign_lhs && !is_selector && node.is_setter {
g.is_array_set = true g.is_array_set = true
g.write('array_set(') g.write('array_set(')
@ -1810,8 +1810,6 @@ fn (var g Gen) return_statement(node ast.Return) {
is_none = true is_none = true
} }
ast.CallExpr { ast.CallExpr {
// TODO: why?
// if !it.is_method {
if it.name == 'error' { if it.name == 'error' {
is_error = true // TODO check name 'error' is_error = true // TODO check name 'error'
} }
@ -2925,4 +2923,3 @@ fn (g Gen) type_to_fmt(typ table.Type) string {
} }
return '%d' return '%d'
} }

View File

@ -21,18 +21,41 @@ mut:
} }
// string_addr map[string]i64 // string_addr map[string]i64
// The registers are ordered for faster generation
// push rax => 50
// push rcx => 51 etc
enum Register { enum Register {
rax
rcx
rdx
rbx
rsp
rbp
rsi
rdi
eax eax
edi edi
rax
rdi
rsi
rbp
edx edx
rdx r8
r9
r10
r11
r12 r12
r13
r14
r15
} }
/*
rax // 0
rcx // 1
rdx // 2
rbx // 3
rsp // 4
rbp // 5
rsi // 6
rdi // 7
*/
enum Size { enum Size {
_8 _8
_16 _16
@ -216,10 +239,23 @@ pub fn (var g Gen) ret() {
} }
pub fn (var g Gen) push(reg Register) { pub fn (var g Gen) push(reg Register) {
if reg < .r8 {
g.write8(0x50 + reg)
} else {
g.write8(0x41)
g.write8(0x50 + reg - 8)
}
/*
match reg { match reg {
.rbp { g.write8(0x55) } .rbp { g.write8(0x55) }
else {} else {}
} }
*/
}
pub fn (var g Gen) pop(reg Register) {
g.write8(0x58 + reg)
// TODO r8...
} }
// returns label's relative address // returns label's relative address
@ -274,7 +310,7 @@ pub fn (var g Gen) gen_exit() {
fn (var g Gen) mov(reg Register, val int) { fn (var g Gen) mov(reg Register, val int) {
match reg { match reg {
.eax { .eax, .rax {
g.write8(0xb8) g.write8(0xb8)
} }
.edi { .edi {
@ -325,37 +361,22 @@ pub fn (var g Gen) call_fn(name string) {
fn (var g Gen) stmt(node ast.Stmt) { fn (var g Gen) stmt(node ast.Stmt) {
match node { match node {
ast.ConstDecl {} ast.AssignStmt {
ast.FnDecl { g.assign_stmt(it)
is_main := it.name == 'main'
println('saving addr $it.name $g.buf.len.hex()')
if is_main {
g.save_main_fn_addr()
} else {
g.register_function_address(it.name)
}
for arg in it.args {
}
for stmt in it.stmts {
g.stmt(stmt)
}
if is_main {
println('end of main: gen exit')
g.gen_exit()
// return
}
g.ret()
} }
ast.ConstDecl {}
ast.ExprStmt {
g.expr(it.expr)
}
ast.FnDecl {
g.fn_decl(it)
}
ast.ForStmt {}
ast.Return { ast.Return {
g.gen_exit() g.gen_exit()
g.ret() g.ret()
} }
ast.AssignStmt {}
ast.ForStmt {}
ast.StructDecl {} ast.StructDecl {}
ast.ExprStmt {
g.expr(it.expr)
}
else { else {
println('x64.stmt(): bad node') println('x64.stmt(): bad node')
} }
@ -395,6 +416,37 @@ fn (var g Gen) expr(node ast.Expr) {
} }
} }
fn (var g Gen) assign_stmt(node ast.AssignStmt) {
// `a := 1` | `a,b := 1,2`
for i, ident in node.left {
}
}
fn (var g Gen) fn_decl(it ast.FnDecl) {
is_main := it.name == 'main'
println('saving addr $it.name $g.buf.len.hex()')
if is_main {
g.save_main_fn_addr()
} else {
g.register_function_address(it.name)
g.push(.rbp)
}
for arg in it.args {
}
for stmt in it.stmts {
g.stmt(stmt)
}
if is_main {
println('end of main: gen exit')
g.gen_exit()
// return
}
if !is_main {
g.pop(.rbp)
}
g.ret()
}
fn verror(s string) { fn verror(s string) {
util.verror('x64 gen error', s) util.verror('x64 gen error', s)
} }