oryx 0.3.1 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|

|
76
|
+
|
77
|
+
## LLVM IR
|
78
|
+

|
79
|
+

|
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
|