-
Notifications
You must be signed in to change notification settings - Fork 22
/
compile_arithmetic.rb
85 lines (72 loc) · 1.94 KB
/
compile_arithmetic.rb
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
# Method to compile arithmetic
class Compiler
def compile_2(scope, left, right)
src = compile_eval_arg(scope,left)
@e.with_register_for(src) do |reg|
# @e.emit(:movl, src, reg)
@e.save_result(compile_eval_arg(scope,right))
yield reg
end
Value.new([:subexpr], nil)
end
def compile_shl(scope, left)
src = compile_eval_arg(scope, left)
@e.shl(src)
@e.save_result(src)
Value.new([:subexpr])
end
def compile_sar(scope, left)
src = compile_eval_arg(scope, left)
@e.sar(src)
@e.save_result(src)
Value.new([:subexpr])
end
def compile_add(scope, left, right)
compile_2(scope,left,right) do |reg|
@e.addl(reg, @e.result)
end
end
def compile_sub(scope, left, right)
compile_2(scope,left,right) do |reg|
@e.subl(:eax,reg)
@e.save_result(reg)
end
end
def compile_mul(scope, left, right)
compile_2(scope,left,right) do |reg|
@e.imull(reg,:eax)
end
end
def compile_div(scope, left, right, &block)
@e.pushl(compile_eval_arg(scope,left))
res = compile_eval_arg(scope,right)
# FIXME @bug
# block_given? does not work in nested
# lambdas
bg = block_given?
@e.with_register(:edx) do |dividend|
xdividend = dividend
@e.with_register do |divisor|
# FIXME: @bug
# dividend gets set incorrectly due to a compiler
# bug in handling of nested lambdas, so using xdividend above instead.
@e.movl(res,divisor)
# We need the dividend in %eax *and* sign extended into %edx, so
# it doesn't matter which one of them we pop it into:
@e.popl(@e.result)
@e.movl(@e.result, xdividend)
@e.sarl(31, xdividend)
@e.idivl(divisor)
if bg
block.call
end
end
end
Value.new([:subexpr])
end
def compile_mod(scope, left, right)
compile_div(scope,left,right) do
@e.movl(:edx, @e.result)
end
end
end