forked from zjryan/e8vm
/
int_op.go
99 lines (89 loc) · 1.94 KB
/
int_op.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package g8
import (
"e8vm.io/e8vm/g8/codegen"
"e8vm.io/e8vm/g8/types"
)
func buildBasicArith(b *builder, ret, A, B *ref, op string) {
switch op {
case "/", "%", "u/", "u%":
isZero := b.newCond()
b.b.Arith(isZero, B.IR(), "==", codegen.Num(0))
zeroPanic := b.f.NewBlock(b.b)
after := b.f.NewBlock(zeroPanic)
b.b.JumpIfNot(isZero, after)
b.b = zeroPanic
callPanic(b, "divided by zero")
b.b = after
}
b.b.Arith(ret.IR(), A.IR(), op, B.IR())
}
func binaryOpInt(b *builder, op string, A, B *ref, t types.T) *ref {
switch op {
case "+", "-", "*", "&", "|", "^", "%", "/":
ret := b.newTemp(t)
buildBasicArith(b, ret, A, B, op)
return ret
case "==", "!=", ">", "<", ">=", "<=":
ret := b.newTemp(types.Bool)
b.b.Arith(ret.IR(), A.IR(), op, B.IR())
return ret
}
panic("bug")
}
func binaryOpUint(b *builder, op string, A, B *ref, t types.T) *ref {
switch op {
case "+", "-", "&", "|", "^":
ret := b.newTemp(t)
buildBasicArith(b, ret, A, B, op)
return ret
case "*", "%", "/":
ret := b.newTemp(t)
buildBasicArith(b, ret, A, B, "u"+op)
return ret
case "==", "!=":
ret := b.newTemp(types.Bool)
b.b.Arith(ret.IR(), A.IR(), op, B.IR())
return ret
case ">", "<", ">=", "<=":
ret := b.newTemp(types.Bool)
b.b.Arith(ret.IR(), A.IR(), "u"+op, B.IR())
return ret
}
panic("bug")
}
func binaryOpConst(b *builder, op string, A, B *ref) *ref {
va, _ := types.NumConst(A.Type())
vb, _ := types.NumConst(B.Type())
br := func(b bool) *ref {
if b {
return refTrue
}
return refFalse
}
switch op {
case "==":
return br(va == vb)
case "!=":
return br(va != vb)
case ">":
return br(va > vb)
case "<":
return br(va < vb)
case ">=":
return br(va >= vb)
case "<=":
return br(va <= vb)
}
panic("bug")
}
func unaryOpInt(b *builder, op string, B *ref) *ref {
switch op {
case "+":
return B
case "-", "^":
ret := b.newTemp(B.Type())
b.b.Arith(ret.IR(), nil, op, B.IR())
return ret
}
panic("bug")
}