diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 44a6eb9848..7c91771bc7 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1901,7 +1901,7 @@ pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) { } } -// return all the registers for a give architecture +// return all the registers for the given architecture pub fn all_registers(mut t Table, arch pref.Arch) map[string]ScopeObject { mut res := map[string]ScopeObject{} match arch { diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index 6b74f4f80c..a6ae99259c 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -2,6 +2,7 @@ module native import term import v.ast +import v.token pub struct Amd64 { mut: @@ -132,7 +133,9 @@ fn (mut g Gen) inc_var(var_name string) { enum JumpOp { je = 0x840f jne = 0x850f + jg = 0x8f0f jge = 0x8d0f + lt = 0x8c0f jle = 0x8e0f } @@ -907,8 +910,6 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) { } ast.StructInit { sym := g.table.get_type_symbol(right.typ) - // println(sym) - // println(typeof(sym.info)) info := sym.info as ast.Struct for field in info.fields { field_name := name + '.' + field.name @@ -1012,10 +1013,70 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { } } -fn (mut g Gen) if_expr(node ast.IfExpr) { - branch := node.branches[0] - infix_expr := branch.cond as ast.InfixExpr - mut cjmp_addr := 0 // location of `jne *00 00 00 00*` +fn (mut g Gen) trap() { + // funnily works on x86 and arm64 + g.write32(0xcccccccc) + g.println('trap') +} + +fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) { + mut cjmp_addr := 0 + mut ine := ast.InfixExpr{} + ane := assert_node.expr + if ane is ast.ParExpr { // assert(1==1) + ine = ane.expr as ast.InfixExpr + } else if ane is ast.InfixExpr { // assert 1==1 + ine = ane + } else { + verror('Unsupported expression in assert') + } + cjmp_addr = g.condition(ine, true) + g.expr(assert_node.expr) + g.trap() + g.write32_at(cjmp_addr, int(g.pos() - cjmp_addr - 4)) // 4 is for "00 00 00 00" +} + +fn (mut g Gen) cjmp_notop(op token.Kind) int { + return match op { + .gt { + g.cjmp(.jle) + } + .lt { + g.cjmp(.jge) + } + .ne { + g.cjmp(.je) + } + .eq { + g.cjmp(.jne) + } + else { + g.cjmp(.je) + } + } +} + +fn (mut g Gen) cjmp_op(op token.Kind) int { + return match op { + .gt { + g.cjmp(.jg) + } + .lt { + g.cjmp(.lt) + } + .ne { + g.cjmp(.jne) + } + .eq { + g.cjmp(.je) + } + else { + g.cjmp(.jne) + } + } +} + +fn (mut g Gen) condition(infix_expr ast.InfixExpr, neg bool) int { match mut infix_expr.left { ast.IntegerLiteral { match mut infix_expr.right { @@ -1057,27 +1118,19 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { } } else { - dump(node) + dump(infix_expr) verror('unhandled infix.left') } } - cjmp_addr = match infix_expr.op { - .gt { - g.cjmp(.jle) - } - .lt { - g.cjmp(.jge) - } - .ne { - g.cjmp(.je) - } - .eq { - g.cjmp(.jne) - } - else { - g.cjmp(.je) - } - } + + // mut cjmp_addr := 0 // location of `jne *00 00 00 00*` + return if neg { g.cjmp_op(infix_expr.op) } else { g.cjmp_notop(infix_expr.op) } +} + +fn (mut g Gen) if_expr(node ast.IfExpr) { + branch := node.branches[0] + infix_expr := branch.cond as ast.InfixExpr + cjmp_addr := g.condition(infix_expr, false) g.stmts(branch.stmts) // Now that we know where we need to jump if the condition is false, update the `jne` call. // The value is the relative address, difference between current position and the location diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index c149ac2c45..8b37908045 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -12,7 +12,7 @@ import v.errors import v.pref import term -pub const builtins = ['print', 'eprint', 'println', 'eprintln', 'exit'] +pub const builtins = ['assert', 'print', 'eprint', 'println', 'eprintln', 'exit'] interface CodeGen { mut: @@ -369,6 +369,9 @@ fn (mut g Gen) stmt(node ast.Stmt) { g.pop(.rbp) g.ret() } + ast.AssertStmt { + g.gen_assert(node) + } ast.StructDecl {} else { println('native.stmt(): bad node: ' + node.type_name()) @@ -380,6 +383,9 @@ fn C.strtol(str &char, endptr &&char, base int) int fn (mut g Gen) expr(node ast.Expr) { match node { + ast.ParExpr { + g.expr(node.expr) + } ast.ArrayInit { verror('array init expr not supported yet') } @@ -387,14 +393,12 @@ fn (mut g Gen) expr(node ast.Expr) { ast.CallExpr { if node.name == 'exit' { g.gen_exit(node.args[0].expr) - return - } - if node.name in ['println', 'print', 'eprintln', 'eprint'] { + } else if node.name in ['println', 'print', 'eprintln', 'eprint'] { expr := node.args[0].expr g.gen_print_from_expr(expr, node.name) - return + } else { + g.call_fn(node) } - g.call_fn(node) } ast.FloatLiteral {} ast.Ident {} diff --git a/vlib/v/gen/native/tests/assert.vv b/vlib/v/gen/native/tests/assert.vv new file mode 100644 index 0000000000..0140021c41 --- /dev/null +++ b/vlib/v/gen/native/tests/assert.vv @@ -0,0 +1,10 @@ +fn main() { + assert 1 == 1 + assert 3 == 3 + assert 1 == 1 + assert 3 == 3 + if 1 == 2 { + assert 1 == 2 + } + println('assert pass') +} diff --git a/vlib/v/gen/native/tests/assert.vv.out b/vlib/v/gen/native/tests/assert.vv.out new file mode 100644 index 0000000000..c8741a3a2a --- /dev/null +++ b/vlib/v/gen/native/tests/assert.vv.out @@ -0,0 +1 @@ +assert pass