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

native: support casting integer to/from enum values (#15928)

This commit is contained in:
lemon 2022-09-30 21:53:17 +09:00 committed by GitHub
parent d694a26f39
commit d78dfabfe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 19 deletions

View File

@ -807,6 +807,35 @@ fn (mut g Gen) mov_var_to_reg(reg Register, var Var, config VarConfig) {
}
}
fn (mut g Gen) mov_extend_reg(a Register, b Register, typ ast.Type) {
size := g.get_type_size(typ)
is_signed := !typ.is_real_pointer() && typ.is_signed()
if size in [1, 2, 4] {
if size == 4 && !is_signed {
g.write8(0x40 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
if int(b) >= int(Register.r8) { 4 } else { 0 })
g.write8(0x89)
} else {
g.write8(0x48 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
if int(b) >= int(Register.r8) { 4 } else { 0 })
if size in [1, 2] {
g.write8(0x0f)
}
g.write8(match true {
size == 1 && is_signed { 0xbe }
size == 1 && !is_signed { 0xb6 }
size == 2 && is_signed { 0xbf }
size == 2 && !is_signed { 0xb7 }
else { 0x63 }
})
}
g.write8(0xc0 + int(a) % 8 * 8 + int(b) % 8)
instruction := if is_signed { 's' } else { 'z' }
g.println('mov${instruction}x $a, $b')
}
}
fn (mut g Gen) call_addr_at(addr int, at i64) i64 {
// Need to calculate the difference between current position (position after the e8 call)
// and the function to call.
@ -2135,20 +2164,6 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
ast.GoExpr {
g.v_error('threads not implemented for the native backend', node.pos)
}
ast.CastExpr {
g.warning('cast expressions are work in progress', right.pos)
match right.typname {
'u64' {
g.allocate_var(name, 8, right.expr.str().int())
}
'int' {
g.allocate_var(name, 4, right.expr.str().int())
}
else {
g.v_error('unsupported cast type $right.typ', node.pos)
}
}
}
ast.FloatLiteral {
g.v_error('floating point arithmetic not yet implemented for the native backend',
node.pos)

View File

@ -1086,10 +1086,6 @@ fn (mut g Gen) stmt(node ast.Stmt) {
mut s := '?' //${node.exprs[0].val.str()}'
if e0 := node.exprs[0] {
match e0 {
ast.CastExpr {
g.mov64(.rax, e0.expr.str().int())
// do the job
}
ast.StringLiteral {
s = g.eval_escape_codes(e0)
g.expr(node.exprs[0])
@ -1326,6 +1322,10 @@ fn (mut g Gen) expr(node ast.Expr) {
g.add(.rax, offset)
g.mov_deref(.rax, .rax, node.typ)
}
ast.CastExpr {
g.expr(node.expr)
g.mov_extend_reg(.rax, .rax, node.typ)
}
ast.EnumVal {
type_name := g.table.get_type_name(node.typ)
g.mov(.rax, g.enum_vals[type_name].fields[node.val])

View File

@ -47,5 +47,30 @@ fn test_enum_variant_and_method_name_clash() {
x.baz()
}
fn main() {
enum Value {
a
b
c = 5 * 3
d
e = 3
}
fn value_test() {
assert int(Value.a) == 0
assert int(Value.b) == 1
assert int(Value.c) == 15
assert int(Value.d) == 16
assert int(Value.e) == 3
assert Value.a == Value(0)
assert Value.b == Value(1)
assert Value.c == Value(15)
assert Value.d == Value(16)
assert Value.e == Value(3)
}
fn main() {
enum_test()
match_test()
test_enum_variant_and_method_name_clash()
value_test()
}

View File

@ -3,6 +3,8 @@ fn cast_test() {
assert a == 1
b := u64(2)
assert b == 2
c := int(u8(i64(u64(i16(4)))))
assert c == 4
}
fn if_test() {