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:
parent
d694a26f39
commit
d78dfabfe0
@ -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)
|
||||
|
@ -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])
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user