native: implement for-c and for-in range loops (#12155)
parent
05db3533d3
commit
1b691e7612
|
@ -71,7 +71,13 @@ fn get_all_commands() []Command {
|
||||||
line: '$vexe run examples/v_script.vsh > /dev/null'
|
line: '$vexe run examples/v_script.vsh > /dev/null'
|
||||||
okmsg: 'V can run the .VSH script file examples/v_script.vsh'
|
okmsg: 'V can run the .VSH script file examples/v_script.vsh'
|
||||||
}
|
}
|
||||||
//
|
$if linux {
|
||||||
|
res << Command{
|
||||||
|
line: '$vexe -b native run examples/native/hello_world.v > /dev/null'
|
||||||
|
okmsg: 'V compiles and runs examples/native/hello_world.v on the native backend for linux'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// only compilation:
|
||||||
res << Command{
|
res << Command{
|
||||||
line: '$vexe -os linux -b native -o hw.linux examples/hello_world.v'
|
line: '$vexe -os linux -b native -o hw.linux examples/hello_world.v'
|
||||||
okmsg: 'V compiles hello_world.v on the native backend for linux'
|
okmsg: 'V compiles hello_world.v on the native backend for linux'
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
// fn println(s string) { }
|
fn test_fn() {
|
||||||
|
println('test fn')
|
||||||
// fn test_fn() {
|
}
|
||||||
// println('test fn')
|
|
||||||
//}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println('native test')
|
println('native test')
|
||||||
// i := 0
|
mut i := 0
|
||||||
// for i < 5 {
|
for i < 5 {
|
||||||
|
println('Hello world from V native machine code generator, in a while style for loop!')
|
||||||
|
i++
|
||||||
|
}
|
||||||
for _ in 1 .. 5 {
|
for _ in 1 .. 5 {
|
||||||
println('Hello world from V native machine code generator!')
|
println('Hello world from V native machine code generator, in a range loop!')
|
||||||
// i++
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
println('Hello again!')
|
println('Hello again!')
|
||||||
//test_fn()
|
test_fn()
|
||||||
println('done')
|
println('done')
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,18 +105,36 @@ fn (mut g Gen) cmp(reg Register, size Size, val i64) {
|
||||||
g.println('cmp $reg, $val')
|
g.println('cmp $reg, $val')
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// `cmp rax, rbx`
|
||||||
rax // 0
|
fn (mut g Gen) cmp_reg(reg Register, reg2 Register) {
|
||||||
rcx // 1
|
match reg {
|
||||||
rdx // 2
|
.rax {
|
||||||
rbx // 3
|
match reg2 {
|
||||||
rsp // 4
|
.rbx {
|
||||||
rbp // 5
|
g.write([byte(0x48), 0x39, 0xd8])
|
||||||
rsi // 6
|
}
|
||||||
rdi // 7
|
else {
|
||||||
*/
|
g.n_error('Cannot compare $reg and $reg2')
|
||||||
// `a == 1`
|
}
|
||||||
// `cmp DWORD [rbp-0x4],0x1`
|
}
|
||||||
|
}
|
||||||
|
.rbx {
|
||||||
|
match reg2 {
|
||||||
|
.rax {
|
||||||
|
g.write([byte(0x48), 0x39, 0xc3])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('Cannot compare $reg and $reg2')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('Cannot compare $reg and $reg2')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.println('cmp $reg, $reg2')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) cmp_var(var_name string, val int) {
|
fn (mut g Gen) cmp_var(var_name string, val int) {
|
||||||
g.write8(0x81) // 83 for 1 byte?
|
g.write8(0x81) // 83 for 1 byte?
|
||||||
g.write8(0x7d)
|
g.write8(0x7d)
|
||||||
|
@ -126,6 +144,15 @@ fn (mut g Gen) cmp_var(var_name string, val int) {
|
||||||
g.println('cmp var `$var_name` $val')
|
g.println('cmp var `$var_name` $val')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `sub DWORD [rbp-0x4], 1`
|
||||||
|
fn (mut g Gen) dec_var(var_name string) {
|
||||||
|
g.write16(0x6d81) // 83 for 1 byte
|
||||||
|
offset := g.get_var_offset(var_name)
|
||||||
|
g.write8(0xff - offset + 1)
|
||||||
|
g.write32(1)
|
||||||
|
g.println('dec_var `$var_name`')
|
||||||
|
}
|
||||||
|
|
||||||
// `add DWORD [rbp-0x4], 1`
|
// `add DWORD [rbp-0x4], 1`
|
||||||
fn (mut g Gen) inc_var(var_name string) {
|
fn (mut g Gen) inc_var(var_name string) {
|
||||||
g.write16(0x4581) // 83 for 1 byte
|
g.write16(0x4581) // 83 for 1 byte
|
||||||
|
@ -260,7 +287,7 @@ fn (mut g Gen) mov_reg_to_var(var_offset int, reg Register) {
|
||||||
fn (mut g Gen) mov_var_to_reg(reg Register, var_offset int) {
|
fn (mut g Gen) mov_var_to_reg(reg Register, var_offset int) {
|
||||||
// 8b 7d f8 mov edi,DWORD PTR [rbp-0x8]
|
// 8b 7d f8 mov edi,DWORD PTR [rbp-0x8]
|
||||||
match reg {
|
match reg {
|
||||||
.rax, .rsi {
|
.rax, .rbx, .rsi {
|
||||||
g.write8(0x48)
|
g.write8(0x48)
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
|
@ -616,6 +643,7 @@ fn (mut g Gen) lea(reg Register, val int) {
|
||||||
g.write8(0x8d)
|
g.write8(0x8d)
|
||||||
g.write8(0x15)
|
g.write8(0x15)
|
||||||
g.write32(val)
|
g.write32(val)
|
||||||
|
g.println('lea $reg, $val')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) mov(reg Register, val int) {
|
fn (mut g Gen) mov(reg Register, val int) {
|
||||||
|
@ -626,7 +654,7 @@ fn (mut g Gen) mov(reg Register, val int) {
|
||||||
g.write8(0xc7)
|
g.write8(0xc7)
|
||||||
g.write8(0xc0)
|
g.write8(0xc0)
|
||||||
g.write32(-1)
|
g.write32(-1)
|
||||||
return
|
g.println('mov $reg, $val')
|
||||||
}
|
}
|
||||||
.rcx {
|
.rcx {
|
||||||
if val == -1 {
|
if val == -1 {
|
||||||
|
@ -638,12 +666,14 @@ fn (mut g Gen) mov(reg Register, val int) {
|
||||||
g.write8(0xff)
|
g.write8(0xff)
|
||||||
g.write8(0xff) // mov rcx 0xffff5
|
g.write8(0xff) // mov rcx 0xffff5
|
||||||
}
|
}
|
||||||
return
|
g.println('mov $reg, $val')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.n_error('unhandled mov $reg, -1')
|
g.n_error('unhandled mov $reg, -1')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g.println('mov $reg, $val')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if val == 0 {
|
if val == 0 {
|
||||||
// Optimise to xor reg, reg when val is 0
|
// Optimise to xor reg, reg when val is 0
|
||||||
|
@ -885,8 +915,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
|
||||||
} else {
|
} else {
|
||||||
g.call(int(addr))
|
g.call(int(addr))
|
||||||
}
|
}
|
||||||
g.println('fn call `${name}()`')
|
g.println('call `${name}()`')
|
||||||
// println('call $name $addr')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) patch_calls() {
|
fn (mut g Gen) patch_calls() {
|
||||||
|
@ -953,11 +982,29 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
g.mov_reg_to_var(dest, .rax)
|
g.mov_reg_to_var(dest, .rax)
|
||||||
}
|
}
|
||||||
.decl_assign {
|
.decl_assign {
|
||||||
g.allocate_var(name, 4, right.val.int())
|
g.allocate_var(name, 8, right.val.int())
|
||||||
}
|
}
|
||||||
.assign {
|
.assign {
|
||||||
match node.left_types[i] {
|
// dump(g.typ(node.left_types[i]))
|
||||||
7 { // ast.IndexExpr {
|
match node.left[i] {
|
||||||
|
ast.Ident {
|
||||||
|
// lname := '${node.left[i]}'
|
||||||
|
// g.expr(node.right[i])
|
||||||
|
g.mov(.rax, right.val.int())
|
||||||
|
offset := g.get_var_offset('i') // node.left[i])
|
||||||
|
g.mov_reg_to_var(offset, .rax)
|
||||||
|
}
|
||||||
|
ast.InfixExpr {
|
||||||
|
eprintln('assign')
|
||||||
|
// dump(node.left[i])
|
||||||
|
offset := g.get_var_offset('i') // node.left[i])
|
||||||
|
g.mov_reg_to_var(offset, native.fn_arg_registers[i])
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
ast.int_type_idx {
|
||||||
|
g.expr(node.left[i])
|
||||||
|
match node.left[i] {
|
||||||
|
ast.IndexExpr {
|
||||||
ie := node.left[i] as ast.IndexExpr
|
ie := node.left[i] as ast.IndexExpr
|
||||||
bracket := name.index('[') or {
|
bracket := name.index('[') or {
|
||||||
g.v_error('bracket expected', node.pos)
|
g.v_error('bracket expected', node.pos)
|
||||||
|
@ -971,7 +1018,13 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
g.mov(.rax, right.val.int())
|
g.mov(.rax, right.val.int())
|
||||||
g.mov_reg_to_var(dest, .rax)
|
g.mov_reg_to_var(dest, .rax)
|
||||||
// eprintln('${var_name}[$index] = ${right.val.int()}')
|
// eprintln('${var_name}[$index] = ${right.val.int()}')
|
||||||
|
} else {
|
||||||
|
dump(node)
|
||||||
|
g.v_error('oops', node.pos)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
else {
|
else {
|
||||||
tn := node.left[i].type_name()
|
tn := node.left[i].type_name()
|
||||||
dump(node.left_types)
|
dump(node.left_types)
|
||||||
|
@ -988,12 +1041,12 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
ast.InfixExpr {
|
ast.InfixExpr {
|
||||||
// eprintln('infix') dump(node) dump(right)
|
// eprintln('infix') dump(node) dump(right)
|
||||||
g.infix_expr(right)
|
g.infix_expr(right)
|
||||||
offset := g.allocate_var(name, 4, 0)
|
offset := g.allocate_var(name, 8, 0)
|
||||||
// `mov DWORD PTR [rbp-0x8],eax`
|
// `mov DWORD PTR [rbp-0x8],eax`
|
||||||
if g.pref.is_verbose {
|
if g.pref.is_verbose {
|
||||||
println('infix assignment $name offset=$offset.hex2()')
|
println('infix assignment $name offset=$offset.hex2()')
|
||||||
}
|
}
|
||||||
g.mov_reg_to_var(offset, .eax)
|
g.mov_reg_to_var(offset, .rax)
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
// eprintln('identr') dump(node) dump(right)
|
// eprintln('identr') dump(node) dump(right)
|
||||||
|
@ -1020,7 +1073,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
g.mov_reg_to_var(dest, .rax)
|
g.mov_reg_to_var(dest, .rax)
|
||||||
}
|
}
|
||||||
.decl_assign {
|
.decl_assign {
|
||||||
dest := g.allocate_var(name, 4, 0)
|
dest := g.allocate_var(name, 8, 0)
|
||||||
g.mov_var_to_reg(.rax, g.get_var_offset(right.name))
|
g.mov_var_to_reg(.rax, g.get_var_offset(right.name))
|
||||||
g.mov_reg_to_var(dest, .rax)
|
g.mov_reg_to_var(dest, .rax)
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1122,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
// a := arr[0]
|
// a := arr[0]
|
||||||
offset := g.allocate_var(name, 4, 0)
|
offset := g.allocate_var(name, 8, 0)
|
||||||
if g.pref.is_verbose {
|
if g.pref.is_verbose {
|
||||||
println('infix assignment $name offset=$offset.hex2()')
|
println('infix assignment $name offset=$offset.hex2()')
|
||||||
}
|
}
|
||||||
|
@ -1131,9 +1184,6 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
if g.pref.is_verbose {
|
|
||||||
println('infix expr op=$node.op')
|
|
||||||
}
|
|
||||||
// TODO
|
// TODO
|
||||||
if node.left is ast.InfixExpr {
|
if node.left is ast.InfixExpr {
|
||||||
g.n_error('only simple expressions are supported right now (not more than 2 operands)')
|
g.n_error('only simple expressions are supported right now (not more than 2 operands)')
|
||||||
|
@ -1229,31 +1279,39 @@ fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
|
||||||
match t.name {
|
match t.name {
|
||||||
'nop' {
|
'nop' {
|
||||||
g.write8(byte(0x90))
|
g.write8(byte(0x90))
|
||||||
|
g.println('nop')
|
||||||
}
|
}
|
||||||
'syscall' {
|
'syscall' {
|
||||||
g.write8(byte(0x0f))
|
g.write8(byte(0x0f))
|
||||||
g.write8(byte(0x05))
|
g.write8(byte(0x05))
|
||||||
|
g.println('syscall')
|
||||||
}
|
}
|
||||||
'ret' {
|
'ret' {
|
||||||
g.write8(byte(0xc3))
|
g.write8(byte(0xc3))
|
||||||
|
g.println('ret')
|
||||||
}
|
}
|
||||||
'int3' {
|
'int3' {
|
||||||
g.write8(byte(0xcc))
|
g.write8(byte(0xcc))
|
||||||
g.write8(byte(imm))
|
g.write8(byte(imm))
|
||||||
|
g.println('int3')
|
||||||
}
|
}
|
||||||
'sti' {
|
'sti' {
|
||||||
g.write8(byte(0xfb))
|
g.write8(byte(0xfb))
|
||||||
|
g.println('sti')
|
||||||
}
|
}
|
||||||
'cli' {
|
'cli' {
|
||||||
g.write8(byte(0xfa))
|
g.write8(byte(0xfa))
|
||||||
|
g.println('cli')
|
||||||
}
|
}
|
||||||
'int' {
|
'int' {
|
||||||
g.write8(byte(0xcd))
|
g.write8(byte(0xcd))
|
||||||
g.write8(byte(imm))
|
g.write8(byte(imm))
|
||||||
|
g.println('int')
|
||||||
}
|
}
|
||||||
'cpuid' {
|
'cpuid' {
|
||||||
g.write8(byte(0x0f))
|
g.write8(byte(0x0f))
|
||||||
g.write8(byte(0xa2))
|
g.write8(byte(0xa2))
|
||||||
|
g.println('cpuid')
|
||||||
}
|
}
|
||||||
'mov' {
|
'mov' {
|
||||||
g.write8(byte(0xb8 + reg))
|
g.write8(byte(0xb8 + reg))
|
||||||
|
@ -1261,6 +1319,7 @@ fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
|
||||||
g.write8(byt(imm, 1))
|
g.write8(byt(imm, 1))
|
||||||
g.write8(byt(imm, 2))
|
g.write8(byt(imm, 2))
|
||||||
g.write8(byt(imm, 3))
|
g.write8(byt(imm, 3))
|
||||||
|
g.println('mov $reg, $imm')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.v_error('unsupported instruction $t.name', asm_node.pos)
|
g.v_error('unsupported instruction $t.name', asm_node.pos)
|
||||||
|
@ -1437,8 +1496,18 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
lit := infix_expr.right as ast.IntegerLiteral
|
lit := infix_expr.right as ast.IntegerLiteral
|
||||||
g.cmp_var(infix_expr.left.name, lit.val.int())
|
g.cmp_var(infix_expr.left.name, lit.val.int())
|
||||||
|
match infix_expr.left.tok_kind {
|
||||||
|
.lt {
|
||||||
jump_addr = g.cjmp(.jge)
|
jump_addr = g.cjmp(.jge)
|
||||||
}
|
}
|
||||||
|
.gt {
|
||||||
|
jump_addr = g.cjmp(.jle)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('unhandled infix cond token')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
g.n_error('unhandled infix.left')
|
g.n_error('unhandled infix.left')
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,25 +446,84 @@ fn (mut g Gen) println(comment string) {
|
||||||
println(' ' + comment)
|
println(' ' + comment)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
|
||||||
g.v_error('for-in statement is not yet implemented', node.pos)
|
if node.has_init {
|
||||||
/*
|
g.stmts([node.init])
|
||||||
if node.is_range {
|
}
|
||||||
// `for x in 1..10 {`
|
start := g.pos()
|
||||||
// i := if node.val_var == '_' { g.new_tmp_var() } else { c_name(node.val_var) }
|
mut jump_addr := i64(0)
|
||||||
// val_typ := g.table.mktyp(node.val_type)
|
if node.has_cond {
|
||||||
g.write32(0x3131) // 'for (${g.typ(val_typ)} $i = ')
|
cond := node.cond
|
||||||
|
match cond {
|
||||||
|
ast.InfixExpr {
|
||||||
|
// g.infix_expr(node.cond)
|
||||||
|
match mut cond.left {
|
||||||
|
ast.Ident {
|
||||||
|
lit := cond.right as ast.IntegerLiteral
|
||||||
|
g.cmp_var(cond.left.name, lit.val.int())
|
||||||
|
match cond.op {
|
||||||
|
.gt {
|
||||||
|
jump_addr = g.cjmp(.jle)
|
||||||
|
}
|
||||||
|
.lt {
|
||||||
|
jump_addr = g.cjmp(.jge)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('unsupported conditional in for-c loop')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.n_error('unhandled infix.left')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
// dump(node.cond)
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
g.write32(0x3232) // ; $i < ')
|
}
|
||||||
g.expr(node.high)
|
g.stmts(node.stmts)
|
||||||
g.write32(0x3333) // '; ++$i) {')
|
if node.has_inc {
|
||||||
|
g.stmts([node.inc])
|
||||||
|
}
|
||||||
|
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
||||||
|
g.write32_at(jump_addr, int(g.pos() - jump_addr - 4))
|
||||||
|
|
||||||
|
// loop back
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
||||||
|
if node.stmts.len == 0 {
|
||||||
|
// if no statements, just dont make it
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if node.is_range {
|
||||||
|
// for a in node.cond .. node.high {
|
||||||
|
i := g.allocate_var(node.val_var, 8, 0) // iterator variable
|
||||||
|
g.expr(node.cond)
|
||||||
|
g.mov_reg_to_var(i, .rax) // i = node.cond // initial value
|
||||||
|
start := g.pos() // label-begin:
|
||||||
|
g.mov_var_to_reg(.rbx, i) // rbx = iterator value
|
||||||
|
g.expr(node.high) // final value
|
||||||
|
g.cmp_reg(.rbx, .rax) // rbx = iterator, rax = max value
|
||||||
|
jump_addr := g.cjmp(.jge) // leave loop if i is beyond end
|
||||||
|
g.stmts(node.stmts)
|
||||||
|
g.inc_var(node.val_var)
|
||||||
|
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
||||||
|
g.write32_at(jump_addr, int(g.pos() - jump_addr - 4))
|
||||||
|
/*
|
||||||
} else if node.kind == .array {
|
} else if node.kind == .array {
|
||||||
} else if node.kind == .array_fixed {
|
} else if node.kind == .array_fixed {
|
||||||
} else if node.kind == .map {
|
} else if node.kind == .map {
|
||||||
} else if node.kind == .string {
|
} else if node.kind == .string {
|
||||||
} else if node.kind == .struct_ {
|
} else if node.kind == .struct_ {
|
||||||
}
|
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
|
||||||
|
} else if it.kind == .map {
|
||||||
*/
|
*/
|
||||||
|
} else {
|
||||||
|
g.v_error('for-in statement is not yet implemented', node.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) gen_exit(node ast.Expr) {
|
pub fn (mut g Gen) gen_exit(node ast.Expr) {
|
||||||
|
@ -487,6 +546,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
g.fn_decl(node)
|
g.fn_decl(node)
|
||||||
}
|
}
|
||||||
|
ast.ForCStmt {
|
||||||
|
g.gen_forc_stmt(node)
|
||||||
|
}
|
||||||
ast.ForInStmt {
|
ast.ForInStmt {
|
||||||
g.for_in_stmt(node)
|
g.for_in_stmt(node)
|
||||||
}
|
}
|
||||||
|
@ -619,7 +681,10 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
g.n_error('array init expr not supported yet')
|
g.n_error('array init expr not supported yet')
|
||||||
}
|
}
|
||||||
ast.BoolLiteral {}
|
ast.BoolLiteral {
|
||||||
|
g.mov64(.rax, if node.val { 1 } else { 0 })
|
||||||
|
eprintln('bool literal')
|
||||||
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
if node.name == 'C.syscall' {
|
if node.name == 'C.syscall' {
|
||||||
g.gen_syscall(node)
|
g.gen_syscall(node)
|
||||||
|
@ -633,7 +698,12 @@ 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.get_var_offset(node.name)
|
||||||
|
// XXX this is intel specific
|
||||||
|
g.mov_var_to_reg(.rax, offset)
|
||||||
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
if node.is_comptime {
|
if node.is_comptime {
|
||||||
eprintln('Warning: ignored compile time conditional not yet supported for the native backend.')
|
eprintln('Warning: ignored compile time conditional not yet supported for the native backend.')
|
||||||
|
@ -641,8 +711,15 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
g.if_expr(node)
|
g.if_expr(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.InfixExpr {}
|
ast.InfixExpr {
|
||||||
ast.IntegerLiteral {}
|
g.infix_expr(node)
|
||||||
|
// get variable by name
|
||||||
|
// save the result in rax
|
||||||
|
}
|
||||||
|
ast.IntegerLiteral {
|
||||||
|
g.mov64(.rax, node.val.int())
|
||||||
|
// g.gen_print_reg(.rax, 3, fd)
|
||||||
|
}
|
||||||
ast.PostfixExpr {
|
ast.PostfixExpr {
|
||||||
g.postfix_expr(node)
|
g.postfix_expr(node)
|
||||||
}
|
}
|
||||||
|
@ -669,9 +746,15 @@ fn (mut g Gen) postfix_expr(node ast.PostfixExpr) {
|
||||||
}
|
}
|
||||||
ident := node.expr as ast.Ident
|
ident := node.expr as ast.Ident
|
||||||
var_name := ident.name
|
var_name := ident.name
|
||||||
if node.op == .inc {
|
match node.op {
|
||||||
|
.inc {
|
||||||
g.inc_var(var_name)
|
g.inc_var(var_name)
|
||||||
}
|
}
|
||||||
|
.dec {
|
||||||
|
g.dec_var(var_name)
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[noreturn]
|
[noreturn]
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
fn main() {
|
||||||
|
mut i := 0
|
||||||
|
for i = 0; i < 3; i++ {
|
||||||
|
println('loop0')
|
||||||
|
}
|
||||||
|
i = 0
|
||||||
|
for i < 3 {
|
||||||
|
println('loop1')
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
for _ in 0 .. 3 {
|
||||||
|
println('loop2')
|
||||||
|
}
|
||||||
|
n := 3
|
||||||
|
for _ in 0 .. n {
|
||||||
|
println('loop3')
|
||||||
|
}
|
||||||
|
for i = 3; i > 0; i-- {
|
||||||
|
println('loop4')
|
||||||
|
}
|
||||||
|
i = 3
|
||||||
|
for i > 0 {
|
||||||
|
println('loop5')
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
loop0
|
||||||
|
loop0
|
||||||
|
loop0
|
||||||
|
loop1
|
||||||
|
loop1
|
||||||
|
loop1
|
||||||
|
loop2
|
||||||
|
loop2
|
||||||
|
loop2
|
||||||
|
loop3
|
||||||
|
loop3
|
||||||
|
loop3
|
||||||
|
loop4
|
||||||
|
loop4
|
||||||
|
loop4
|
||||||
|
loop5
|
||||||
|
loop5
|
||||||
|
loop5
|
Loading…
Reference in New Issue