mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: support integer infix arithmetics (#15536)
This commit is contained in:
parent
dbf28c5bfb
commit
939e9245db
@ -850,6 +850,57 @@ fn (mut g Gen) mul8_var(reg Register, var_offset int) {
|
||||
g.println('mul8 $reg,DWORD PTR[rbp-$var_offset.hex2()]')
|
||||
}
|
||||
|
||||
fn (mut g Gen) bitand_reg(a Register, b Register) {
|
||||
g.write8(0x48 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
|
||||
if int(b) >= int(Register.r8) { 4 } else { 0 })
|
||||
g.write8(0x21)
|
||||
g.write8(0xc0 + int(a) % 8 + int(b) % 8 * 8)
|
||||
}
|
||||
|
||||
fn (mut g Gen) bitor_reg(a Register, b Register) {
|
||||
g.write8(0x48 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
|
||||
if int(b) >= int(Register.r8) { 4 } else { 0 })
|
||||
g.write8(0x09)
|
||||
g.write8(0xc0 + int(a) % 8 + int(b) % 8 * 8)
|
||||
}
|
||||
|
||||
fn (mut g Gen) bitxor_reg(a Register, b Register) {
|
||||
g.write8(0x48 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
|
||||
if int(b) >= int(Register.r8) { 4 } else { 0 })
|
||||
g.write8(0x31)
|
||||
g.write8(0xc0 + int(a) % 8 + int(b) % 8 * 8)
|
||||
}
|
||||
|
||||
fn (mut g Gen) shl_reg(a Register, b Register) {
|
||||
if b != .rcx {
|
||||
g.mov_reg(.rcx, b)
|
||||
}
|
||||
g.write8(if int(a) >= int(Register.r8) { 0x49 } else { 0x48 })
|
||||
g.write8(0xd3)
|
||||
g.write8(0xe0 + int(a) % 8)
|
||||
g.println('shl $a, $b')
|
||||
}
|
||||
|
||||
fn (mut g Gen) sar_reg(a Register, b Register) {
|
||||
if b != .rcx {
|
||||
g.mov_reg(.rcx, b)
|
||||
}
|
||||
g.write8(if int(a) > 7 { 0x49 } else { 0x48 })
|
||||
g.write8(0xd3)
|
||||
g.write8(0xf8 + int(a) % 8)
|
||||
g.println('sar $a, $b')
|
||||
}
|
||||
|
||||
fn (mut g Gen) shr_reg(a Register, b Register) {
|
||||
if b != .rcx {
|
||||
g.mov_reg(.rcx, b)
|
||||
}
|
||||
g.write8(if int(a) > 7 { 0x49 } else { 0x48 })
|
||||
g.write8(0xd3)
|
||||
g.write8(0xe8 + int(a) % 8)
|
||||
g.println('shr $a, $b')
|
||||
}
|
||||
|
||||
fn (mut g Gen) leave() {
|
||||
g.println('; label 0: return')
|
||||
if g.defer_stmts.len != 0 {
|
||||
@ -1332,39 +1383,25 @@ fn (mut g Gen) mod_reg(a Register, b Register) {
|
||||
}
|
||||
|
||||
fn (mut g Gen) sub_reg(a Register, b Register) {
|
||||
if a == .rax && b == .rbx {
|
||||
g.write8(0x48)
|
||||
if int(a) <= int(Register.r15) && int(b) <= int(Register.r15) {
|
||||
g.write8(0x48 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
|
||||
if int(b) >= int(Register.r8) { 4 } else { 0 })
|
||||
g.write8(0x29)
|
||||
g.write8(0xd8)
|
||||
} else if a == .rdx && b == .rax {
|
||||
g.write8(0x48)
|
||||
g.write8(0x29)
|
||||
g.write8(0xc2)
|
||||
} else if a == .rdi && b == .rax {
|
||||
g.write8(0x48)
|
||||
g.write8(0x29)
|
||||
g.write8(0xc7)
|
||||
g.write8(0xc0 + int(a) % 8 + int(b) % 8 * 8)
|
||||
} else {
|
||||
panic('unhandled add $a, $b')
|
||||
g.n_error('unhandled sub $a, $b')
|
||||
}
|
||||
g.println('sub $a, $b')
|
||||
}
|
||||
|
||||
fn (mut g Gen) add_reg(a Register, b Register) {
|
||||
if a == .rax && b == .rbx {
|
||||
g.write8(0x48)
|
||||
if int(a) <= int(Register.r15) && int(b) <= int(Register.r15) {
|
||||
g.write8(0x48 + if int(a) >= int(Register.r8) { 1 } else { 0 } +
|
||||
if int(b) >= int(Register.r8) { 4 } else { 0 })
|
||||
g.write8(0x01)
|
||||
g.write8(0xd8)
|
||||
} else if a == .rax && b == .rdi {
|
||||
g.write8(0x48)
|
||||
g.write8(0x01)
|
||||
g.write8(0xf8)
|
||||
} else if a == .rax && b == .rax {
|
||||
g.write8(0x48)
|
||||
g.write8(0x01)
|
||||
g.write8(0xc0)
|
||||
g.write8(0xc0 + int(a) % 8 + int(b) % 8 * 8)
|
||||
} else {
|
||||
panic('unhandled add $a, $b')
|
||||
g.n_error('unhandled add $a, $b')
|
||||
}
|
||||
g.println('add $a, $b')
|
||||
}
|
||||
@ -1741,6 +1778,7 @@ fn (mut g Gen) cset_op(op token.Kind) {
|
||||
}
|
||||
|
||||
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
/*
|
||||
if node.left is ast.Ident && node.right is ast.Ident {
|
||||
left := node.left as ast.Ident
|
||||
right := node.right as ast.Ident
|
||||
@ -1756,33 +1794,109 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
g.expr(node.left)
|
||||
mut label := 0
|
||||
g.push(.rax)
|
||||
}*/
|
||||
if node.op in [.logical_or, .and] {
|
||||
label = g.labels.new_label()
|
||||
g.expr(node.left)
|
||||
label := g.labels.new_label()
|
||||
g.cmp_zero(.rax)
|
||||
jump_addr := g.cjmp(if node.op == .logical_or { .jne } else { .je })
|
||||
g.labels.patches << LabelPatch{
|
||||
id: label
|
||||
pos: jump_addr
|
||||
}
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.pop(.rdx)
|
||||
// left: rdx, right: rax
|
||||
match node.op {
|
||||
.logical_or, .and {
|
||||
g.labels.addrs[label] = g.pos()
|
||||
g.expr(node.right)
|
||||
g.labels.addrs[label] = g.pos()
|
||||
return
|
||||
} else {
|
||||
g.expr(node.right)
|
||||
// optimize for ast.Ident
|
||||
match node.left {
|
||||
ast.Ident {
|
||||
g.mov_reg(match node.op {
|
||||
.left_shift, .right_shift, .unsigned_right_shift, .div, .mod { .rcx }
|
||||
else { .rdx }
|
||||
}, .rax)
|
||||
g.mov_var_to_reg(.rax, node.left as ast.Ident)
|
||||
}
|
||||
else {
|
||||
g.push(.rax)
|
||||
g.expr(node.left)
|
||||
g.pop(match node.op {
|
||||
.left_shift, .right_shift, .unsigned_right_shift, .div, .mod { .rcx }
|
||||
else { .rdx }
|
||||
})
|
||||
}
|
||||
}
|
||||
.eq, .ne, .gt, .lt, .ge, .le {
|
||||
g.cmp_reg(.rdx, .rax)
|
||||
g.mov64(.rax, 0)
|
||||
g.cset_op(node.op)
|
||||
if node.left_type !in ast.integer_type_idxs && node.left_type != ast.bool_type_idx {
|
||||
g.n_error('unsupported type for `$node.op`: $node.left_type')
|
||||
}
|
||||
else {
|
||||
g.n_error('`$node.op` expression is not supported right now')
|
||||
// left: rax, right: rdx
|
||||
match node.op {
|
||||
.eq, .ne, .gt, .lt, .ge, .le {
|
||||
g.cmp_reg(.rax, .rdx)
|
||||
g.mov64(.rax, 0)
|
||||
g.cset_op(node.op)
|
||||
}
|
||||
.plus {
|
||||
g.add_reg(.rax, .rdx)
|
||||
}
|
||||
.minus {
|
||||
g.sub_reg(.rax, .rdx)
|
||||
}
|
||||
.mul {
|
||||
g.write32(0xc2af0f48)
|
||||
g.println('imul rax, rdx')
|
||||
}
|
||||
.div {
|
||||
if node.left_type in ast.unsigned_integer_type_idxs {
|
||||
g.write8(0xba)
|
||||
g.write32(0)
|
||||
g.println('mov edx, 0')
|
||||
g.write([u8(0x48), 0xf7, 0xf1])
|
||||
g.println('div rcx')
|
||||
} else {
|
||||
g.write16(0x9948)
|
||||
g.println('cqo')
|
||||
g.write([u8(0x48), 0xf7, 0xf9])
|
||||
g.println('idiv rcx')
|
||||
}
|
||||
}
|
||||
.mod {
|
||||
if node.left_type in ast.unsigned_integer_type_idxs {
|
||||
g.write8(0xba)
|
||||
g.write32(0)
|
||||
g.println('mov edx, 0')
|
||||
g.write([u8(0x48), 0xf7, 0xf1])
|
||||
g.println('div rcx')
|
||||
} else {
|
||||
g.write16(0x9948)
|
||||
g.println('cqo')
|
||||
g.write([u8(0x48), 0xf7, 0xf9])
|
||||
g.println('idiv rcx')
|
||||
}
|
||||
g.mov_reg(.rax, .rdx)
|
||||
}
|
||||
.amp {
|
||||
g.bitand_reg(.rax, .rdx)
|
||||
}
|
||||
.pipe {
|
||||
g.bitor_reg(.rax, .rdx)
|
||||
}
|
||||
.xor {
|
||||
g.bitxor_reg(.rax, .rdx)
|
||||
}
|
||||
.left_shift {
|
||||
g.shl_reg(.rax, .rcx)
|
||||
}
|
||||
.right_shift {
|
||||
g.sar_reg(.rax, .rcx)
|
||||
}
|
||||
.unsigned_right_shift {
|
||||
g.shr_reg(.rax, .rcx)
|
||||
}
|
||||
else {
|
||||
g.n_error('`$node.op` expression is not supported right now')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,17 +44,39 @@ fn test_add() {
|
||||
y := 3
|
||||
sum := x + y
|
||||
product := x * y
|
||||
// diff := y - x
|
||||
diff := y - x
|
||||
div := y / x
|
||||
mod := y % x
|
||||
bitand := x & y
|
||||
bitor := x | y
|
||||
bitxor := x ^ y
|
||||
lshift := x << x
|
||||
rshift := 12 >> x
|
||||
print_number(x)
|
||||
print_number(y)
|
||||
print_number(sum)
|
||||
print_number(product)
|
||||
// XXX fails on linux-amd64 but works on macos-amd64
|
||||
// print_number(diff)
|
||||
print_number(diff)
|
||||
print_number(div)
|
||||
print_number(mod)
|
||||
print_number(bitand)
|
||||
print_number(bitor)
|
||||
print_number(bitxor)
|
||||
print_number(lshift)
|
||||
print_number(rshift)
|
||||
}
|
||||
|
||||
fn test_multiple() {
|
||||
a := 3
|
||||
b := 5
|
||||
c := 2
|
||||
result := (a * ((a & b) + c) << (b ^ a)) | a - b % (b / c)
|
||||
println(result)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('start')
|
||||
test_add()
|
||||
test_multiple()
|
||||
println('end')
|
||||
}
|
||||
|
@ -4,5 +4,14 @@ test_add()
|
||||
3
|
||||
5
|
||||
6
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
1
|
||||
8
|
||||
3
|
||||
578
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user