rltk3 3.0.2
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.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/LICENSE +27 -0
- data/README.md +852 -0
- data/Rakefile +197 -0
- data/lib/rltk/ast.rb +573 -0
- data/lib/rltk/cfg.rb +683 -0
- data/lib/rltk/cg/basic_block.rb +157 -0
- data/lib/rltk/cg/bindings.rb +151 -0
- data/lib/rltk/cg/builder.rb +1127 -0
- data/lib/rltk/cg/context.rb +48 -0
- data/lib/rltk/cg/contractor.rb +51 -0
- data/lib/rltk/cg/execution_engine.rb +194 -0
- data/lib/rltk/cg/function.rb +237 -0
- data/lib/rltk/cg/generated_bindings.rb +8118 -0
- data/lib/rltk/cg/generic_value.rb +95 -0
- data/lib/rltk/cg/instruction.rb +519 -0
- data/lib/rltk/cg/llvm.rb +150 -0
- data/lib/rltk/cg/memory_buffer.rb +75 -0
- data/lib/rltk/cg/module.rb +451 -0
- data/lib/rltk/cg/pass_manager.rb +252 -0
- data/lib/rltk/cg/support.rb +29 -0
- data/lib/rltk/cg/target.rb +230 -0
- data/lib/rltk/cg/triple.rb +58 -0
- data/lib/rltk/cg/type.rb +554 -0
- data/lib/rltk/cg/value.rb +1272 -0
- data/lib/rltk/cg.rb +32 -0
- data/lib/rltk/lexer.rb +372 -0
- data/lib/rltk/lexers/calculator.rb +44 -0
- data/lib/rltk/lexers/ebnf.rb +38 -0
- data/lib/rltk/parser.rb +1702 -0
- data/lib/rltk/parsers/infix_calc.rb +43 -0
- data/lib/rltk/parsers/postfix_calc.rb +34 -0
- data/lib/rltk/parsers/prefix_calc.rb +34 -0
- data/lib/rltk/token.rb +90 -0
- data/lib/rltk/version.rb +11 -0
- data/lib/rltk.rb +16 -0
- data/test/cg/tc_basic_block.rb +83 -0
- data/test/cg/tc_control_flow.rb +191 -0
- data/test/cg/tc_function.rb +54 -0
- data/test/cg/tc_generic_value.rb +33 -0
- data/test/cg/tc_instruction.rb +256 -0
- data/test/cg/tc_llvm.rb +25 -0
- data/test/cg/tc_math.rb +88 -0
- data/test/cg/tc_module.rb +89 -0
- data/test/cg/tc_transforms.rb +68 -0
- data/test/cg/tc_type.rb +69 -0
- data/test/cg/tc_value.rb +151 -0
- data/test/cg/ts_cg.rb +23 -0
- data/test/tc_ast.rb +332 -0
- data/test/tc_cfg.rb +164 -0
- data/test/tc_lexer.rb +216 -0
- data/test/tc_parser.rb +711 -0
- data/test/tc_token.rb +34 -0
- data/test/ts_rltk.rb +47 -0
- metadata +317 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/03/20
|
4
|
+
# Description: This file defines the Context class.
|
5
|
+
|
6
|
+
############
|
7
|
+
# Requires #
|
8
|
+
############
|
9
|
+
|
10
|
+
# Ruby Language Toolkit
|
11
|
+
require 'rltk/cg/bindings'
|
12
|
+
|
13
|
+
#######################
|
14
|
+
# Classes and Modules #
|
15
|
+
#######################
|
16
|
+
|
17
|
+
module RLTK::CG
|
18
|
+
|
19
|
+
# Bindings for LLVM contexts.
|
20
|
+
class Context
|
21
|
+
include BindingClass
|
22
|
+
|
23
|
+
# The Proc object called by the garbage collector to free resources used by LLVM.
|
24
|
+
CLASS_FINALIZER = Proc.new { |id| Bindings.context_dispose(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
|
25
|
+
|
26
|
+
#################
|
27
|
+
# Class Methods #
|
28
|
+
#################
|
29
|
+
|
30
|
+
# @return [Context] A global context.
|
31
|
+
def self.global
|
32
|
+
self.new(Bindings.get_global_context())
|
33
|
+
end
|
34
|
+
|
35
|
+
####################
|
36
|
+
# Instance Methods #
|
37
|
+
####################
|
38
|
+
|
39
|
+
# @param [FFI::Pointer, nil] ptr Pointer representing a context. If nil, a new context is created.
|
40
|
+
def initialize(ptr = nil)
|
41
|
+
@ptr = ptr || Bindings.context_create()
|
42
|
+
|
43
|
+
# Define a finalizer to free the memory used by LLVM for this
|
44
|
+
# context.
|
45
|
+
ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/09/21
|
4
|
+
# Description: This file contains a combination of the Visitor and Builder
|
5
|
+
# classes called a Contractor.
|
6
|
+
|
7
|
+
############
|
8
|
+
# Requires #
|
9
|
+
############
|
10
|
+
|
11
|
+
# Gems
|
12
|
+
require 'filigree/visitor'
|
13
|
+
|
14
|
+
# Ruby Language Toolkit
|
15
|
+
require 'rltk/cg/builder'
|
16
|
+
|
17
|
+
#######################
|
18
|
+
# Classes and Modules #
|
19
|
+
#######################
|
20
|
+
|
21
|
+
module RLTK::CG
|
22
|
+
|
23
|
+
class Contractor < Builder
|
24
|
+
|
25
|
+
include Filigree::Visitor
|
26
|
+
|
27
|
+
####################
|
28
|
+
# Instance Methods #
|
29
|
+
####################
|
30
|
+
|
31
|
+
# Alias out the RLTK::Visitor.visit method.
|
32
|
+
alias :wrapped_visit :visit
|
33
|
+
|
34
|
+
# Visit an object in the context of this builder. See the
|
35
|
+
# Filigree::Visitor's visit method for more details about the basic
|
36
|
+
# behaviour of this method. The special options for this method are:
|
37
|
+
#
|
38
|
+
# @param [Object] object The object to visit.
|
39
|
+
# @param [BasicBlock] at Where to position the contractor before visiting the object.
|
40
|
+
# @param [Boolean] rcb If specified the method will also return the block where the contractor is currently positioned.
|
41
|
+
#
|
42
|
+
# @return [Object]
|
43
|
+
def visit(object, at: nil, rcb: false)
|
44
|
+
target at if at
|
45
|
+
|
46
|
+
result = wrapped_visit(object)
|
47
|
+
|
48
|
+
if rcb then [result, current_block] else result end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/03/15
|
4
|
+
# Description: This file defines the ExecutionEngine class, along with its
|
5
|
+
# subclasses.
|
6
|
+
|
7
|
+
############
|
8
|
+
# Requires #
|
9
|
+
############
|
10
|
+
|
11
|
+
# Gems
|
12
|
+
require 'filigree/abstract_class'
|
13
|
+
|
14
|
+
# Ruby Language Toolkit
|
15
|
+
require 'rltk/cg/bindings'
|
16
|
+
require 'rltk/cg/pass_manager'
|
17
|
+
require 'rltk/cg/target'
|
18
|
+
|
19
|
+
#######################
|
20
|
+
# Classes and Modules #
|
21
|
+
#######################
|
22
|
+
|
23
|
+
module RLTK::CG
|
24
|
+
|
25
|
+
# The ExecutionEngine class and its subclasses execute code from the
|
26
|
+
# provided module, as well as providing a {PassManager} and
|
27
|
+
# {FunctionPassManager} for optimizing modules.
|
28
|
+
#
|
29
|
+
# @abstract Implemented by {Interpreter} and {JITCompiler}.
|
30
|
+
class ExecutionEngine
|
31
|
+
include Filigree::AbstractClass
|
32
|
+
include BindingClass
|
33
|
+
|
34
|
+
# The Proc object called by the garbage collector to free resources used by LLVM.
|
35
|
+
CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_execution_engine(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
|
36
|
+
|
37
|
+
# @return [Module]
|
38
|
+
attr_reader :module
|
39
|
+
|
40
|
+
# Create a new execution engine.
|
41
|
+
#
|
42
|
+
# @param [Module] mod Module to be executed.
|
43
|
+
# @param [Proc] block Block used by subclass constructors. Don't use this parameter.
|
44
|
+
#
|
45
|
+
# @raise [RuntimeError] An error is raised if something went horribly wrong inside LLVM during the creation of this engine.
|
46
|
+
def initialize(mod, &block)
|
47
|
+
check_type(mod, Module, 'mod')
|
48
|
+
|
49
|
+
block = Proc.new { |ptr, error| Bindings.create_execution_engine_for_module(ptr, mod, error) } if block == nil
|
50
|
+
|
51
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
52
|
+
error = FFI::MemoryPointer.new(:pointer)
|
53
|
+
status = block.call(ptr, error)
|
54
|
+
|
55
|
+
if status.zero?
|
56
|
+
@ptr = ptr.read_pointer
|
57
|
+
@module = mod
|
58
|
+
|
59
|
+
# Associate this engine with the provided module.
|
60
|
+
@module.engine = self
|
61
|
+
|
62
|
+
# Define a finalizer to free the memory used by LLVM for
|
63
|
+
# this execution engine.
|
64
|
+
ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
|
65
|
+
else
|
66
|
+
errorp = error.read_pointer
|
67
|
+
message = errorp.null? ? 'Unknown' : errorp.read_string
|
68
|
+
|
69
|
+
error.autorelease = false
|
70
|
+
|
71
|
+
Bindings.dispose_message(error)
|
72
|
+
|
73
|
+
raise "Error creating execution engine: #{message}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Builds a pointer to a global value.
|
78
|
+
#
|
79
|
+
# @param [GlobalValue] global Value you want a pointer to.
|
80
|
+
#
|
81
|
+
# @return [FFI::Pointer]
|
82
|
+
def pointer_to_global(global)
|
83
|
+
Bindings.get_pointer_to_global(@ptr, global)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Execute a function in the engine's module with the given arguments.
|
87
|
+
# The arguments may be either GnericValue objects or any object that
|
88
|
+
# can be turned into a GenericValue.
|
89
|
+
#
|
90
|
+
# @param [Function] fun Function object to be executed.
|
91
|
+
# @param [Array<GenericValue, Object>] args Arguments to be passed to the function.
|
92
|
+
#
|
93
|
+
# @return [GenericValue]
|
94
|
+
def run_function(fun, *args)
|
95
|
+
new_args =
|
96
|
+
fun.params.zip(args).map do |param, arg|
|
97
|
+
if arg.is_a?(GenericValue) then arg else GenericValue.new(arg) end
|
98
|
+
end
|
99
|
+
|
100
|
+
args_ptr = FFI::MemoryPointer.new(:pointer, args.length)
|
101
|
+
args_ptr.write_array_of_pointer(new_args)
|
102
|
+
|
103
|
+
GenericValue.new(Bindings.run_function(@ptr, fun, args.length, args_ptr))
|
104
|
+
end
|
105
|
+
alias :run :run_function
|
106
|
+
|
107
|
+
# Execute a function in the engine's module with the given arguments
|
108
|
+
# as the main function of a program.
|
109
|
+
#
|
110
|
+
# @param [Function] fun Function object to be executed.
|
111
|
+
# @param [Array<String>] args Arguments to be passed to the function.
|
112
|
+
#
|
113
|
+
# @return [GenericValue]
|
114
|
+
def run_function_as_main(fun, *args)
|
115
|
+
# Prepare the ARGV parameter.
|
116
|
+
argv = FFI::MemoryPointer.new(:pointer, argc)
|
117
|
+
argv.write_array_of_pointer(args.map { |str| FFI::MemoryPointer.from_string(str) })
|
118
|
+
|
119
|
+
# Prepare the ENV parameter.
|
120
|
+
env = FFI::MemoryPointer.new(:pointer, ENV.size)
|
121
|
+
env.write_array_of_pointer(ENV.to_a.map { |pair| FFI::MemoryPointer.from_string(pair[0] + '=' + pair[1]) })
|
122
|
+
|
123
|
+
GenericValue.new(Bindings.run_function_as_main(@ptr, fun, args.length, argv, env))
|
124
|
+
end
|
125
|
+
alias :run_main :run_function_as_main
|
126
|
+
|
127
|
+
# @return [TargetData] Information about the target architecture for this execution engine.
|
128
|
+
def target_data
|
129
|
+
TargetData.new(Bindings.get_execution_engine_target_data(@ptr))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# An execution engine that interprets the given code.
|
134
|
+
class Interpreter < ExecutionEngine
|
135
|
+
|
136
|
+
# Create a new interpreter.
|
137
|
+
#
|
138
|
+
# @param [Module] mod Module to be executed.
|
139
|
+
def initialize(mod)
|
140
|
+
super(mod) do |ptr, error|
|
141
|
+
Bindings.create_interpreter_for_module(ptr, mod, error)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# An execution engine that compiles the given code when needed.
|
147
|
+
class JITCompiler < ExecutionEngine
|
148
|
+
|
149
|
+
# Create a new just-in-time compiler.
|
150
|
+
#
|
151
|
+
# @param [Module] mod Module to be executed.
|
152
|
+
# @param [1, 2, 3] opt_level Optimization level; determines how much optimization is done during execution.
|
153
|
+
def initialize(mod, opt_level = 3)
|
154
|
+
super(mod) do |ptr, error|
|
155
|
+
Bindings.create_jit_compiler_for_module(ptr, mod, opt_level, error)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Options for initializing a {MCJITCompiler}.
|
161
|
+
class MCJITCompilerOptions < RLTK::CG::Bindings::MCJITCompilerOptions
|
162
|
+
|
163
|
+
# Create an object representing MCJIT compiler options.
|
164
|
+
#
|
165
|
+
# @param [Integer] opt_level Optimization level
|
166
|
+
# @param [Symbol from _enum_code_model_] code_model JIT compilation code model
|
167
|
+
# @param [Boolean] no_frame_pointer_elim Disable frame pointer elimination
|
168
|
+
# @param [Boolean] enable_fast_i_sel Turn on fast instruction selection
|
169
|
+
def initialize(opt_level = 0, code_model = :jit_default, no_frame_pointer_elim = false,
|
170
|
+
enable_fast_i_sel = true)
|
171
|
+
|
172
|
+
Bindings.initialize_mcjit_compiler_options(self.to_ptr, self.class.size)
|
173
|
+
|
174
|
+
super(opt_level, code_model, no_frame_pointer_elim.to_i, enable_fast_i_sel.to_i, nil)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# The new LLVM JIT execution engine.
|
179
|
+
class MCJITCompiler < ExecutionEngine
|
180
|
+
|
181
|
+
# Create a new MC just-in-time-compiler.
|
182
|
+
#
|
183
|
+
# @see http://llvm.org/docs/MCJITDesignAndImplementation.html
|
184
|
+
# @see http://blog.llvm.org/2013/07/using-mcjit-with-kaleidoscope-tutorial.html
|
185
|
+
#
|
186
|
+
# @param [Module] mod Module to be executed
|
187
|
+
# @param [MCJITCompilerOptions] options Options used to create the MCJIT
|
188
|
+
def initialize(mod, options = MCJITCompilerOptions.new)
|
189
|
+
super(mod) do |ptr, error|
|
190
|
+
Bindings.create_mcjit_compiler_for_module(ptr, mod, options, MCJITCompilerOptions.size, error)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/04/06
|
4
|
+
# Description: This file defines the Function class.
|
5
|
+
|
6
|
+
############
|
7
|
+
# Requires #
|
8
|
+
############
|
9
|
+
|
10
|
+
# Ruby Language Toolkit
|
11
|
+
require 'rltk/cg/bindings'
|
12
|
+
require 'rltk/cg/basic_block'
|
13
|
+
require 'rltk/cg/value'
|
14
|
+
|
15
|
+
#######################
|
16
|
+
# Classes and Modules #
|
17
|
+
#######################
|
18
|
+
|
19
|
+
module RLTK::CG
|
20
|
+
|
21
|
+
# An LLVM IR function.
|
22
|
+
class Function < GlobalValue
|
23
|
+
# @return [FunctionType] FunctionType object describing this function's type.
|
24
|
+
attr_reader :type
|
25
|
+
|
26
|
+
# Define a new function in a given module. You can also use the
|
27
|
+
# {Module::FunctionCollection#add} method to add functions to
|
28
|
+
# modules.
|
29
|
+
#
|
30
|
+
# @param [FFI::Pointer, Module] overloaded Pointer to a function objet or a module.
|
31
|
+
# @param [String] name Name of the function in LLVM IR.
|
32
|
+
# @param [FunctionType, Array(Type, Array<Type>)] type_info FunctionType or Values that will be passed to {FunctionType#initialize}.
|
33
|
+
# @param [Proc] block Block to be executed inside the context of the function.
|
34
|
+
#
|
35
|
+
# @raise [RuntimeError] An error is raised if the overloaded parameter is of an incorrect type.
|
36
|
+
def initialize(overloaded, name = '', *type_info, &block)
|
37
|
+
@ptr =
|
38
|
+
case overloaded
|
39
|
+
when FFI::Pointer
|
40
|
+
overloaded
|
41
|
+
|
42
|
+
when RLTK::CG::Module
|
43
|
+
@type = if type_info.first.is_a?(FunctionType) then type_info.first else FunctionType.new(*type_info) end
|
44
|
+
|
45
|
+
Bindings.add_function(overloaded, name.to_s, @type)
|
46
|
+
|
47
|
+
else
|
48
|
+
raise 'The first argument to Function.new must be either a pointer or an instance of RLTK::CG::Module.'
|
49
|
+
end
|
50
|
+
|
51
|
+
self.instance_exec(self, &block) if block
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [FunctionAttrCollection] Proxy object for inspecting function attributes.
|
55
|
+
def attributes
|
56
|
+
@attributes ||= FunctionAttrCollection.new(self)
|
57
|
+
end
|
58
|
+
alias :attrs :attributes
|
59
|
+
|
60
|
+
# @return [BasicBlockCollection] Proxy object for inspecting a function's basic blocks.
|
61
|
+
def basic_blocks
|
62
|
+
@basic_blocks ||= BasicBlockCollection.new(self)
|
63
|
+
end
|
64
|
+
alias :blocks :basic_blocks
|
65
|
+
|
66
|
+
# Get a function's calling convention.
|
67
|
+
#
|
68
|
+
# @see Bindings._enum_call_conv_
|
69
|
+
#
|
70
|
+
# @return [Symbol]
|
71
|
+
def calling_convention
|
72
|
+
Bindings.enum_type(:call_conv)[Bindings.get_function_call_conv(@ptr)]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Set a function's calling convention.
|
76
|
+
#
|
77
|
+
# @see Bindings._enum_call_conv_
|
78
|
+
#
|
79
|
+
# @param [Symbol] conv Calling convention to set.
|
80
|
+
def calling_convention=(conv)
|
81
|
+
Bindings.set_function_call_conv(@ptr, Bindings.enum_type(:call_conv)[conv])
|
82
|
+
|
83
|
+
conv
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [ParameterCollection] Proxy object for inspecting a function's parameters.
|
87
|
+
def parameters
|
88
|
+
@parameters ||= ParameterCollection.new(self)
|
89
|
+
end
|
90
|
+
alias :params :parameters
|
91
|
+
|
92
|
+
# Verify that the function is valid LLVM IR.
|
93
|
+
#
|
94
|
+
# @return [nil, String] Human-readable description of any invalid constructs if invalid.
|
95
|
+
def verify
|
96
|
+
do_verification(:return_status)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Verify that the function is valid LLVM IR and abort the process if it isn't.
|
100
|
+
#
|
101
|
+
# @return [nil]
|
102
|
+
def verify!
|
103
|
+
do_verification(:abort_process)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Helper function for {#verify} and {#verify!}
|
107
|
+
def do_verification(action)
|
108
|
+
Bindings.verify_function(@ptr, action).to_bool
|
109
|
+
end
|
110
|
+
private :do_verification
|
111
|
+
|
112
|
+
# This class is used to access a function's {BasicBlock BasicBlocks}
|
113
|
+
class BasicBlockCollection
|
114
|
+
include Enumerable
|
115
|
+
|
116
|
+
# @param [Function] fun Function for which this is a proxy.
|
117
|
+
def initialize(fun)
|
118
|
+
@fun = fun
|
119
|
+
end
|
120
|
+
|
121
|
+
# Add a {BasicBlock} to the end of this function.
|
122
|
+
#
|
123
|
+
# @note The first argument to any proc passed to this function
|
124
|
+
# will be the function the block is being appended to.
|
125
|
+
#
|
126
|
+
# @param [String] name Name of the block in LLVM IR.
|
127
|
+
# @param [Builder, nil] builder Builder to be used in evaluating *block*.
|
128
|
+
# @param [Context, nil] context Context in which to create the block.
|
129
|
+
# @param [Array<Object>] block_args Arguments to be passed to *block*. The function the block is appended to is automatically added to the front of this list.
|
130
|
+
# @param [Proc] block Block to be evaluated using *builder* after positioning it at the end of the new block.
|
131
|
+
#
|
132
|
+
# @return [BasicBlock] New BasicBlock.
|
133
|
+
def append(name = '', builder = nil, context = nil, *block_args, &block)
|
134
|
+
BasicBlock.new(@fun, name, builder, context, *block_args, &block)
|
135
|
+
end
|
136
|
+
|
137
|
+
# An iterator for each block inside this collection.
|
138
|
+
#
|
139
|
+
# @yieldparam block [BasicBlock]
|
140
|
+
#
|
141
|
+
# @return [Enumerator] Returns an Enumerator if no block is given.
|
142
|
+
def each
|
143
|
+
return to_enum :each unless block_given?
|
144
|
+
|
145
|
+
ptr = Bindings.get_first_basic_block(@fun)
|
146
|
+
|
147
|
+
self.size.times do |i|
|
148
|
+
yield BasicBlock.new(ptr)
|
149
|
+
ptr = Bindings.get_next_basic_block(ptr)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# @return [BasicBlock, nil] The function's entry block if it has been added.
|
154
|
+
def entry
|
155
|
+
if (ptr = Bindings.get_entry_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
|
156
|
+
end
|
157
|
+
|
158
|
+
# @return [BasicBlock, nil] The function's first block if one has been added.
|
159
|
+
def first
|
160
|
+
if (ptr = Bindings.get_first_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
|
161
|
+
end
|
162
|
+
|
163
|
+
# @return [BasicBlock, nil] The function's last block if one has been added.
|
164
|
+
def last
|
165
|
+
if (ptr = Bindings.get_last_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
|
166
|
+
end
|
167
|
+
|
168
|
+
# @return [Integer] Number of basic blocks that comprise this function.
|
169
|
+
def size
|
170
|
+
Bindings.count_basic_blocks(@fun)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# This class is used to access a function's attributes.
|
175
|
+
class FunctionAttrCollection < AttrCollection
|
176
|
+
@@add_method = :add_function_attr
|
177
|
+
@@del_method = :remove_function_attr
|
178
|
+
|
179
|
+
# Set a target-dependent function attribute.
|
180
|
+
#
|
181
|
+
# @param [String] attribute Attribute name
|
182
|
+
# @param [String] value Attribute value
|
183
|
+
#
|
184
|
+
# @return [void]
|
185
|
+
def add_td_attr(attribute, value)
|
186
|
+
Bindings.add_target_dependent_function_attr(@value, attribute, value)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
# This class is used to access a function's parameters.
|
192
|
+
class ParameterCollection
|
193
|
+
include Enumerable
|
194
|
+
|
195
|
+
# @param [Function] fun Function for which this is a proxy.
|
196
|
+
def initialize(fun)
|
197
|
+
@fun = fun
|
198
|
+
end
|
199
|
+
|
200
|
+
# Access the parameter at the given index.
|
201
|
+
#
|
202
|
+
# @param [Integer] index Index of the desired parameter. May be negative.
|
203
|
+
#
|
204
|
+
# @return [Value] Value object representing the parameter.
|
205
|
+
def [](index)
|
206
|
+
index += self.size if index < 0
|
207
|
+
|
208
|
+
if 0 <= index and index < self.size
|
209
|
+
Value.new(Bindings.get_param(@fun, index))
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# An iterator for each parameter inside this collection.
|
214
|
+
#
|
215
|
+
# @yieldparam val [Value]
|
216
|
+
#
|
217
|
+
# @return [Enumerator] Returns an Enumerator if no block is given.
|
218
|
+
def each
|
219
|
+
return to_enum :each unless block_given?
|
220
|
+
|
221
|
+
self.size.times { |index| yield self[index] }
|
222
|
+
|
223
|
+
self
|
224
|
+
end
|
225
|
+
|
226
|
+
# @return [Integer] Number of function parameters.
|
227
|
+
def size
|
228
|
+
Bindings.count_params(@fun)
|
229
|
+
end
|
230
|
+
|
231
|
+
# @return [Array<Value>] Array of Value objects representing the function parameters.
|
232
|
+
def to_a
|
233
|
+
self.size.times.to_a.inject([]) { |params, index| params << self[index] }
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|