mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: rune
type literals/printing, pointer comparison and some missing branches in functions (#17839)
This commit is contained in:
parent
e1b8617c94
commit
fedf0f7939
|
@ -1521,11 +1521,16 @@ fn (mut g Gen) mul_reg(a Register, b Register) {
|
|||
g.write8(0xf7)
|
||||
g.write8(0xeb)
|
||||
}
|
||||
.rdx {
|
||||
g.write8(0x48)
|
||||
g.write8(0xf7)
|
||||
g.write8(0xe2)
|
||||
}
|
||||
else {
|
||||
panic('unhandled div ${a}')
|
||||
panic('unhandled mul ${b}')
|
||||
}
|
||||
}
|
||||
g.println('mul ${a}')
|
||||
g.println('mul ${b}')
|
||||
}
|
||||
|
||||
fn (mut g Gen) imul_reg(r Register) {
|
||||
|
@ -1558,11 +1563,16 @@ fn (mut g Gen) div_reg(a Register, b Register) {
|
|||
g.write8(0xf7)
|
||||
g.write8(0xfb) // idiv ebx
|
||||
}
|
||||
.rdx {
|
||||
g.write8(0x48)
|
||||
g.write8(0xf7)
|
||||
g.write8(0xf2)
|
||||
}
|
||||
else {
|
||||
panic('unhandled div ${a}')
|
||||
panic('unhandled div ${b}')
|
||||
}
|
||||
}
|
||||
g.println('div ${a}')
|
||||
g.println('div ${b}')
|
||||
}
|
||||
|
||||
fn (mut g Gen) mod_reg(a Register, b Register) {
|
||||
|
@ -2207,7 +2217,7 @@ fn (mut g Gen) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, nam
|
|||
}
|
||||
ast.StringLiteral {
|
||||
// TODO: use learel
|
||||
str := g.eval_escape_codes(e)
|
||||
str := g.eval_str_lit_escape_codes(e)
|
||||
g.mov64(.rsi, g.allocate_string(str, 2, .abs64)) // for rsi its 2
|
||||
g.mov_reg_to_var(LocalVar{pos, ast.u64_type_idx, ''}, .rsi)
|
||||
pos += 8
|
||||
|
@ -2247,7 +2257,7 @@ fn (mut g Gen) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, nam
|
|||
ast.StringLiteral {
|
||||
dest := g.allocate_var(name, 8, 0)
|
||||
ie := right as ast.StringLiteral
|
||||
str := g.eval_escape_codes(ie)
|
||||
str := g.eval_str_lit_escape_codes(ie)
|
||||
g.learel(.rsi, g.allocate_string(str, 3, .rel32))
|
||||
g.mov_reg_to_var(LocalVar{dest, ast.u64_type_idx, name}, .rsi)
|
||||
}
|
||||
|
@ -2831,7 +2841,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
|||
}
|
||||
}
|
||||
if node.left_type !in ast.integer_type_idxs && node.left_type != ast.bool_type_idx
|
||||
&& g.table.sym(node.left_type).info !is ast.Enum {
|
||||
&& g.table.sym(node.left_type).info !is ast.Enum && !node.left_type.is_ptr()
|
||||
&& !node.left_type.is_voidptr() {
|
||||
g.n_error('unsupported type for `${node.op}`: ${node.left_type}')
|
||||
}
|
||||
// left: rax, right: rdx
|
||||
|
@ -3203,6 +3214,18 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
|||
.gt {
|
||||
jump_addr = g.cjmp(.jle)
|
||||
}
|
||||
.le {
|
||||
jump_addr = g.cjmp(.jg)
|
||||
}
|
||||
.ge {
|
||||
jump_addr = g.cjmp(.jl)
|
||||
}
|
||||
.ne {
|
||||
jump_addr = g.cjmp(.je)
|
||||
}
|
||||
.eq {
|
||||
jump_addr = g.cjmp(.jne)
|
||||
}
|
||||
else {
|
||||
g.n_error('unhandled infix cond token')
|
||||
}
|
||||
|
|
|
@ -686,12 +686,15 @@ fn (mut g Gen) gen_match_expr(expr ast.MatchExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
|
||||
fn (mut g Gen) eval_str_lit_escape_codes(str_lit ast.StringLiteral) string {
|
||||
if str_lit.is_raw {
|
||||
return str_lit.val
|
||||
} else {
|
||||
return g.eval_escape_codes(str_lit.val)
|
||||
}
|
||||
}
|
||||
|
||||
str := str_lit.val
|
||||
fn (mut g Gen) eval_escape_codes(str string) string {
|
||||
mut buffer := []u8{}
|
||||
|
||||
mut i := 0
|
||||
|
@ -705,7 +708,7 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
|
|||
// skip \
|
||||
i++
|
||||
match str[i] {
|
||||
`\\`, `'`, `"` {
|
||||
`\\`, `'`, `"`, `\`` {
|
||||
buffer << str[i]
|
||||
i++
|
||||
}
|
||||
|
@ -792,9 +795,23 @@ fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
|
||||
fn (mut g Gen) gen_var_to_string(reg Register, expr ast.Expr, var Var, config VarConfig) {
|
||||
typ := g.get_type_from_var(var)
|
||||
if typ.is_int() {
|
||||
if typ == ast.rune_type_idx {
|
||||
buffer := g.allocate_var('rune-buffer', 8, 0)
|
||||
g.lea_var_to_reg(reg, buffer)
|
||||
match reg {
|
||||
.rax {
|
||||
g.mov_var_to_reg(.rdi, var, config)
|
||||
g.write8(0x48)
|
||||
g.write8(0x89)
|
||||
g.write8(0x38)
|
||||
}
|
||||
else {
|
||||
g.n_error('rune to string not implemented for ${reg}')
|
||||
}
|
||||
}
|
||||
} else if typ.is_int() {
|
||||
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
|
||||
g.mov_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 0), var, config)
|
||||
g.lea_var_to_reg(g.get_builtin_arg_reg(.int_to_string, 1), buffer)
|
||||
|
@ -804,7 +821,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
|
|||
g.mov_var_to_reg(g.get_builtin_arg_reg(.bool_to_string, 0), var, config)
|
||||
g.call_builtin(.bool_to_string)
|
||||
} else if typ.is_string() {
|
||||
g.mov_var_to_reg(.rax, var, config)
|
||||
g.mov_var_to_reg(reg, var, config)
|
||||
} else {
|
||||
g.n_error('int-to-string conversion not implemented for type ${typ}')
|
||||
}
|
||||
|
@ -815,7 +832,15 @@ pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string)
|
|||
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
|
||||
match expr {
|
||||
ast.StringLiteral {
|
||||
str := g.eval_escape_codes(expr)
|
||||
str := g.eval_str_lit_escape_codes(expr)
|
||||
if newline {
|
||||
g.gen_print(str + '\n', fd)
|
||||
} else {
|
||||
g.gen_print(str, fd)
|
||||
}
|
||||
}
|
||||
ast.CharLiteral {
|
||||
str := g.eval_escape_codes(expr.val)
|
||||
if newline {
|
||||
g.gen_print(str + '\n', fd)
|
||||
} else {
|
||||
|
@ -826,7 +851,7 @@ pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string)
|
|||
vo := g.try_var_offset(expr.name)
|
||||
|
||||
if vo != -1 {
|
||||
g.gen_var_to_string(.rax, expr as ast.Ident)
|
||||
g.gen_var_to_string(.rax, expr, expr as ast.Ident)
|
||||
g.gen_print_reg(.rax, -1, fd)
|
||||
if newline {
|
||||
g.gen_print('\n', fd)
|
||||
|
@ -1173,7 +1198,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
if node.exprs.len == 1 {
|
||||
match node.exprs[0] {
|
||||
ast.StringLiteral {
|
||||
s = g.eval_escape_codes(node.exprs[0] as ast.StringLiteral)
|
||||
s = g.eval_str_lit_escape_codes(node.exprs[0] as ast.StringLiteral)
|
||||
g.expr(node.exprs[0])
|
||||
g.mov64(.rax, g.allocate_string(s, 2, .abs64))
|
||||
}
|
||||
|
@ -1383,7 +1408,7 @@ fn (mut g Gen) gen_syscall(node ast.CallExpr) {
|
|||
if expr.field_name == 'str' {
|
||||
match expr.expr {
|
||||
ast.StringLiteral {
|
||||
s := g.eval_escape_codes(expr.expr)
|
||||
s := g.eval_str_lit_escape_codes(expr.expr)
|
||||
g.allocate_string(s, 2, .abs64)
|
||||
g.mov64(ra[i], 1)
|
||||
done = true
|
||||
|
@ -1400,7 +1425,7 @@ fn (mut g Gen) gen_syscall(node ast.CallExpr) {
|
|||
g.warning('C.syscall expects c"string" or "string".str, C backend will crash',
|
||||
node.pos)
|
||||
}
|
||||
s := g.eval_escape_codes(expr)
|
||||
s := g.eval_str_lit_escape_codes(expr)
|
||||
g.allocate_string(s, 2, .abs64)
|
||||
g.mov64(ra[i], 1)
|
||||
}
|
||||
|
@ -1512,9 +1537,21 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.prefix_expr(node)
|
||||
}
|
||||
ast.StringLiteral {
|
||||
str := g.eval_escape_codes(node)
|
||||
str := g.eval_str_lit_escape_codes(node)
|
||||
g.allocate_string(str, 3, .rel32)
|
||||
}
|
||||
ast.CharLiteral {
|
||||
bytes := g.eval_escape_codes(node.val)
|
||||
.bytes()
|
||||
mut val := rune(0)
|
||||
for i, v in bytes {
|
||||
val |= v << (i * 8)
|
||||
if i >= sizeof(rune) {
|
||||
g.n_error('runes are only 4 bytes wide')
|
||||
}
|
||||
}
|
||||
g.movabs(.rax, i64(val))
|
||||
}
|
||||
ast.StructInit {
|
||||
pos := g.allocate_by_type('_anonstruct', node.typ)
|
||||
g.init_struct(LocalVar{ offset: pos, typ: node.typ }, node)
|
||||
|
|
68
vlib/v/gen/native/tests/pointers.vv
Normal file
68
vlib/v/gen/native/tests/pointers.vv
Normal file
|
@ -0,0 +1,68 @@
|
|||
fn main() {
|
||||
test_eq_ne()
|
||||
test_lt_gt()
|
||||
test_ref_deref()
|
||||
println("ok")
|
||||
}
|
||||
|
||||
fn test_eq_ne() {
|
||||
unsafe {
|
||||
mut a := voidptr(0)
|
||||
mut b := voidptr(0)
|
||||
assert a == a
|
||||
assert !(a != a)
|
||||
assert a == b
|
||||
assert !(a != b)
|
||||
|
||||
a = voidptr(0xdeadbeef)
|
||||
assert a != b
|
||||
assert !(a == b)
|
||||
|
||||
b = voidptr(0xdeadbeef)
|
||||
assert a == b
|
||||
assert !(a != b)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_lt_gt() {
|
||||
unsafe {
|
||||
mut a := voidptr(0)
|
||||
mut b := voidptr(1)
|
||||
|
||||
assert !(a < a)
|
||||
assert !(a > a)
|
||||
assert a >= a
|
||||
assert a <= a
|
||||
|
||||
assert a < b
|
||||
assert !(a > b)
|
||||
assert a <= b
|
||||
assert !(a >= b)
|
||||
|
||||
a = voidptr(0x42)
|
||||
assert a > b
|
||||
assert a >= b
|
||||
assert !(a < b)
|
||||
assert !(a <= b)
|
||||
|
||||
b = voidptr(0x42)
|
||||
assert a >= b
|
||||
assert a <= b
|
||||
assert !(a > b)
|
||||
assert !(a < b)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_ref_deref() {
|
||||
mut a := 42
|
||||
b := &a
|
||||
c := &b
|
||||
|
||||
assert *b == 42
|
||||
|
||||
a = 50
|
||||
assert *b == 50
|
||||
|
||||
assert *c == b
|
||||
assert **c == *b
|
||||
}
|
1
vlib/v/gen/native/tests/pointers.vv.out
Normal file
1
vlib/v/gen/native/tests/pointers.vv.out
Normal file
|
@ -0,0 +1 @@
|
|||
ok
|
|
@ -21,8 +21,25 @@ fn test_raw_string() {
|
|||
println(raw)
|
||||
}
|
||||
|
||||
fn test_runes() {
|
||||
mut a := `V`
|
||||
println(a)
|
||||
|
||||
a = `😀`
|
||||
println(a)
|
||||
|
||||
rocket := `🚀`
|
||||
println(rocket)
|
||||
|
||||
// should all print `★`
|
||||
print(`\u2605`)
|
||||
print(`\xe2\x98\x85`)
|
||||
println(`\xe2\x98\x85`)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_unicode_characters()
|
||||
test_escape_codes()
|
||||
test_raw_string()
|
||||
test_runes()
|
||||
}
|
|
@ -4,4 +4,8 @@
|
|||
aaa
|
||||
## #
|
||||
### #
|
||||
hello\tworld\n
|
||||
hello\tworld\n
|
||||
V
|
||||
😀
|
||||
🚀
|
||||
★★★
|
Loading…
Reference in New Issue
Block a user