oryx 0.3.1 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -0
- data/doc/cflat.md +2 -0
- data/doc/fibonacci.md +253 -3
- data/doc/img/cfgfib.jpg +0 -0
- data/doc/img/cfgmain.jpg +0 -0
- data/doc/intro.md +3 -2
- data/lib/oryx/ast.rb +17 -1
- data/lib/oryx/contractor.rb +70 -11
- data/lib/oryx/options.rb +9 -3
- data/lib/oryx/parser.rb +6 -2
- data/lib/oryx/runner.rb +64 -15
- data/lib/oryx/version.rb +1 -1
- data/test/data/and.c +14 -0
- data/test/data/and2.c +14 -0
- data/test/data/fun_2.c +9 -0
- data/test/data/fun_3.c +11 -0
- data/test/data/fun_4.c +9 -0
- data/test/data/gvar_1.c +2 -1
- data/test/data/if.c +1 -1
- data/test/data/if_2.c +15 -0
- data/test/data/if_3.c +20 -0
- data/test/data/if_4.c +20 -0
- data/test/data/long.c +30 -0
- data/test/data/mut.c +9 -0
- data/test/data/neg.c +3 -0
- data/test/data/neg2.c +5 -0
- data/test/data/neg3.c +6 -0
- data/test/data/neg4.c +5 -0
- data/test/data/or.c +10 -0
- data/test/data/or2.c +10 -0
- data/test/lib/oryx/runner_test.rb +20 -4
- data/test/shoulda_macros/runner.rb +7 -10
- metadata +38 -4
data/README.md
CHANGED
@@ -16,6 +16,14 @@ C-Flat to x86 compiler.
|
|
16
16
|
+ Oryx 0.3.1
|
17
17
|
+ Abstract Syntax Tree defined and generated
|
18
18
|
+ Fixed Travis errors by pre-compiling LLVM shared library
|
19
|
+
- 8 May 13
|
20
|
+
+ Oryx 0.3.7
|
21
|
+
+ Added mutable values
|
22
|
+
+ Introduced negation of integers
|
23
|
+
+ `and` and `or` code generation
|
24
|
+
+ Improved UX
|
25
|
+
+ Debug mode
|
26
|
+
|
19
27
|
|
20
28
|
## C-Flat
|
21
29
|
C-Flat is a working subset of C designed for use in compilers courses. C-flat includes expressions, basic control flow, recursive functions, and strict type checking. It is object-compatible with ordinary C and thus can take advantage of the standard C library, at least when using limited types.
|
data/doc/cflat.md
CHANGED
@@ -7,6 +7,7 @@ C-Flat is a working subset of C designed for use in compilers courses. C-Flat in
|
|
7
7
|
- `boolean`
|
8
8
|
- `char`
|
9
9
|
- `else`
|
10
|
+
- `false`
|
10
11
|
- `if`
|
11
12
|
- `int`
|
12
13
|
- `print`
|
@@ -29,6 +30,7 @@ C-Flat ignores whitespace (beyond separating identifiers).
|
|
29
30
|
C-Flat includes many of the arithmetic operators found in C. Here they are enumerated with precedence.
|
30
31
|
|
31
32
|
( ) grouping ^ (highest precedence)
|
33
|
+
- negation |
|
32
34
|
* / multiplication |
|
33
35
|
+ - addition |
|
34
36
|
< <= >= == != comparison |
|
data/doc/fibonacci.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# Fibonacci Example
|
1
|
+
# Recursive Fibonacci Example
|
2
2
|
|
3
|
-
Source Code (`test/data/fib.c`)
|
3
|
+
## Source Code (`test/data/fib.c`)
|
4
4
|
|
5
5
|
int fib(int x) {
|
6
6
|
if (x < 2) return 1;
|
@@ -11,5 +11,255 @@ Source Code (`test/data/fib.c`)
|
|
11
11
|
return fib(5);
|
12
12
|
}
|
13
13
|
|
14
|
-
|
14
|
+
## Command
|
15
|
+
|
16
|
+
oryx -v fib.c -o fib.out
|
17
|
+
|
18
|
+
## Tokens
|
19
|
+
File: `fib.lex`
|
20
|
+
|
21
|
+
TYPE | VALUE | POSITION
|
22
|
+
-----------------------------------
|
23
|
+
INT 1,0
|
24
|
+
IDENT fib 1,4
|
25
|
+
LPAREN 1,7
|
26
|
+
INT 1,8
|
27
|
+
IDENT x 1,12
|
28
|
+
RPAREN 1,13
|
29
|
+
LCURLY 1,15
|
30
|
+
IF 2,2
|
31
|
+
LPAREN 2,5
|
32
|
+
IDENT x 2,6
|
33
|
+
LE 2,8
|
34
|
+
NUM 2 2,10
|
35
|
+
RPAREN 2,11
|
36
|
+
RETURN 2,13
|
37
|
+
NUM 1 2,20
|
38
|
+
SEMI 2,21
|
39
|
+
ELSE 3,2
|
40
|
+
RETURN 3,7
|
41
|
+
IDENT fib 3,14
|
42
|
+
LPAREN 3,17
|
43
|
+
IDENT x 3,18
|
44
|
+
MINUS 3,19
|
45
|
+
NUM 1 3,20
|
46
|
+
RPAREN 3,21
|
47
|
+
PLUS 3,22
|
48
|
+
IDENT fib 3,23
|
49
|
+
LPAREN 3,26
|
50
|
+
IDENT x 3,27
|
51
|
+
MINUS 3,28
|
52
|
+
NUM 2 3,29
|
53
|
+
RPAREN 3,30
|
54
|
+
SEMI 3,31
|
55
|
+
RCURLY 4,0
|
56
|
+
INT 6,0
|
57
|
+
IDENT main 6,4
|
58
|
+
LPAREN 6,8
|
59
|
+
RPAREN 6,9
|
60
|
+
LCURLY 6,11
|
61
|
+
RETURN 7,2
|
62
|
+
IDENT fib 7,9
|
63
|
+
LPAREN 7,12
|
64
|
+
NUM 8 7,13
|
65
|
+
RPAREN 7,14
|
66
|
+
SEMI 7,15
|
67
|
+
RCURLY 8,0
|
68
|
+
EOS
|
69
|
+
|
70
|
+
## Parse Tree
|
71
|
+
Files: `fib.dot`, `fib.jpg`
|
72
|
+
|
73
|
+
Command: `dot -Tjpeg fib.dot -o fib.jpg`
|
74
|
+
|
15
75
|
![Parse Tree](img/fib_parse.jpg)
|
76
|
+
|
77
|
+
## LLVM IR
|
78
|
+
![main function](img/cfgmain.jpg)
|
79
|
+
![fib function](img/cfgfib.jpg)
|
80
|
+
|
81
|
+
File: `fib.ll`
|
82
|
+
|
83
|
+
; ModuleID = 'Oryx JIT'
|
84
|
+
|
85
|
+
define i32 @fib(i32 %x) {
|
86
|
+
entry:
|
87
|
+
%x1 = alloca i32
|
88
|
+
store i32 %x, i32* %x1
|
89
|
+
br label %code_block
|
90
|
+
|
91
|
+
code_block: ; preds = %entry
|
92
|
+
%x2 = load i32* %x1
|
93
|
+
%0 = icmp slt i32 %x2, 2
|
94
|
+
%booltmp = sext i1 %0 to i32
|
95
|
+
%ifcond = icmp ne i32 %booltmp, 0
|
96
|
+
br i1 %ifcond, label %then, label %else
|
97
|
+
|
98
|
+
then: ; preds = %code_block
|
99
|
+
br label %merge
|
100
|
+
|
101
|
+
else: ; preds = %code_block
|
102
|
+
%x3 = load i32* %x1
|
103
|
+
%subtmp = sub i32 %x3, 1
|
104
|
+
%calltmp = call i32 @fib(i32 %subtmp)
|
105
|
+
%x4 = load i32* %x1
|
106
|
+
%subtmp5 = sub i32 %x4, 2
|
107
|
+
%calltmp6 = call i32 @fib(i32 %subtmp5)
|
108
|
+
%addtmp = add i32 %calltmp, %calltmp6
|
109
|
+
br label %merge
|
110
|
+
|
111
|
+
merge: ; preds = %else, %then
|
112
|
+
%iftmp = phi i32 [ 1, %then ], [ %addtmp, %else ]
|
113
|
+
br label %phi_bb
|
114
|
+
|
115
|
+
phi_bb: ; preds = %merge
|
116
|
+
%iftmp7 = phi i32 [ %iftmp, %merge ]
|
117
|
+
ret i32 %iftmp7
|
118
|
+
}
|
119
|
+
|
120
|
+
define i32 @main() {
|
121
|
+
entry:
|
122
|
+
br label %code_block
|
123
|
+
|
124
|
+
code_block: ; preds = %entry
|
125
|
+
%calltmp = call i32 @fib(i32 8)
|
126
|
+
br label %phi_bb
|
127
|
+
|
128
|
+
phi_bb: ; preds = %code_block
|
129
|
+
%iftmp = phi i32 [ %calltmp, %code_block ]
|
130
|
+
ret i32 %iftmp
|
131
|
+
}
|
132
|
+
|
133
|
+
## x86
|
134
|
+
File: `fib.s`
|
135
|
+
|
136
|
+
.section __TEXT,__text,regular,pure_instructions
|
137
|
+
.globl _fib
|
138
|
+
.align 4, 0x90
|
139
|
+
_fib: ## @fib
|
140
|
+
Ltmp2:
|
141
|
+
## BB#0: ## %entry
|
142
|
+
pushq %rbx
|
143
|
+
Ltmp3:
|
144
|
+
subq $16, %rsp
|
145
|
+
Ltmp4:
|
146
|
+
Ltmp5:
|
147
|
+
movl %edi, 12(%rsp)
|
148
|
+
movl $-1, %eax
|
149
|
+
cmpl $2, 12(%rsp)
|
150
|
+
movl $0, %ecx
|
151
|
+
cmovll %eax, %ecx
|
152
|
+
movl $1, %eax
|
153
|
+
testl %ecx, %ecx
|
154
|
+
jne LBB0_2
|
155
|
+
## BB#1: ## %else
|
156
|
+
movl 12(%rsp), %edi
|
157
|
+
decl %edi
|
158
|
+
callq _fib
|
159
|
+
movl %eax, %ebx
|
160
|
+
movl 12(%rsp), %edi
|
161
|
+
addl $-2, %edi
|
162
|
+
callq _fib
|
163
|
+
addl %ebx, %eax
|
164
|
+
LBB0_2: ## %phi_bb
|
165
|
+
addq $16, %rsp
|
166
|
+
popq %rbx
|
167
|
+
ret
|
168
|
+
Ltmp6:
|
169
|
+
Leh_func_end0:
|
170
|
+
|
171
|
+
.globl _main
|
172
|
+
.align 4, 0x90
|
173
|
+
_main: ## @main
|
174
|
+
Ltmp8:
|
175
|
+
## BB#0: ## %entry
|
176
|
+
pushq %rax
|
177
|
+
Ltmp9:
|
178
|
+
movl $8, %edi
|
179
|
+
callq _fib
|
180
|
+
popq %rdx
|
181
|
+
ret
|
182
|
+
Ltmp10:
|
183
|
+
Leh_func_end1:
|
184
|
+
|
185
|
+
|
186
|
+
.subsections_via_symbols
|
187
|
+
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
188
|
+
Ltmp11:
|
189
|
+
EH_frame0:
|
190
|
+
Ltmp13 = (Ltmp12-EH_frame0)-4 ## CIE Length
|
191
|
+
.long Ltmp13
|
192
|
+
.long 0 ## CIE ID Tag
|
193
|
+
.byte 1 ## DW_CIE_VERSION
|
194
|
+
.ascii "zR" ## CIE Augmentation
|
195
|
+
.byte 0
|
196
|
+
.byte 1 ## CIE Code Alignment Factor
|
197
|
+
.byte 120 ## CIE Data Alignment Factor
|
198
|
+
.byte 16 ## CIE Return Address Column
|
199
|
+
.byte 1 ## Augmentation Size
|
200
|
+
.byte 16 ## FDE Encoding = indirect pcrel sdata8
|
201
|
+
.byte 12 ## DW_CFA_def_cfa
|
202
|
+
.byte 7 ## Reg 7
|
203
|
+
.byte 8 ## Offset 8
|
204
|
+
.byte 144 ## DW_CFA_offset + Reg(16)
|
205
|
+
.byte 1 ## Offset 1
|
206
|
+
.align 2
|
207
|
+
Ltmp12:
|
208
|
+
.globl _fib.eh
|
209
|
+
_fib.eh:
|
210
|
+
Ltmp16 = (Ltmp15-Ltmp14)-0 ## FDE Length
|
211
|
+
.long Ltmp16
|
212
|
+
Ltmp14:
|
213
|
+
Ltmp17 = (Ltmp14-EH_frame0)-0 ## FDE CIE Offset
|
214
|
+
.long Ltmp17
|
215
|
+
Ltmp18:
|
216
|
+
Ltmp19 = Ltmp2-Ltmp18 ## FDE initial location
|
217
|
+
.quad Ltmp19
|
218
|
+
Ltmp20 = (Ltmp6-Ltmp2)-0 ## FDE address range
|
219
|
+
.quad Ltmp20
|
220
|
+
.byte 0 ## Augmentation size
|
221
|
+
.byte 4 ## DW_CFA_advance_loc4
|
222
|
+
Ltmp21 = Ltmp3-Ltmp2
|
223
|
+
.long Ltmp21
|
224
|
+
.byte 14 ## DW_CFA_def_cfa_offset
|
225
|
+
.byte 16 ## Offset 16
|
226
|
+
.byte 4 ## DW_CFA_advance_loc4
|
227
|
+
Ltmp22 = Ltmp4-Ltmp3
|
228
|
+
.long Ltmp22
|
229
|
+
.byte 14 ## DW_CFA_def_cfa_offset
|
230
|
+
.byte 32 ## Offset 32
|
231
|
+
.byte 4 ## DW_CFA_advance_loc4
|
232
|
+
Ltmp23 = Ltmp5-Ltmp4
|
233
|
+
.long Ltmp23
|
234
|
+
.byte 131 ## DW_CFA_offset + Reg(3)
|
235
|
+
.byte 2 ## Offset 2
|
236
|
+
.align 3
|
237
|
+
Ltmp15:
|
238
|
+
.globl _main.eh
|
239
|
+
_main.eh:
|
240
|
+
Ltmp26 = (Ltmp25-Ltmp24)-0 ## FDE Length
|
241
|
+
.long Ltmp26
|
242
|
+
Ltmp24:
|
243
|
+
Ltmp27 = (Ltmp24-EH_frame0)-0 ## FDE CIE Offset
|
244
|
+
.long Ltmp27
|
245
|
+
Ltmp28:
|
246
|
+
Ltmp29 = Ltmp8-Ltmp28 ## FDE initial location
|
247
|
+
.quad Ltmp29
|
248
|
+
Ltmp30 = (Ltmp10-Ltmp8)-0 ## FDE address range
|
249
|
+
.quad Ltmp30
|
250
|
+
.byte 0 ## Augmentation size
|
251
|
+
.byte 4 ## DW_CFA_advance_loc4
|
252
|
+
Ltmp31 = Ltmp9-Ltmp8
|
253
|
+
.long Ltmp31
|
254
|
+
.byte 14 ## DW_CFA_def_cfa_offset
|
255
|
+
.byte 16 ## Offset 16
|
256
|
+
.align 3
|
257
|
+
.align 3
|
258
|
+
Ltmp25:
|
259
|
+
|
260
|
+
## Return Value
|
261
|
+
|
262
|
+
$ echo $?
|
263
|
+
34
|
264
|
+
|
265
|
+
|
data/doc/img/cfgfib.jpg
ADDED
Binary file
|
data/doc/img/cfgmain.jpg
ADDED
Binary file
|
data/doc/intro.md
CHANGED
@@ -7,8 +7,9 @@
|
|
7
7
|
- Produce tokens from source code (Oryx 0.1.1)
|
8
8
|
- Create parse tree from token stream (Oryx 0.2.1)
|
9
9
|
- Symbol Table working (Oryx 0.2.7)
|
10
|
-
- Translate parse tree into AST (Oryx
|
11
|
-
- Emit LLVM intermediate code by walking AST (Oryx
|
10
|
+
- Translate parse tree into AST (Oryx 0.3.1)
|
11
|
+
- Emit LLVM intermediate code by walking AST (Oryx 0.3.7)
|
12
|
+
- Loops and Printing (Oryx ?.?.?)
|
12
13
|
- Implement Semantic Analysis (Oryx ?.?.?)
|
13
14
|
- Use LLVM optimizations (Oryx ?.?.?)
|
14
15
|
- Improved error handling (Oryx ?.?.?)
|
data/lib/oryx/ast.rb
CHANGED
@@ -7,6 +7,14 @@ module Oryx
|
|
7
7
|
value :value, Integer
|
8
8
|
end
|
9
9
|
|
10
|
+
class Cstring < Expression
|
11
|
+
value :value, String
|
12
|
+
end
|
13
|
+
|
14
|
+
class BoolConst < Expression
|
15
|
+
value :value, Symbol
|
16
|
+
end
|
17
|
+
|
10
18
|
class Type < Expression
|
11
19
|
value :t, String
|
12
20
|
end
|
@@ -21,6 +29,12 @@ module Oryx
|
|
21
29
|
child :right, Expression
|
22
30
|
end
|
23
31
|
|
32
|
+
class Uniary < Expression
|
33
|
+
child :right, Expression
|
34
|
+
end
|
35
|
+
|
36
|
+
class Neg < Uniary; end
|
37
|
+
|
24
38
|
class Initialization < Expression
|
25
39
|
value :name, String
|
26
40
|
child :right, Expression
|
@@ -63,8 +77,10 @@ module Oryx
|
|
63
77
|
class GEQ < Binary; end
|
64
78
|
class LE < Binary; end
|
65
79
|
class LEQ < Binary; end
|
66
|
-
class EQ
|
80
|
+
class EQ < Binary; end
|
67
81
|
class NEQ < Binary; end
|
82
|
+
class And < Binary; end
|
83
|
+
class Or < Binary; end
|
68
84
|
|
69
85
|
class Return < Expression
|
70
86
|
child :right, Expression
|
data/lib/oryx/contractor.rb
CHANGED
@@ -17,6 +17,7 @@ module Oryx
|
|
17
17
|
super
|
18
18
|
@module = RLTK::CG::Module.new('Oryx JIT')
|
19
19
|
@st = SymbolTable.new
|
20
|
+
@branch_needed = true
|
20
21
|
end
|
21
22
|
|
22
23
|
def begin ast
|
@@ -32,14 +33,19 @@ module Oryx
|
|
32
33
|
param_types = parameter_types node.params
|
33
34
|
return_type = visit node.return_type
|
34
35
|
fun = @module.functions.add(node.i, return_type, param_types)
|
35
|
-
node.params.params.each {|p| visit p}
|
36
36
|
param_names = parameter_names node.params
|
37
37
|
param_names.each_with_index do |name, i|
|
38
|
-
|
38
|
+
fun.params[i].name = name
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
42
|
-
|
41
|
+
build(fun.blocks.append('entry')) do
|
42
|
+
fun.params.each do |param|
|
43
|
+
loc = alloca RLTK::CG::NativeIntType, param.name
|
44
|
+
st.insert param.name, loc
|
45
|
+
store param, loc
|
46
|
+
end
|
47
|
+
ret ( visit node.body )
|
48
|
+
end
|
43
49
|
st.exit_scope
|
44
50
|
|
45
51
|
returning(fun) { fun.verify }
|
@@ -54,15 +60,35 @@ module Oryx
|
|
54
60
|
|
55
61
|
on Variable do |node|
|
56
62
|
begin
|
57
|
-
|
63
|
+
self.load (st.lookup node.name.to_sym), node.name
|
58
64
|
rescue SymbolTableError => e
|
59
65
|
STDERR.puts e.message, "Attempting to continue without this value."
|
60
66
|
end
|
61
67
|
end
|
62
68
|
|
63
69
|
on CodeBlock do |node|
|
64
|
-
|
65
|
-
|
70
|
+
st.enter_scope
|
71
|
+
start = current_block
|
72
|
+
fun = start.parent
|
73
|
+
b = fun.blocks.append('code_block')
|
74
|
+
value = ''
|
75
|
+
next_b = [b]
|
76
|
+
node.statements.each_with_index do |s, i|
|
77
|
+
value, new_b = visit s, at: next_b.last, rcb: true
|
78
|
+
if new_b != b
|
79
|
+
build(next_b.last) { br new_b} if @branch_needed and i != node.statements.count-1
|
80
|
+
@branch_needed = true
|
81
|
+
next_b << new_b
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
phi_bb = fun.blocks.append('phi_bb', self)
|
87
|
+
phi_inst = build(phi_bb) { phi RLTK::CG::NativeIntType, { next_b.last=> value, next_b.last => value}, 'iftmp' }
|
88
|
+
build(start) { br b }
|
89
|
+
build(next_b.last) { br phi_bb }
|
90
|
+
st.exit_scope
|
91
|
+
returning(phi_inst) { target phi_bb }
|
66
92
|
end
|
67
93
|
|
68
94
|
on Return do |node|
|
@@ -85,6 +111,8 @@ module Oryx
|
|
85
111
|
when LEQ then integer_cast(icmp(:sle, left, right), RLTK::CG::NativeIntType, 'booltmp')
|
86
112
|
when EQ then integer_cast(icmp(:eq, left, right), RLTK::CG::NativeIntType, 'booltmp')
|
87
113
|
when NEQ then integer_cast(icmp(:ne, left, right), RLTK::CG::NativeIntType, 'booltmp')
|
114
|
+
when And then integer_cast((build_inst :and, left, right), RLTK::CG::NativeIntType, 'andtmp')
|
115
|
+
when Or then integer_cast((build_inst :or, left, right), RLTK::CG::NativeIntType, 'ortmp')
|
88
116
|
end
|
89
117
|
end
|
90
118
|
|
@@ -92,11 +120,37 @@ module Oryx
|
|
92
120
|
RLTK::CG::NativeInt.new(node.value)
|
93
121
|
end
|
94
122
|
|
123
|
+
on BoolConst do |node|
|
124
|
+
int_val = (node.value == :true) ? 1 : 0
|
125
|
+
RLTK::CG::Int1.new(int_val)
|
126
|
+
end
|
127
|
+
|
128
|
+
on Neg do |node|
|
129
|
+
right = visit node.right
|
130
|
+
sub(ZERO, right, 'negtmp')
|
131
|
+
end
|
132
|
+
|
95
133
|
on GInitialization do |node|
|
96
134
|
name = node.name.to_sym
|
97
135
|
value = visit node.right
|
136
|
+
loc = alloca RLTK::CG::NativeIntType, name.to_s
|
137
|
+
puts "#{name} -> #{loc}"
|
138
|
+
begin
|
139
|
+
st.insert(name, loc)
|
140
|
+
rescue SymbolTableError => e
|
141
|
+
STDERR.puts e.message, "Continuing processing without modifying the symbol table"
|
142
|
+
end
|
143
|
+
puts "#{name} -> #{st.lookup name}"
|
144
|
+
store value, loc
|
145
|
+
end
|
146
|
+
|
147
|
+
on Initialization do |node|
|
148
|
+
name = node.name.to_sym
|
149
|
+
value = visit node.right
|
150
|
+
loc = alloca RLTK::CG::NativeIntType, name.to_s
|
98
151
|
begin
|
99
|
-
st.insert(name,
|
152
|
+
st.insert(name, loc)
|
153
|
+
store value, loc
|
100
154
|
rescue SymbolTableError => e
|
101
155
|
STDERR.puts e.message, "Continuing processing without modifying the symbol table"
|
102
156
|
end
|
@@ -104,8 +158,9 @@ module Oryx
|
|
104
158
|
|
105
159
|
on GDeclaration do |node|
|
106
160
|
name = node.name.to_sym
|
161
|
+
loc = alloca RLTK::CG::NativeIntType, name.to_s
|
107
162
|
begin
|
108
|
-
st.insert name
|
163
|
+
st.insert name, loc
|
109
164
|
rescue SymbolTableError => e
|
110
165
|
STDERR.puts e.message, "Continuing processing without modifying the symbol table"
|
111
166
|
end
|
@@ -113,8 +168,9 @@ module Oryx
|
|
113
168
|
|
114
169
|
on Declaration do |node|
|
115
170
|
name = node.name.to_sym
|
171
|
+
loc = alloca RLTK::CG::NativeIntType, name.to_s
|
116
172
|
begin
|
117
|
-
st.insert name
|
173
|
+
st.insert name, loc
|
118
174
|
rescue SymbolTableError => e
|
119
175
|
STDERR.puts e.message, "Continuing processing without modifying the symbol table"
|
120
176
|
end
|
@@ -124,7 +180,9 @@ module Oryx
|
|
124
180
|
value = visit node.right
|
125
181
|
name = node.name.to_sym
|
126
182
|
begin
|
127
|
-
st.
|
183
|
+
loc = st.lookup name
|
184
|
+
store value, loc
|
185
|
+
self.load loc, name.to_s
|
128
186
|
rescue SymbolTableError => e
|
129
187
|
STDERR.puts e.message, "Continuing processing witout modifying the symbol table"
|
130
188
|
end
|
@@ -155,6 +213,7 @@ module Oryx
|
|
155
213
|
build(start_bb) { cond cond_val, then_bb, else_bb }
|
156
214
|
build(new_then_bb) { br merge_bb }
|
157
215
|
build(new_else_bb) { br merge_bb }
|
216
|
+
@branch_needed = false
|
158
217
|
returning(phi_inst) { target merge_bb }
|
159
218
|
end
|
160
219
|
|
data/lib/oryx/options.rb
CHANGED
@@ -4,12 +4,15 @@ require 'pathname'
|
|
4
4
|
module Oryx
|
5
5
|
class Options
|
6
6
|
DEFAULT_INPUT = ""
|
7
|
-
DEFAULT_OUTPUT = Pathname.new
|
7
|
+
DEFAULT_OUTPUT = Pathname.new "a.out"
|
8
8
|
|
9
9
|
def initialize(argv)
|
10
|
-
@config = {output:
|
11
|
-
input:
|
10
|
+
@config = {output: DEFAULT_OUTPUT,
|
11
|
+
input: DEFAULT_INPUT,
|
12
|
+
verbose: false}
|
13
|
+
|
12
14
|
parse(argv)
|
15
|
+
|
13
16
|
begin
|
14
17
|
input = Pathname.new(argv.pop).expand_path
|
15
18
|
@config[:input] = input
|
@@ -37,6 +40,9 @@ module Oryx
|
|
37
40
|
opts.on("-o", "--output FILE", String, "Output filename") do |path|
|
38
41
|
@config[:output] = Pathname.new(path).expand_path
|
39
42
|
end
|
43
|
+
opts.on("-v", "--verbose", "Auxilary information about compilation process") do
|
44
|
+
@config[:verbose] = true
|
45
|
+
end
|
40
46
|
|
41
47
|
begin
|
42
48
|
argv = ["-h"] if argv.empty?
|
data/lib/oryx/parser.rb
CHANGED
@@ -94,7 +94,7 @@ module Oryx
|
|
94
94
|
clause('e SEMI') { |e, _| e }
|
95
95
|
clause('if_statement') { |i| i}
|
96
96
|
clause('WHILE LPAREN e RPAREN code_block') {|_,_,e,_,c| While.new(e,c) }
|
97
|
-
clause('type_spec IDENT ASSIGN e SEMI') { |t, e0, _, e1, _| Initialization.new
|
97
|
+
clause('type_spec IDENT ASSIGN e SEMI') { |t, e0, _, e1, _| Initialization.new e0, e1, t }
|
98
98
|
clause('type_spec IDENT SEMI') { |t, i, _ | Declaration.new i,t }
|
99
99
|
end
|
100
100
|
|
@@ -118,6 +118,7 @@ module Oryx
|
|
118
118
|
clause('constant') { |c| c }
|
119
119
|
clause('IDENT ASSIGN e') { |e0, _, e1| Assign.new e0, e1 }
|
120
120
|
|
121
|
+
clause('MINUS e') { |_, e| Neg.new(e) }
|
121
122
|
clause('e PLUS e') { |e0, _, e1| Add.new(e0, e1) }
|
122
123
|
clause('e MINUS e') { |e0, _, e1| Sub.new(e0, e1) }
|
123
124
|
clause('e TIMES e') { |e0, _, e1| Mul.new(e0, e1) }
|
@@ -128,13 +129,16 @@ module Oryx
|
|
128
129
|
clause('e LEQ e') { |e0, _, e1| LEQ.new(e0, e1) }
|
129
130
|
clause('e EQ e') { |e0, _, e1| EQ.new(e0, e1) }
|
130
131
|
clause('e NEQ e') { |e0, _, e1| NEQ.new(e0, e1) }
|
132
|
+
clause('e AND e') { |e0, _, e1| And.new(e0, e1) }
|
133
|
+
clause('e OR e') { |e0, _, e1| Or.new(e0, e1) }
|
131
134
|
|
135
|
+
clause('TRUE') { |t| BoolConst.new (:true) }
|
136
|
+
clause('FALSE') { |t| BoolConst.new (:false) }
|
132
137
|
|
133
138
|
clause('RETURN e') { |_, e| Return.new e }
|
134
139
|
|
135
140
|
clause('IDENT LPAREN opt_arg_list RPAREN') { |i, _, oal, _| Call.new(i, oal) }
|
136
141
|
end
|
137
142
|
|
138
|
-
finalize explain: 'explain.out'
|
139
143
|
end
|
140
144
|
end
|
data/lib/oryx/runner.rb
CHANGED
@@ -9,30 +9,68 @@ module Oryx
|
|
9
9
|
@options = Options.new argv
|
10
10
|
@input_filename = @options.input
|
11
11
|
@output_filename = @options.output
|
12
|
+
@verbose = @options.verbose
|
12
13
|
end
|
13
14
|
|
14
15
|
def run
|
15
16
|
puts "input: #{input_filename}"
|
16
17
|
puts "output: #{output_filename}"
|
17
|
-
print "lexing".blue+"."*17
|
18
|
-
l = Lexer.new
|
19
|
-
output_filename.open('w:UTF-8') { |f| f.write(tabularize_output l.lex_file(input_filename.to_s)) }
|
20
|
-
puts "complete".green
|
21
18
|
|
22
|
-
|
23
|
-
ast
|
19
|
+
tokens = lex input_filename
|
20
|
+
ast = parse tokens
|
21
|
+
generate ast
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def lex code
|
26
|
+
STDERR.print "lexing".blue+"."*17
|
27
|
+
l = Lexer.new
|
28
|
+
tokens = l.lex_file(code)
|
29
|
+
output("lex") { tabularize_output tokens }
|
30
|
+
STDERR.puts "complete".green
|
31
|
+
tokens
|
32
|
+
end
|
24
33
|
|
25
|
-
|
26
|
-
|
34
|
+
def parse tokens=[]
|
35
|
+
STDERR.print "parsing".blue+"."*17
|
36
|
+
finalize_parser
|
37
|
+
p = Parser.new
|
38
|
+
parse_flags = Hash.new
|
39
|
+
parse_flags.merge!( {
|
40
|
+
parse_tree: name("parse.dot"),
|
41
|
+
verbose: name("parse.log")
|
42
|
+
}
|
43
|
+
) if @verbose
|
44
|
+
ast = p.parse(tokens, parse_flags)
|
45
|
+
STDERR.puts "complete".green
|
46
|
+
ast
|
47
|
+
end
|
27
48
|
|
28
|
-
|
49
|
+
def generate ast
|
50
|
+
STDERR.print "generating".blue+"."*17
|
51
|
+
c = Contractor.new
|
52
|
+
c.begin ast
|
29
53
|
|
30
|
-
|
31
|
-
create_executable
|
54
|
+
output_ir c.module
|
32
55
|
|
33
|
-
|
56
|
+
translate_to_assembly
|
57
|
+
create_executable
|
58
|
+
STDERR.puts "complete".green
|
59
|
+
end
|
60
|
+
|
61
|
+
def finalize_parser
|
62
|
+
if 0 == Parser.class_eval { @states.length }
|
63
|
+
if @verbose
|
64
|
+
explain_file = name("parse")
|
65
|
+
Parser.class_eval do
|
66
|
+
finalize explain: explain_file
|
67
|
+
end
|
68
|
+
else
|
69
|
+
Parser.class_eval { finalize }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
34
73
|
|
35
|
-
private
|
36
74
|
def tabularize_output tokens
|
37
75
|
s = table_header
|
38
76
|
tokens.each do |t|
|
@@ -51,6 +89,17 @@ module Oryx
|
|
51
89
|
input_filename.to_s.split('.').first
|
52
90
|
end
|
53
91
|
|
92
|
+
def name extension
|
93
|
+
"#{base_name}.#{extension.to_s}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def output extension
|
97
|
+
if @verbose
|
98
|
+
file = Pathname.new name(extension)
|
99
|
+
file.open('w:UTF-8') { |f| f.write (yield) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
54
103
|
def output_ir ir_module
|
55
104
|
ir_module.verify
|
56
105
|
orig_stderr = $stderr.clone
|
@@ -60,11 +109,11 @@ module Oryx
|
|
60
109
|
end
|
61
110
|
|
62
111
|
def translate_to_assembly
|
63
|
-
`llc -disable-cfi #{
|
112
|
+
`llc -disable-cfi #{name "ll"}`
|
64
113
|
end
|
65
114
|
|
66
115
|
def create_executable
|
67
|
-
`gcc #{base_name}.s -o #{
|
116
|
+
`gcc #{base_name}.s -o #{output_filename}`
|
68
117
|
end
|
69
118
|
|
70
119
|
def table_header
|
data/lib/oryx/version.rb
CHANGED
data/test/data/and.c
ADDED
data/test/data/and2.c
ADDED
data/test/data/fun_2.c
ADDED
data/test/data/fun_3.c
ADDED
data/test/data/fun_4.c
ADDED
data/test/data/gvar_1.c
CHANGED
data/test/data/if.c
CHANGED
data/test/data/if_2.c
ADDED
data/test/data/if_3.c
ADDED
data/test/data/if_4.c
ADDED
data/test/data/long.c
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
int main(){
|
2
|
+
int a = 1;
|
3
|
+
int b = 2;
|
4
|
+
int c = 3;
|
5
|
+
int d = 4;
|
6
|
+
int e = 5;
|
7
|
+
int f = 6;
|
8
|
+
int g = 7;
|
9
|
+
int h = 8;
|
10
|
+
int j = 9;
|
11
|
+
int i = 10;
|
12
|
+
int k = 11;
|
13
|
+
int l = 12;
|
14
|
+
int m = 13;
|
15
|
+
int n = 14;
|
16
|
+
int o = 15;
|
17
|
+
int p = 16;
|
18
|
+
int q = 17;
|
19
|
+
int r = 18;
|
20
|
+
int s = 19;
|
21
|
+
int t = 20;
|
22
|
+
int u = 21;
|
23
|
+
int v = 22;
|
24
|
+
int w = 23;
|
25
|
+
int x = 24;
|
26
|
+
int y = 25;
|
27
|
+
int z = 26;
|
28
|
+
|
29
|
+
return z;
|
30
|
+
}
|
data/test/data/mut.c
ADDED
data/test/data/neg.c
ADDED
data/test/data/neg2.c
ADDED
data/test/data/neg3.c
ADDED
data/test/data/neg4.c
ADDED
data/test/data/or.c
ADDED
data/test/data/or2.c
ADDED
@@ -8,18 +8,34 @@ module Oryx
|
|
8
8
|
should_generate_toolchain_output("sub", (-7)%256)
|
9
9
|
should_generate_toolchain_output("mul", 175)
|
10
10
|
should_generate_toolchain_output("div", 2)
|
11
|
-
should_generate_toolchain_output("gvar_1", 7)
|
12
|
-
should_generate_toolchain_output("gvar_2", 42)
|
13
|
-
should_generate_toolchain_output("gvar_3", 15)
|
11
|
+
# should_generate_toolchain_output("gvar_1", 7)
|
12
|
+
# should_generate_toolchain_output("gvar_2", 42)
|
13
|
+
# should_generate_toolchain_output("gvar_3", 15)
|
14
14
|
should_generate_toolchain_output("fun_1", 9)
|
15
|
+
should_generate_toolchain_output("fun_2", 25)
|
16
|
+
should_generate_toolchain_output("fun_3", 121)
|
17
|
+
should_generate_toolchain_output("fun_4", 8)
|
15
18
|
should_generate_toolchain_output("ge", 7)
|
16
19
|
should_generate_toolchain_output("le", 8)
|
17
20
|
should_generate_toolchain_output("leq", 15)
|
18
21
|
should_generate_toolchain_output("geq", 9)
|
19
22
|
should_generate_toolchain_output("eq", 5)
|
20
23
|
should_generate_toolchain_output("neq", 4)
|
21
|
-
should_generate_toolchain_output("if",
|
24
|
+
# should_generate_toolchain_output("if", 1)
|
25
|
+
# should_generate_toolchain_output("if_2", 21)
|
26
|
+
should_generate_toolchain_output("if_3", 16)
|
27
|
+
should_generate_toolchain_output("if_4", 21)
|
22
28
|
should_generate_toolchain_output("fib", 34)
|
29
|
+
should_generate_toolchain_output("neg", (-1)%256)
|
30
|
+
should_generate_toolchain_output("neg2", (-11)%256)
|
31
|
+
should_generate_toolchain_output("neg3", 50)
|
32
|
+
should_generate_toolchain_output("neg4", (-13)%256)
|
33
|
+
should_generate_toolchain_output("and", 5)
|
34
|
+
should_generate_toolchain_output("and2", 4)
|
35
|
+
should_generate_toolchain_output("or", 9)
|
36
|
+
should_generate_toolchain_output("or2", 3)
|
37
|
+
should_generate_toolchain_output("mut", 182)
|
38
|
+
should_generate_toolchain_output("long", 26)
|
23
39
|
end
|
24
40
|
end
|
25
41
|
end
|
@@ -10,25 +10,19 @@ module Oryx
|
|
10
10
|
teardown_helper base_name
|
11
11
|
end
|
12
12
|
|
13
|
-
should "create
|
13
|
+
should "create files" do
|
14
14
|
path = @directory + "#{@base_name}.ll"
|
15
15
|
assert path.exist?, "#{path} was not created"
|
16
|
-
end
|
17
16
|
|
18
|
-
should "translate IR into Assembly" do
|
19
17
|
path = @directory + "#{@base_name}.s"
|
20
18
|
assert path.exist?, "#{path} was not created"
|
21
|
-
end
|
22
19
|
|
23
|
-
should "create executable" do
|
24
20
|
path = @directory + "#{@base_name}.out"
|
25
21
|
assert path.exist?, "#{path} was not created"
|
26
22
|
assert path.executable?, "#{path} is not an executable"
|
27
|
-
end
|
28
23
|
|
29
|
-
should "return the correct result" do
|
30
24
|
path = @directory + "#{@base_name}.out"
|
31
|
-
assert_equal return_value, %x[#{path}; echo $?].to_i
|
25
|
+
assert_equal return_value, %x[#{path}; echo $?].to_i, "Wrong result returned"
|
32
26
|
end
|
33
27
|
end
|
34
28
|
end
|
@@ -47,12 +41,15 @@ module Oryx
|
|
47
41
|
def setup_helper file
|
48
42
|
@directory = Pathname.new "test/data/"
|
49
43
|
@base_name = file
|
50
|
-
r = Runner.new [(@directory+"#{@base_name}.c")]
|
44
|
+
r = Runner.new [(@directory+"#{@base_name}.c"), "-o", (@directory+"#{@base_name}.out").to_s]
|
51
45
|
stfu {r.run}
|
52
46
|
end
|
53
47
|
|
54
48
|
def teardown_helper file
|
55
|
-
%w[ll s out].each
|
49
|
+
%w[ll s out].each do |e|
|
50
|
+
path = @directory+"#{@base_name}.#{e}"
|
51
|
+
path.delete if path.exist?
|
52
|
+
end
|
56
53
|
end
|
57
54
|
end
|
58
55
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oryx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -94,6 +94,8 @@ files:
|
|
94
94
|
- doc/cflat.md
|
95
95
|
- doc/conclusion.md
|
96
96
|
- doc/fibonacci.md
|
97
|
+
- doc/img/cfgfib.jpg
|
98
|
+
- doc/img/cfgmain.jpg
|
97
99
|
- doc/img/fib_parse.jpg
|
98
100
|
- doc/intermediate_lang.md
|
99
101
|
- doc/intro.md
|
@@ -114,20 +116,36 @@ files:
|
|
114
116
|
- lib/oryx/version.rb
|
115
117
|
- oryx.gemspec
|
116
118
|
- test/data/add.c
|
119
|
+
- test/data/and.c
|
120
|
+
- test/data/and2.c
|
117
121
|
- test/data/div.c
|
118
122
|
- test/data/eq.c
|
119
123
|
- test/data/fib.c
|
120
124
|
- test/data/fun_1.c
|
125
|
+
- test/data/fun_2.c
|
126
|
+
- test/data/fun_3.c
|
127
|
+
- test/data/fun_4.c
|
121
128
|
- test/data/ge.c
|
122
129
|
- test/data/geq.c
|
123
130
|
- test/data/gvar_1.c
|
124
131
|
- test/data/gvar_2.c
|
125
132
|
- test/data/gvar_3.c
|
126
133
|
- test/data/if.c
|
134
|
+
- test/data/if_2.c
|
135
|
+
- test/data/if_3.c
|
136
|
+
- test/data/if_4.c
|
127
137
|
- test/data/le.c
|
128
138
|
- test/data/leq.c
|
139
|
+
- test/data/long.c
|
129
140
|
- test/data/mul.c
|
141
|
+
- test/data/mut.c
|
142
|
+
- test/data/neg.c
|
143
|
+
- test/data/neg2.c
|
144
|
+
- test/data/neg3.c
|
145
|
+
- test/data/neg4.c
|
130
146
|
- test/data/neq.c
|
147
|
+
- test/data/or.c
|
148
|
+
- test/data/or2.c
|
131
149
|
- test/data/return.c
|
132
150
|
- test/data/sub.c
|
133
151
|
- test/lib/oryx/error_test.rb
|
@@ -152,7 +170,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
152
170
|
version: '0'
|
153
171
|
segments:
|
154
172
|
- 0
|
155
|
-
hash:
|
173
|
+
hash: 2494793455272379608
|
156
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
175
|
none: false
|
158
176
|
requirements:
|
@@ -161,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
179
|
version: '0'
|
162
180
|
segments:
|
163
181
|
- 0
|
164
|
-
hash:
|
182
|
+
hash: 2494793455272379608
|
165
183
|
requirements: []
|
166
184
|
rubyforge_project:
|
167
185
|
rubygems_version: 1.8.23
|
@@ -170,20 +188,36 @@ specification_version: 3
|
|
170
188
|
summary: Take a program written in C-Flat and convert it to x86 assembly
|
171
189
|
test_files:
|
172
190
|
- test/data/add.c
|
191
|
+
- test/data/and.c
|
192
|
+
- test/data/and2.c
|
173
193
|
- test/data/div.c
|
174
194
|
- test/data/eq.c
|
175
195
|
- test/data/fib.c
|
176
196
|
- test/data/fun_1.c
|
197
|
+
- test/data/fun_2.c
|
198
|
+
- test/data/fun_3.c
|
199
|
+
- test/data/fun_4.c
|
177
200
|
- test/data/ge.c
|
178
201
|
- test/data/geq.c
|
179
202
|
- test/data/gvar_1.c
|
180
203
|
- test/data/gvar_2.c
|
181
204
|
- test/data/gvar_3.c
|
182
205
|
- test/data/if.c
|
206
|
+
- test/data/if_2.c
|
207
|
+
- test/data/if_3.c
|
208
|
+
- test/data/if_4.c
|
183
209
|
- test/data/le.c
|
184
210
|
- test/data/leq.c
|
211
|
+
- test/data/long.c
|
185
212
|
- test/data/mul.c
|
213
|
+
- test/data/mut.c
|
214
|
+
- test/data/neg.c
|
215
|
+
- test/data/neg2.c
|
216
|
+
- test/data/neg3.c
|
217
|
+
- test/data/neg4.c
|
186
218
|
- test/data/neq.c
|
219
|
+
- test/data/or.c
|
220
|
+
- test/data/or2.c
|
187
221
|
- test/data/return.c
|
188
222
|
- test/data/sub.c
|
189
223
|
- test/lib/oryx/error_test.rb
|