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 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.
@@ -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 |
@@ -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
- Parse Tree
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
+
Binary file
Binary file
@@ -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 ?.?.?)
@@ -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 < Binary; end
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
@@ -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
- st.update name.to_sym, fun.params[i]
38
+ fun.params[i].name = name
39
39
  end
40
40
  end
41
-
42
- ret (visit node.body, at: fun.blocks.append('entry'))
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
- st.lookup node.name.to_sym
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
- a = node.statements.map {|s| visit s}
65
- a.first
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, value)
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.update name, value
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
 
@@ -4,12 +4,15 @@ require 'pathname'
4
4
  module Oryx
5
5
  class Options
6
6
  DEFAULT_INPUT = ""
7
- DEFAULT_OUTPUT = Pathname.new("/tmp/oryx-output")
7
+ DEFAULT_OUTPUT = Pathname.new "a.out"
8
8
 
9
9
  def initialize(argv)
10
- @config = {output: DEFAULT_OUTPUT,
11
- input: DEFAULT_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?
@@ -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 t, e0, e1 }
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
@@ -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
- p = Parser.new
23
- ast = p.parse(l.lex_file(input_filename.to_s), parse_tree: 'tree.dot', verbose: 'parse.out')
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
- c = Contractor.new
26
- c.begin ast
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
- output_ir c.module
49
+ def generate ast
50
+ STDERR.print "generating".blue+"."*17
51
+ c = Contractor.new
52
+ c.begin ast
29
53
 
30
- translate_to_assembly
31
- create_executable
54
+ output_ir c.module
32
55
 
33
- end
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 #{base_name}.ll`
112
+ `llc -disable-cfi #{name "ll"}`
64
113
  end
65
114
 
66
115
  def create_executable
67
- `gcc #{base_name}.s -o #{base_name}.out`
116
+ `gcc #{base_name}.s -o #{output_filename}`
68
117
  end
69
118
 
70
119
  def table_header
@@ -1,3 +1,3 @@
1
1
  module Oryx
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.7"
3
3
  end
@@ -0,0 +1,14 @@
1
+ int test_and(int a, int b, int c){
2
+ if(a < b && b > c)
3
+ return 5;
4
+ else
5
+ return 4;
6
+ }
7
+
8
+ int main(){
9
+ int a = 7;
10
+ int b = 8;
11
+ int c = 1;
12
+
13
+ return test_and(a, b, c);
14
+ }
@@ -0,0 +1,14 @@
1
+ int test_and(int a, int b, int c){
2
+ if(a < b && b > c)
3
+ return 5;
4
+ else
5
+ return 4;
6
+ }
7
+
8
+ int main(){
9
+ int a = 7;
10
+ int b = 8;
11
+ int c = 1;
12
+
13
+ return test_and(c,a,b);
14
+ }
@@ -0,0 +1,9 @@
1
+ int fun_2(int a, int b){
2
+ int c;
3
+ c = a + b;
4
+ return c;
5
+ }
6
+
7
+ int main(){
8
+ return fun_2(12,13);
9
+ }
@@ -0,0 +1,11 @@
1
+ int fun_3(int a, int b) {
2
+ int c = a*a;
3
+ int d = 2*a*b;
4
+ int e = b*b;
5
+ int sum = c + d + e;
6
+ return sum;
7
+ }
8
+
9
+ int main(){
10
+ return fun_3(5,6);
11
+ }
@@ -0,0 +1,9 @@
1
+ int f(int a){
2
+ return a+1;
3
+ }
4
+
5
+ int main(){
6
+ int a = 7;
7
+ return f(a);
8
+ }
9
+
@@ -1,5 +1,6 @@
1
- int a = 7;
1
+ int a;
2
2
 
3
3
  int main(){
4
+ a = 7;
4
5
  return a;
5
6
  }
@@ -2,7 +2,7 @@ int a = 8;
2
2
  int b = 13;
3
3
 
4
4
  int main(){
5
- if(a < b){
5
+ if(a > b){
6
6
  a = a + b;
7
7
  b = 1;
8
8
  if (b < a)
@@ -0,0 +1,15 @@
1
+ int a = 8;
2
+ int b = 13;
3
+
4
+ int main(){
5
+ if(a < b){
6
+ a = a + b;
7
+ b = 1;
8
+ if (b > a)
9
+ return b;
10
+ else
11
+ return a;
12
+ }
13
+ else
14
+ return a;
15
+ }
@@ -0,0 +1,20 @@
1
+ int main(){
2
+ int a = 8;
3
+ int b = 13;
4
+ int c;
5
+
6
+ if(a < b){
7
+ c = a;
8
+ }else{
9
+ c = b;
10
+ }
11
+
12
+ if(b < c){
13
+ c = c + b;
14
+ }
15
+ else{
16
+ c = c + a;
17
+ }
18
+
19
+ return c;
20
+ }
@@ -0,0 +1,20 @@
1
+ int main(){
2
+ int a = 8;
3
+ int b = 13;
4
+ int c;
5
+
6
+ if(a < b){
7
+ c = a;
8
+ }else{
9
+ c = b;
10
+ }
11
+
12
+ if(b > c){
13
+ c = c + b;
14
+ }
15
+ else{
16
+ c = c + a;
17
+ }
18
+
19
+ return c;
20
+ }
@@ -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
+ }
@@ -0,0 +1,9 @@
1
+ int main(){
2
+ int a = 5;
3
+ int b;
4
+ b = 9;
5
+ b = b + a;
6
+ a = a* b;
7
+ b = a - b;
8
+ return a + 2*b;
9
+ }
@@ -0,0 +1,3 @@
1
+ int main(){
2
+ return -1;
3
+ }
@@ -0,0 +1,5 @@
1
+ int main(){
2
+ int a = 1;
3
+ int b = -a - 10;
4
+ return b;
5
+ }
@@ -0,0 +1,6 @@
1
+ int main(){
2
+ int a = 42;
3
+ int b = 8;
4
+ int c = a - -b;
5
+ return c;
6
+ }
@@ -0,0 +1,5 @@
1
+ int main(){
2
+ int a = 13;
3
+
4
+ return ---------a;
5
+ }
@@ -0,0 +1,10 @@
1
+ int test_or(int a, int b, int c){
2
+ if(a < b || b < c)
3
+ return a;
4
+ else
5
+ return c;
6
+ }
7
+
8
+ int main(){
9
+ return test_or(9, -5, 3);
10
+ }
@@ -0,0 +1,10 @@
1
+ int test_or(int a, int b, int c){
2
+ if(a < b || b < c)
3
+ return a;
4
+ else
5
+ return c;
6
+ }
7
+
8
+ int main(){
9
+ return test_or(9, 5, 3);
10
+ }
@@ -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", 21)
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 LLVM IR" do
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 { |e| (@directory+"#{@base_name}.#{e}").delete }
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.1
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-04-29 00:00:00.000000000 Z
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: 1968373242303314984
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: 1968373242303314984
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