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

native: move for_in_stmt to stmt.v (#18705)

This commit is contained in:
Eliyaan (Nopana) 2023-07-04 21:43:23 +02:00 committed by GitHub
parent 578264c815
commit b0323c79ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 61 deletions

View File

@ -10,7 +10,7 @@ import v.token
pub struct Amd64 { pub struct Amd64 {
mut: mut:
g &Gen = unsafe { nil } g &Gen = unsafe { nil }
// arm64 specific stuff for code generation // amd64 specific stuff for code generation
is_16bit_aligned bool is_16bit_aligned bool
} }
@ -995,7 +995,8 @@ fn (mut c Amd64) ret() {
c.g.println('ret') c.g.println('ret')
} }
fn (mut c Amd64) push(reg Amd64Register) { fn (mut c Amd64) push(r Register) {
reg := r as Amd64Register
if int(reg) < int(Amd64Register.r8) { if int(reg) < int(Amd64Register.r8) {
c.g.write8(0x50 + int(reg)) c.g.write8(0x50 + int(reg))
} else { } else {
@ -1122,7 +1123,7 @@ fn (mut c Amd64) leave() {
c.g.println('; label 0: return') c.g.println('; label 0: return')
if c.g.defer_stmts.len != 0 { if c.g.defer_stmts.len != 0 {
// save return value // save return value
c.push(.rax) c.push(Amd64Register.rax)
for defer_stmt in c.g.defer_stmts.reverse() { for defer_stmt in c.g.defer_stmts.reverse() {
name := '_defer${defer_stmt.idx_in_fn}' name := '_defer${defer_stmt.idx_in_fn}'
defer_var := c.g.get_var_offset(name) defer_var := c.g.get_var_offset(name)
@ -1712,14 +1713,14 @@ pub fn (mut c Amd64) call_fn(node ast.CallExpr) {
is_16bit_aligned := c.is_16bit_aligned != (stack_size % 2 == 1) is_16bit_aligned := c.is_16bit_aligned != (stack_size % 2 == 1)
if !is_16bit_aligned { if !is_16bit_aligned {
// dummy data // dummy data
c.push(.rbp) c.push(Amd64Register.rbp)
} }
reg_args << ssereg_args reg_args << ssereg_args
reg_args << stack_args reg_args << stack_args
for i in reg_args.reverse() { for i in reg_args.reverse() {
if i == 0 && is_struct_return { if i == 0 && is_struct_return {
c.lea_var_to_reg(Amd64Register.rax, return_pos) c.lea_var_to_reg(Amd64Register.rax, return_pos)
c.push(.rax) c.push(Amd64Register.rax)
continue continue
} }
c.g.expr(args[i].expr) c.g.expr(args[i].expr)
@ -1754,17 +1755,17 @@ pub fn (mut c Amd64) call_fn(node ast.CallExpr) {
} else { } else {
match args_size[i] { match args_size[i] {
1...8 { 1...8 {
c.push(.rax) c.push(Amd64Register.rax)
} }
9...16 { 9...16 {
c.push(.rdx) c.push(Amd64Register.rdx)
c.push(.rax) c.push(Amd64Register.rax)
} }
else { else {
c.add(.rax, args_size[i] - ((args_size[i] + 7) % 8 + 1)) c.add(.rax, args_size[i] - ((args_size[i] + 7) % 8 + 1))
for _ in 0 .. (args_size[i] + 7) / 8 { for _ in 0 .. (args_size[i] + 7) / 8 {
c.mov_deref(.rdx, .rax, ast.i64_type_idx) c.mov_deref(.rdx, .rax, ast.i64_type_idx)
c.push(.rdx) c.push(Amd64Register.rdx)
c.sub(.rax, 8) c.sub(.rax, 8)
} }
} }
@ -1854,51 +1855,6 @@ fn (mut c Amd64) call_builtin(name Builtin) i64 {
return call_addr return call_addr
} }
fn (mut c Amd64) for_in_stmt(node ast.ForInStmt) {
if node.is_range {
// for a in node.cond .. node.high {
i := c.allocate_var(node.val_var, 8, 0) // iterator variable
c.g.expr(node.cond)
c.mov_reg_to_var(LocalVar{i, ast.i64_type_idx, node.val_var}, Amd64Register.rax) // i = node.cond // initial value
start := c.g.pos() // label-begin:
start_label := c.g.labels.new_label()
c.mov_var_to_reg(Amd64Register.rbx, LocalVar{i, ast.i64_type_idx, node.val_var}) // rbx = iterator value
c.g.expr(node.high) // final value
c.cmp_reg(.rbx, .rax) // rbx = iterator, rax = max value
jump_addr := c.cjmp(.jge) // leave loop if i is beyond end
end_label := c.g.labels.new_label()
c.g.labels.patches << LabelPatch{
id: end_label
pos: jump_addr
}
c.g.println('; jump to label ${end_label}')
c.g.labels.branches << BranchLabel{
name: node.label
start: start_label
end: end_label
}
c.g.stmts(node.stmts)
c.g.labels.addrs[start_label] = c.g.pos()
c.g.println('; label ${start_label}')
c.inc_var(LocalVar{i, ast.i64_type_idx, node.val_var})
c.g.labels.branches.pop()
c.jmp_back(start)
c.g.labels.addrs[end_label] = c.g.pos()
c.g.println('; label ${end_label}')
/*
} else if node.kind == .array {
} else if node.kind == .array_fixed {
} else if node.kind == .map {
} else if node.kind == .string {
} else if node.kind == .struct_ {
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
} else if it.kind == .map {
*/
} else {
c.g.v_error('for-in statement is not yet implemented', node.pos)
}
}
fn (mut c Amd64) gen_concat_expr(node ast.ConcatExpr) { fn (mut c Amd64) gen_concat_expr(node ast.ConcatExpr) {
typ := node.return_type typ := node.return_type
ts := c.g.table.sym(typ) ts := c.g.table.sym(typ)
@ -3186,7 +3142,7 @@ fn (mut c Amd64) infloop() {
} }
fn (mut c Amd64) fn_decl(node ast.FnDecl) { fn (mut c Amd64) fn_decl(node ast.FnDecl) {
c.push(.rbp) c.push(Amd64Register.rbp)
c.mov_reg(Amd64Register.rbp, Amd64Register.rsp) c.mov_reg(Amd64Register.rbp, Amd64Register.rsp)
local_alloc_pos := c.g.pos() local_alloc_pos := c.g.pos()
c.sub(.rsp, 0) c.sub(.rsp, 0)
@ -3616,7 +3572,7 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) {
loop_start := c.g.pos() loop_start := c.g.pos()
c.g.println('; label ${loop_label}') c.g.println('; label ${loop_label}')
c.push(.rax) c.push(Amd64Register.rax)
c.mov(Amd64Register.rdx, 0) c.mov(Amd64Register.rdx, 0)
c.mov(Amd64Register.rbx, 10) c.mov(Amd64Register.rbx, 10)
@ -3719,7 +3675,7 @@ fn (mut c Amd64) gen_match_expr(expr ast.MatchExpr) {
} else { } else {
c.g.expr(expr.cond) c.g.expr(expr.cond)
} }
c.push(.rax) c.push(Amd64Register.rax)
mut else_label := 0 mut else_label := 0
for i, branch in expr.branches { for i, branch in expr.branches {
@ -3747,7 +3703,7 @@ fn (mut c Amd64) gen_match_expr(expr ast.MatchExpr) {
id: branch_labels[i] id: branch_labels[i]
pos: then_addr pos: then_addr
} }
c.push(.rdx) c.push(Amd64Register.rdx)
} }
else { else {
c.g.expr(cond) c.g.expr(cond)
@ -3758,7 +3714,7 @@ fn (mut c Amd64) gen_match_expr(expr ast.MatchExpr) {
id: branch_labels[i] id: branch_labels[i]
pos: then_addr pos: then_addr
} }
c.push(.rdx) c.push(Amd64Register.rdx)
} }
} }
} }
@ -4172,6 +4128,11 @@ fn (mut c Amd64) gen_cast_expr(expr ast.CastExpr) {
} }
} }
fn (mut c Amd64) cmp_to_stack_top(reg Register) {
c.pop(.rbx)
c.cmp_reg(.rbx, reg as Amd64Register)
}
// Temporary! // Temporary!
fn (mut c Amd64) adr(r Arm64Register, delta int) { fn (mut c Amd64) adr(r Arm64Register, delta int) {
panic('`adr` instruction not supported with amd64') panic('`adr` instruction not supported with amd64')

View File

@ -522,3 +522,11 @@ fn (mut c Arm64) call_addr_at(addr int, at i64) i64 {
fn (mut c Arm64) gen_concat_expr(expr ast.ConcatExpr) { fn (mut c Arm64) gen_concat_expr(expr ast.ConcatExpr) {
panic('Arm64.gen_concat_expr() not implemented') panic('Arm64.gen_concat_expr() not implemented')
} }
fn (mut c Arm64) cmp_to_stack_top(reg Register) {
panic('Arm64.cmp_to_stack_top() not implemented')
}
fn (mut c Arm64) push(r Register) {
panic('Arm64.push() not implemented')
}

View File

@ -78,6 +78,7 @@ mut:
call_fn(node ast.CallExpr) call_fn(node ast.CallExpr)
call(addr int) i64 call(addr int) i64
cjmp(op JumpOp) int cjmp(op JumpOp) int
cmp_to_stack_top(r Register)
cmp_var_reg(var Var, reg Register, config VarConfig) cmp_var_reg(var Var, reg Register, config VarConfig)
cmp_var(var Var, val int, config VarConfig) cmp_var(var Var, val int, config VarConfig)
cmp_zero(reg Register) cmp_zero(reg Register)
@ -86,7 +87,6 @@ mut:
convert_rune_to_string(r Register, buffer int, var Var, config VarConfig) convert_rune_to_string(r Register, buffer int, var Var, config VarConfig)
dec_var(var Var, config VarConfig) dec_var(var Var, config VarConfig)
fn_decl(node ast.FnDecl) fn_decl(node ast.FnDecl)
for_in_stmt(node ast.ForInStmt)
gen_asm_stmt(asm_node ast.AsmStmt) gen_asm_stmt(asm_node ast.AsmStmt)
gen_assert(assert_node ast.AssertStmt) gen_assert(assert_node ast.AssertStmt)
gen_cast_expr(expr ast.CastExpr) gen_cast_expr(expr ast.CastExpr)
@ -118,6 +118,7 @@ mut:
mov64(r Register, val i64) mov64(r Register, val i64)
movabs(reg Register, val i64) movabs(reg Register, val i64)
prefix_expr(node ast.PrefixExpr) prefix_expr(node ast.PrefixExpr)
push(r Register)
ret() ret()
return_stmt(node ast.Return) return_stmt(node ast.Return)
reverse_string(r Register) reverse_string(r Register)

View File

@ -63,7 +63,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
// if no statements, just dont make it // if no statements, just dont make it
return return
} }
g.code_gen.for_in_stmt(node) g.for_in_stmt(node)
} }
ast.ForStmt { ast.ForStmt {
g.for_stmt(node) g.for_stmt(node)
@ -274,3 +274,52 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
g.println('; label ${end_label}') g.println('; label ${end_label}')
g.println('jmp after for') g.println('jmp after for')
} }
fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
if node.is_range {
// for a in node.cond .. node.high {
i := g.code_gen.allocate_var(node.val_var, 8, 0) // iterator variable
g.expr(node.cond) // outputs the lower loop bound (initial value) to the main reg
main_reg := g.code_gen.main_reg()
g.code_gen.mov_reg_to_var(LocalVar{i, ast.i64_type_idx, node.val_var}, main_reg) // i = node.cond // initial value
start := g.pos() // label-begin:
start_label := g.labels.new_label()
g.code_gen.mov_var_to_reg(main_reg, LocalVar{i, ast.i64_type_idx, node.val_var})
g.code_gen.push(main_reg) // put the iterator on the stack
g.expr(node.high) // final value (upper bound) to the main reg
g.code_gen.cmp_to_stack_top(main_reg)
jump_addr := g.code_gen.cjmp(.jge) // leave loop i >= upper bound
end_label := g.labels.new_label()
g.labels.patches << LabelPatch{
id: end_label
pos: jump_addr
}
g.println('; jump to label ${end_label}')
g.labels.branches << BranchLabel{
name: node.label
start: start_label
end: end_label
}
g.stmts(node.stmts) // writes the actual body of the loop
g.labels.addrs[start_label] = g.pos()
g.println('; label ${start_label}')
g.code_gen.inc_var(LocalVar{i, ast.i64_type_idx, node.val_var})
g.labels.branches.pop()
g.code_gen.jmp_back(start) // loops
g.labels.addrs[end_label] = g.pos()
g.println('; label ${end_label}')
/*
} else if node.kind == .array {
} else if node.kind == .array_fixed {
} else if node.kind == .map {
} else if node.kind == .string {
} 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)
}
}