mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
native: implement for in string
for amd64 (#24613)
This commit is contained in:
parent
42a992775e
commit
f9a4f8f19f
9 changed files with 128 additions and 10 deletions
|
@ -212,6 +212,10 @@ fn (mut c Amd64) cmp(reg Amd64Register, size Size, val i64) {
|
|||
c.g.println('cmp ${reg}, ${val}')
|
||||
}
|
||||
|
||||
fn (mut c Amd64) cmp_reg2(reg Register, reg2 Register) {
|
||||
c.cmp_reg(reg as Amd64Register, reg2 as Amd64Register)
|
||||
}
|
||||
|
||||
// `cmp rax, rbx`
|
||||
fn (mut c Amd64) cmp_reg(reg Amd64Register, reg2 Amd64Register) {
|
||||
match reg {
|
||||
|
@ -1101,8 +1105,12 @@ fn (mut c Amd64) push(r Register) {
|
|||
c.g.write8(0x50 + i32(reg) - 8)
|
||||
}
|
||||
c.is_16bit_aligned = !c.is_16bit_aligned
|
||||
c.g.println('push ${reg}')
|
||||
c.g.stack_depth++
|
||||
c.g.println('push ${reg}; stack_depth:${c.g.stack_depth}')
|
||||
}
|
||||
|
||||
fn (mut c Amd64) pop2(r Register) {
|
||||
c.pop(r as Amd64Register)
|
||||
}
|
||||
|
||||
pub fn (mut c Amd64) pop(reg Amd64Register) {
|
||||
|
@ -1111,8 +1119,8 @@ pub fn (mut c Amd64) pop(reg Amd64Register) {
|
|||
}
|
||||
c.g.write8(0x58 + i32(reg) % 8)
|
||||
c.is_16bit_aligned = !c.is_16bit_aligned
|
||||
c.g.println('pop ${reg}')
|
||||
c.g.stack_depth--
|
||||
c.g.println('pop ${reg} ; stack_depth:${c.g.stack_depth}')
|
||||
}
|
||||
|
||||
pub fn (mut c Amd64) sub8(reg Amd64Register, val i32) {
|
||||
|
@ -3620,7 +3628,7 @@ pub fn (mut c Amd64) allocate_var(name string, size i32, initial_val Number) i32
|
|||
}
|
||||
|
||||
// println('allocate_var(size=$size, initial_val=$initial_val)')
|
||||
c.g.println('mov [rbp-${int(n).hex2()}], ${initial_val} ; Allocate var `${name}`')
|
||||
c.g.println('mov [rbp-${int(n).hex2()}], ${initial_val} ; Allocate var `${name}` size: ${size}')
|
||||
return c.g.stack_var_pos
|
||||
}
|
||||
|
||||
|
|
|
@ -535,6 +535,14 @@ pub fn (mut c Arm64) add_reg2(r Register, r2 Register) {
|
|||
panic('Arm64.add_reg2() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) pop2(r Register) {
|
||||
panic('Arm64.pop2() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) cmp_reg2(reg Register, reg2 Register) {
|
||||
panic('Arm64.add_reg2() not implemented')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) create_string_struct(typ ast.Type, name string, str string) {
|
||||
panic('Arm64.add_reg2() not implemented')
|
||||
}
|
||||
|
|
|
@ -46,7 +46,12 @@ const whitelist = {
|
|||
'string.is_capital': false
|
||||
'string.is_ascii': false
|
||||
'string.is_identifier': false
|
||||
// 'string.is_blank': false need for in
|
||||
'string.is_blank': false
|
||||
'string.indent_width': false
|
||||
'string.index_u8': false
|
||||
'string.last_index': true
|
||||
'string.last_index_u8': false
|
||||
'string.contains_u8': false
|
||||
}
|
||||
|
||||
fn (g &Gen) is_blacklisted(name string, is_builtin bool) bool {
|
||||
|
|
|
@ -95,6 +95,7 @@ mut:
|
|||
cmp_to_stack_top(r Register)
|
||||
cmp_var_reg(var Var, reg Register, config VarConfig)
|
||||
cmp_var(var Var, val i32, config VarConfig)
|
||||
cmp_reg2(reg Register, reg2 Register)
|
||||
cmp_zero(reg Register)
|
||||
convert_bool_to_string(r Register)
|
||||
convert_int_to_string(a Register, b Register)
|
||||
|
@ -131,6 +132,7 @@ mut:
|
|||
mov64(r Register, val Number)
|
||||
movabs(reg Register, val i64)
|
||||
patch_relative_jmp(pos i32, addr i64)
|
||||
pop2(r Register)
|
||||
prefix_expr(node ast.PrefixExpr)
|
||||
push(r Register)
|
||||
ret()
|
||||
|
|
|
@ -255,6 +255,7 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
|||
}
|
||||
|
||||
fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
|
||||
main_reg := g.code_gen.main_reg()
|
||||
if node.is_range {
|
||||
g.println('; for ${node.val_var} in range {')
|
||||
// for a in node.cond .. node.high {
|
||||
|
@ -262,7 +263,6 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
|
|||
i := g.code_gen.allocate_var(node.val_var, 8, i64(0)) // iterator variable
|
||||
g.println('; evaluate node.cond for lower bound:')
|
||||
g.expr(node.cond) // outputs the lower loop bound (initial value) to the main reg
|
||||
main_reg := g.code_gen.main_reg()
|
||||
g.println('; move the result to i')
|
||||
g.code_gen.mov_reg_to_var(LocalVar{i, ast.i64_type_idx, node.val_var}, main_reg) // i = node.cond // initial value
|
||||
|
||||
|
@ -299,11 +299,79 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { // Work on that
|
|||
g.labels.addrs[end_label] = g.pos()
|
||||
g.println('; label ${end_label} (end_label)')
|
||||
g.println('; for ${node.val_var} in range }')
|
||||
} else if node.kind == .string {
|
||||
g.println('; for ${node.val_var} in string {')
|
||||
// for c in my_string {
|
||||
|
||||
key_var := if node.key_var == '' { 'i' } else { node.key_var }
|
||||
i := g.code_gen.allocate_var(key_var, 8, i64(0)) // iterator variable
|
||||
c := g.code_gen.allocate_var(node.val_var, 1, i64(0)) // char variable
|
||||
|
||||
g.expr(node.cond) // get the address of the string variable
|
||||
g.code_gen.mov_deref(Amd64Register.rdx, main_reg, ast.charptr_type)
|
||||
g.println('; push address of the string chars')
|
||||
g.code_gen.push(Amd64Register.rdx) // address of the string
|
||||
g.code_gen.add(main_reg, g.get_field_offset(ast.string_type, 'len'))
|
||||
g.println('; push address of the len:')
|
||||
g.code_gen.push(main_reg) // address of the len
|
||||
|
||||
start := g.pos() // label-begin:
|
||||
|
||||
g.println('; check iterator against upper loop bound')
|
||||
g.code_gen.mov_var_to_reg(main_reg, LocalVar{i, ast.i64_type_idx, key_var})
|
||||
g.println('; pop address of the len:')
|
||||
g.code_gen.pop2(Amd64Register.rdx)
|
||||
g.println('; push address of the len:')
|
||||
g.code_gen.push(Amd64Register.rdx) // len
|
||||
g.code_gen.mov_deref(Amd64Register.rdx, Amd64Register.rdx, ast.int_type)
|
||||
g.code_gen.cmp_reg2(main_reg, Amd64Register.rdx)
|
||||
jump_addr := g.code_gen.cjmp(.jge) // leave loop i >= len
|
||||
|
||||
g.println('; pop address of the len:')
|
||||
g.code_gen.pop2(Amd64Register.rdx) // len
|
||||
g.println('; pop address of the string chars')
|
||||
g.code_gen.pop2(Amd64Register.rax) // address of the string
|
||||
g.println('; push address of the string chars')
|
||||
g.code_gen.push(Amd64Register.rax)
|
||||
g.println('; push address of the len:')
|
||||
g.code_gen.push(Amd64Register.rdx) // len
|
||||
|
||||
g.code_gen.mov_var_to_reg(Amd64Register.rdx, LocalVar{i, ast.i64_type_idx, key_var})
|
||||
g.code_gen.add_reg2(Amd64Register.rax, Amd64Register.rdx)
|
||||
g.code_gen.mov_deref(Amd64Register.rax, Amd64Register.rax, ast.u8_type_idx)
|
||||
g.code_gen.mov_reg_to_var(LocalVar{c, ast.u8_type_idx, node.val_var}, Amd64Register.rax) // store the char
|
||||
|
||||
end_label := g.labels.new_label()
|
||||
g.labels.patches << LabelPatch{
|
||||
id: end_label
|
||||
pos: jump_addr
|
||||
}
|
||||
g.println('; jump to label ${end_label} (end_label)')
|
||||
|
||||
start_label := g.labels.new_label() // used for continue
|
||||
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() // used for continue (continue: jump before the inc)
|
||||
g.println('; label ${start_label} (continue_label)')
|
||||
|
||||
g.code_gen.inc_var(LocalVar{i, ast.i64_type_idx, key_var})
|
||||
g.labels.branches.pop()
|
||||
g.code_gen.jmp_back(start) // loops
|
||||
|
||||
g.labels.addrs[end_label] = g.pos()
|
||||
g.code_gen.pop2(Amd64Register.rdx) // len
|
||||
g.code_gen.pop2(Amd64Register.rax) // address of the string
|
||||
g.println('; label ${end_label} (end_label)')
|
||||
g.println('; for ${node.val_var} in string }')
|
||||
/*
|
||||
} 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 {
|
||||
|
|
|
@ -22,7 +22,6 @@ assert !a.is_ascii()
|
|||
assert '_9'.is_identifier() == true
|
||||
assert 'a 9'.is_identifier() == false
|
||||
assert 't'.is_identifier() == true
|
||||
/*
|
||||
assert ''.is_blank()
|
||||
assert ' '.is_blank()
|
||||
assert ' \t'.is_blank()
|
||||
|
@ -48,18 +47,18 @@ assert !a.is_ascii()
|
|||
assert 'abc'.index_u8(`A`) == -1
|
||||
assert 'abc'.index_u8(`B`) == -1
|
||||
assert 'abc'.index_u8(`C`) == -1
|
||||
/*
|
||||
assert 'abcabca'.last_index('ca')? == 5
|
||||
assert 'abcabca'.last_index('ab')? == 3
|
||||
assert 'abcabca'.last_index('b')? == 4
|
||||
assert 'Zabcabca'.last_index('Z')? == 0
|
||||
x := 'Zabcabca'.last_index('Y')
|
||||
assert x == none
|
||||
// TODO: `assert 'Zabcabca'.index_last('Y') == none` is a cgen error, 2023/12/04
|
||||
*/
|
||||
assert 'abcabca'.last_index_u8(`a`) == 6
|
||||
assert 'abcabca'.last_index_u8(`c`) == 5
|
||||
assert 'abcabca'.last_index_u8(`b`) == 4
|
||||
assert 'Zabcabca'.last_index_u8(`Z`) == 0
|
||||
//
|
||||
assert 'abc'.last_index_u8(`d`) == -1
|
||||
assert 'abc'.last_index_u8(`A`) == -1
|
||||
assert 'abc'.last_index_u8(`B`) == -1
|
||||
|
@ -69,6 +68,7 @@ assert !a.is_ascii()
|
|||
assert 'abc abca'.contains_u8(`c`)
|
||||
assert 'abc abca'.contains_u8(` `)
|
||||
assert !'abc abca'.contains_u8(`A`)
|
||||
/*
|
||||
assert 'Abcd'.camel_to_snake() == 'abcd'
|
||||
assert 'aBcd'.camel_to_snake() == 'a_bcd'
|
||||
assert 'AAbb'.camel_to_snake() == 'aa_bb'
|
||||
|
|
21
vlib/v/gen/native/tests/linux.vv
Normal file
21
vlib/v/gen/native/tests/linux.vv
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
fn test_for_c_in_string() {
|
||||
$if windows {
|
||||
println('0')
|
||||
println('97')
|
||||
println('1')
|
||||
println('98')
|
||||
println('2')
|
||||
println('99')
|
||||
} $else {
|
||||
s := 'abc'
|
||||
for i, c in s {
|
||||
println(i)
|
||||
println(int(c))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_for_c_in_string()
|
||||
}
|
6
vlib/v/gen/native/tests/linux.vv.out
Normal file
6
vlib/v/gen/native/tests/linux.vv.out
Normal file
|
@ -0,0 +1,6 @@
|
|||
0
|
||||
97
|
||||
1
|
||||
98
|
||||
2
|
||||
99
|
|
@ -49,7 +49,7 @@ fn test_native() {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if test == 'fibonacci_native.vv' {
|
||||
if test == 'fibonacci_native.vv' || test.contains('linux') {
|
||||
if user_os == 'windows' {
|
||||
println('>>> SKIPPING ${test} on windows for now')
|
||||
continue
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue