voodoo 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/voodoo.rb +1 -0
- data/lib/voodoo/code_generator.rb +27 -0
- data/lib/voodoo/compiler.rb +5 -1
- data/lib/voodoo/config.rb +2 -2
- data/lib/voodoo/error.rb +5 -0
- data/lib/voodoo/generators/amd64_nasm_generator.rb +1 -1
- data/lib/voodoo/generators/arm_gas_generator.rb +7 -15
- data/lib/voodoo/generators/common_code_generator.rb +44 -8
- data/lib/voodoo/generators/mips_gas_generator.rb +3 -9
- data/lib/voodoo/generators/nasm_generator.rb +3 -8
- data/lib/voodoo/parser.rb +2 -2
- metadata +16 -15
data/lib/voodoo.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'voodoo/config'
|
2
|
+
require 'voodoo/error'
|
2
3
|
|
3
4
|
module Voodoo
|
4
5
|
# Module for selecting code generators.
|
@@ -64,6 +65,32 @@ module Voodoo
|
|
64
65
|
def formats architecture
|
65
66
|
@@generators[architecture.to_sym].keys
|
66
67
|
end
|
68
|
+
|
69
|
+
# Base class for errors raised by code generators.
|
70
|
+
class Error < Voodoo::Error
|
71
|
+
end
|
72
|
+
|
73
|
+
# Error raised when a symbol is exported after it has been used.
|
74
|
+
class SymbolsExportedAfterUseError < Error
|
75
|
+
def initialize symbols
|
76
|
+
@symbols = symbols
|
77
|
+
super("Symbols exported after they have been used: " +
|
78
|
+
symbols.to_a.join(" "))
|
79
|
+
end
|
80
|
+
|
81
|
+
attr_reader :symbols
|
82
|
+
end
|
83
|
+
|
84
|
+
# Error raised when a symbol is imported after it has been used.
|
85
|
+
class SymbolsImportedAfterUseError < Error
|
86
|
+
def initialize symbols
|
87
|
+
@symbols = symbols
|
88
|
+
super("Symbols imported after they have been used: " +
|
89
|
+
symbols.to_a.join(" "))
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_reader :symbols
|
93
|
+
end
|
67
94
|
end
|
68
95
|
end
|
69
96
|
|
data/lib/voodoo/compiler.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'voodoo/error'
|
1
2
|
require 'voodoo/parser'
|
2
3
|
|
3
4
|
module Voodoo
|
@@ -9,7 +10,7 @@ module Voodoo
|
|
9
10
|
# An example of its usage can be found on the main page for the
|
10
11
|
# Voodoo module.
|
11
12
|
class Compiler
|
12
|
-
class Error <
|
13
|
+
class Error < Voodoo::Error
|
13
14
|
def initialize errors
|
14
15
|
@errors = errors
|
15
16
|
end
|
@@ -54,6 +55,9 @@ module Voodoo
|
|
54
55
|
@generator.add section, statement
|
55
56
|
end
|
56
57
|
|
58
|
+
rescue CodeGenerator::Error => e
|
59
|
+
errors << e
|
60
|
+
|
57
61
|
rescue Parser::MultipleErrors => e
|
58
62
|
errors.concat e.errors
|
59
63
|
|
data/lib/voodoo/config.rb
CHANGED
@@ -2,7 +2,7 @@ module Voodoo
|
|
2
2
|
# Methods to get and set configuration parameters
|
3
3
|
module Config
|
4
4
|
IMPLEMENTATION_NAME = 'Voodoo Compiler'
|
5
|
-
IMPLEMENTATION_VERSION = '1.1.
|
5
|
+
IMPLEMENTATION_VERSION = '1.1.3'
|
6
6
|
|
7
7
|
# Class that holds configuration parameters
|
8
8
|
class Configuration
|
@@ -38,7 +38,7 @@ module Voodoo
|
|
38
38
|
case arch
|
39
39
|
when 'x86_64', 'amd64'
|
40
40
|
:amd64
|
41
|
-
when
|
41
|
+
when /^arm/
|
42
42
|
:arm
|
43
43
|
when 'i386', 'i686'
|
44
44
|
:i386
|
data/lib/voodoo/error.rb
ADDED
@@ -99,7 +99,6 @@ module Voodoo
|
|
99
99
|
@frame_offset = 0
|
100
100
|
@frame_size = 0
|
101
101
|
@function_end_label = nil
|
102
|
-
@imports = Set.new
|
103
102
|
@if_labels = []
|
104
103
|
@saved_registers = [] # registers we've saved in the current frame
|
105
104
|
@saved_size = 0 # bytes dedicated to saved registers
|
@@ -338,6 +337,11 @@ module Voodoo
|
|
338
337
|
@constants = []
|
339
338
|
end
|
340
339
|
|
340
|
+
# Declares symbols to be exported.
|
341
|
+
def emit_export *symbols
|
342
|
+
symbols.each { |sym| emit ".globl #{sym}\n" }
|
343
|
+
end
|
344
|
+
|
341
345
|
# Emit function prologue.
|
342
346
|
def emit_function_prologue formals = [], nlocals = 0
|
343
347
|
# Calculate the number of arguments we were passed in
|
@@ -443,13 +447,13 @@ module Voodoo
|
|
443
447
|
case op
|
444
448
|
when :div
|
445
449
|
func = :"__aeabi_idiv"
|
446
|
-
import func unless @
|
450
|
+
import func unless @relocated_symbols.member? func
|
447
451
|
call func, expr[1], expr[2]
|
448
452
|
emit "cpy #{register}, r0\n" if register != :r0
|
449
453
|
return
|
450
454
|
when :mod
|
451
455
|
func = :"__aeabi_idivmod"
|
452
|
-
import func unless @
|
456
|
+
import func unless @relocated_symbols.member? func
|
453
457
|
call func, expr[1], expr[2]
|
454
458
|
emit "cpy #{register}, r1\n" if register != :r1
|
455
459
|
return
|
@@ -543,11 +547,6 @@ module Voodoo
|
|
543
547
|
end
|
544
548
|
end
|
545
549
|
|
546
|
-
# Export symbols from the current section
|
547
|
-
def export *symbols
|
548
|
-
symbols.each { |sym| emit ".globl #{sym}\n" }
|
549
|
-
end
|
550
|
-
|
551
550
|
# Load byte from _base_ + _offset_ into _register_
|
552
551
|
def get_byte base, offset, register
|
553
552
|
# If base is an integer, but offset isn't, swap them
|
@@ -656,13 +655,6 @@ module Voodoo
|
|
656
655
|
common_if :ifne, x, y
|
657
656
|
end
|
658
657
|
|
659
|
-
# Import labels into the current section
|
660
|
-
def import *symbols
|
661
|
-
# Record imported labels in @imports and @symbol_tracker
|
662
|
-
@imports.merge symbols
|
663
|
-
@symbol_tracker.define *symbols
|
664
|
-
end
|
665
|
-
|
666
658
|
# Introduce a new local variable
|
667
659
|
def let symbol, *expr
|
668
660
|
n = @environment.locals
|
@@ -295,6 +295,13 @@ module Voodoo
|
|
295
295
|
@sections[real_section_name(@section)] << code
|
296
296
|
end
|
297
297
|
|
298
|
+
# Emits code for an import incantation. For some targets, no code actually
|
299
|
+
# need be emitted, so the default implementation of this method does
|
300
|
+
# nothing.
|
301
|
+
def emit_import *symbols
|
302
|
+
# No need to emit anything.
|
303
|
+
end
|
304
|
+
|
298
305
|
# Emits a label.
|
299
306
|
def emit_label name
|
300
307
|
emit "#{name}:\n"
|
@@ -308,11 +315,21 @@ module Voodoo
|
|
308
315
|
# Declares that the given symbols are to be externally visible.
|
309
316
|
# Requires subclasses to implement emit_export.
|
310
317
|
def export *symbols
|
311
|
-
|
312
|
-
|
318
|
+
used_earlier = symbols_used_unrelocated symbols
|
319
|
+
# Exporting symbols after they have been used is not allowed.
|
320
|
+
error = nil
|
321
|
+
unless used_earlier.empty?
|
322
|
+
error = CodeGenerator::SymbolsExportedAfterUseError.new(used_earlier)
|
323
|
+
end
|
324
|
+
begin
|
325
|
+
if real_section_name(section) == ".data"
|
326
|
+
@relocated_symbols.merge symbols
|
327
|
+
end
|
328
|
+
@symbol_tracker.use *symbols
|
329
|
+
emit_export *symbols
|
330
|
+
ensure
|
331
|
+
raise error unless error == nil
|
313
332
|
end
|
314
|
-
@symbol_tracker.use *symbols
|
315
|
-
emit_export *symbols
|
316
333
|
end
|
317
334
|
|
318
335
|
# Adds a function to the current section.
|
@@ -330,13 +347,24 @@ module Voodoo
|
|
330
347
|
end
|
331
348
|
|
332
349
|
# Declares that the given symbols are imported from an external object.
|
333
|
-
#
|
350
|
+
# This function calls emit_import to actually emit code for the import
|
351
|
+
# statements. The default implementation of emit_import does nothing,
|
352
|
+
# so targets where code is required for imports will want to override
|
353
|
+
# emit_import.
|
334
354
|
def import *symbols
|
335
|
-
|
355
|
+
used_earlier = symbols_used_unrelocated symbols
|
356
|
+
# Importing symbols after they have been used is not allowed.
|
357
|
+
error = nil
|
358
|
+
unless used_earlier.empty?
|
359
|
+
error = CodeGenerator::SymbolsImportedAfterUseError.new(used_earlier)
|
360
|
+
end
|
361
|
+
begin
|
336
362
|
@relocated_symbols.merge symbols
|
363
|
+
@symbol_tracker.define *symbols
|
364
|
+
emit_import *symbols
|
365
|
+
ensure
|
366
|
+
raise error unless error == nil
|
337
367
|
end
|
338
|
-
@symbol_tracker.define *symbols
|
339
|
-
emit_import *symbols
|
340
368
|
end
|
341
369
|
|
342
370
|
# Executes a block of code using the given section as the current section.
|
@@ -722,5 +750,13 @@ module Voodoo
|
|
722
750
|
end
|
723
751
|
max
|
724
752
|
end
|
753
|
+
|
754
|
+
# Given symbols, returns the set of symbols among those that
|
755
|
+
# have been used without relocation.
|
756
|
+
def symbols_used_unrelocated symbols
|
757
|
+
symbols_set = symbols.kind_of?(Set) ? symbols : Set.new(symbols)
|
758
|
+
new_symbols = symbols_set - @relocated_symbols
|
759
|
+
@symbol_tracker.used_symbols & new_symbols
|
760
|
+
end
|
725
761
|
end
|
726
762
|
end
|
@@ -136,7 +136,6 @@ module Voodoo
|
|
136
136
|
@TEMPORARIES = [:'$8', :'$9', :'$10', :'$11',
|
137
137
|
:'$12', :'$13', :'$14', :'$15']
|
138
138
|
@function_end_label = nil
|
139
|
-
@imports = {}
|
140
139
|
@if_labels = []
|
141
140
|
super params
|
142
141
|
@output_file_suffix = '.s'
|
@@ -282,7 +281,7 @@ module Voodoo
|
|
282
281
|
# Load function address
|
283
282
|
if global? func
|
284
283
|
@symbol_tracker.use func
|
285
|
-
if @
|
284
|
+
if @relocated_symbols.include? func
|
286
285
|
# Load address from global offset table
|
287
286
|
emit "lw #{@FUNCTION}, %call16(#{func})(#{@GOT})\n"
|
288
287
|
else
|
@@ -395,12 +394,6 @@ module Voodoo
|
|
395
394
|
end
|
396
395
|
end
|
397
396
|
|
398
|
-
# Imports labels into the current section.
|
399
|
-
def emit_import *symbols
|
400
|
-
# Record imported labels in @imports
|
401
|
-
symbols.each { |sym| @imports[sym] = sym }
|
402
|
-
end
|
403
|
-
|
404
397
|
# Emits a label type annotation.
|
405
398
|
def emit_label_type name, type
|
406
399
|
type_map = {
|
@@ -689,6 +682,7 @@ module Voodoo
|
|
689
682
|
return register
|
690
683
|
else
|
691
684
|
# Assume global
|
685
|
+
@symbol_tracker.use x
|
692
686
|
if @relocated_symbols.include? x
|
693
687
|
emit "lw #{register}, %got(#{x})(#{@GOT})\n"
|
694
688
|
else
|
@@ -920,7 +914,7 @@ module Voodoo
|
|
920
914
|
|
921
915
|
# Load function address
|
922
916
|
if global? func
|
923
|
-
if @
|
917
|
+
if @relocated_symbols.include? func
|
924
918
|
# Load address from global offset table
|
925
919
|
emit "lw #{@FUNCTION}, %call16(#{func})(#{@GOT})\n"
|
926
920
|
else
|
@@ -35,12 +35,11 @@ module Voodoo
|
|
35
35
|
#
|
36
36
|
|
37
37
|
# Export symbols from the current section
|
38
|
-
def
|
38
|
+
def emit_export *symbols
|
39
39
|
case real_section_name(section)
|
40
40
|
when ".text"
|
41
41
|
symbols.each { |sym| emit "global #{sym}:function\n" }
|
42
42
|
else
|
43
|
-
@relocated_symbols.merge symbols
|
44
43
|
symbols.each { |sym| emit "global #{sym}:data #{sym}.end-#{sym}\n" }
|
45
44
|
end
|
46
45
|
end
|
@@ -53,12 +52,8 @@ module Voodoo
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
#
|
57
|
-
def
|
58
|
-
@symbol_tracker.define *symbols
|
59
|
-
if real_section_name(section) != ".text"
|
60
|
-
@relocated_symbols.merge symbols
|
61
|
-
end
|
55
|
+
# Emits code to declare symbols as imported from an external object.
|
56
|
+
def emit_import *symbols
|
62
57
|
emit "extern #{symbols.join ', '}\n"
|
63
58
|
end
|
64
59
|
|
data/lib/voodoo/parser.rb
CHANGED
@@ -22,7 +22,7 @@ module Voodoo
|
|
22
22
|
class Parser
|
23
23
|
NUMBER_STARTER = /\d|-/
|
24
24
|
STRING_STARTER = '"'
|
25
|
-
SYMBOL_STARTER = /[[:alpha:]]|\\/
|
25
|
+
SYMBOL_STARTER = /[[:alpha:]]|_|\\/
|
26
26
|
|
27
27
|
# Creates a parser using the specified object as input.
|
28
28
|
# The input object must support a method +getc+, which must
|
@@ -41,7 +41,7 @@ module Voodoo
|
|
41
41
|
# This provides methods to get the name of the input being processed,
|
42
42
|
# as well as the start_line, start_column, and text of the code
|
43
43
|
# that triggered the error.
|
44
|
-
class Error <
|
44
|
+
class Error < Voodoo::Error
|
45
45
|
def initialize message, input_name, start_line, start_column, text
|
46
46
|
super message
|
47
47
|
@input_name = input_name
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: voodoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
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-12-01 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'The Voodoo compiler is an implementation of the Voodoo programming
|
15
15
|
|
@@ -30,27 +30,28 @@ extensions: []
|
|
30
30
|
extra_rdoc_files: []
|
31
31
|
files:
|
32
32
|
- bin/voodooc
|
33
|
-
- lib/voodoo.rb
|
34
|
-
- lib/voodoo/parser.rb
|
35
|
-
- lib/voodoo/generators/mips_elf_generator.rb
|
36
|
-
- lib/voodoo/generators/common_code_generator.rb
|
37
|
-
- lib/voodoo/generators/nasm_elf_generator.rb
|
38
|
-
- lib/voodoo/generators/amd64_nasm_generator.rb
|
39
|
-
- lib/voodoo/generators/gas_elf_generator.rb
|
40
|
-
- lib/voodoo/generators/i386_nasm_generator.rb
|
33
|
+
- lib/voodoo/symbol_tracker.rb
|
41
34
|
- lib/voodoo/generators/arm_gas_generator.rb
|
42
|
-
- lib/voodoo/generators/nasm_generator.rb
|
43
35
|
- lib/voodoo/generators/mips_gas_generator.rb
|
36
|
+
- lib/voodoo/generators/common_code_generator.rb
|
37
|
+
- lib/voodoo/generators/mips_elf_generator.rb
|
44
38
|
- lib/voodoo/generators/dummy_generator.rb
|
45
|
-
- lib/voodoo/generators/arm_elf_generator.rb
|
46
39
|
- lib/voodoo/generators/amd64_elf_generator.rb
|
40
|
+
- lib/voodoo/generators/arm_elf_generator.rb
|
47
41
|
- lib/voodoo/generators/i386_elf_generator.rb
|
42
|
+
- lib/voodoo/generators/i386_nasm_generator.rb
|
43
|
+
- lib/voodoo/generators/amd64_nasm_generator.rb
|
44
|
+
- lib/voodoo/generators/nasm_generator.rb
|
48
45
|
- lib/voodoo/generators/command_postprocessor.rb
|
46
|
+
- lib/voodoo/generators/gas_elf_generator.rb
|
47
|
+
- lib/voodoo/generators/nasm_elf_generator.rb
|
48
|
+
- lib/voodoo/parser.rb
|
49
|
+
- lib/voodoo/config.rb
|
50
|
+
- lib/voodoo/error.rb
|
51
|
+
- lib/voodoo/validator.rb
|
49
52
|
- lib/voodoo/code_generator.rb
|
50
53
|
- lib/voodoo/compiler.rb
|
51
|
-
- lib/voodoo
|
52
|
-
- lib/voodoo/config.rb
|
53
|
-
- lib/voodoo/symbol_tracker.rb
|
54
|
+
- lib/voodoo.rb
|
54
55
|
homepage: http://inglorion.net/software/voodoo/
|
55
56
|
licenses: []
|
56
57
|
post_install_message:
|