rltk 2.0.0 → 2.1.0

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.
@@ -32,6 +32,52 @@ module RLTK::CG::Bindings
32
32
  # @scope class
33
33
  attach_function :target_version, :LLVMTargetVersion, [], :string
34
34
 
35
+ # (Not documented)
36
+ #
37
+ # @method initialize_all_asm_parsers()
38
+ # @return [nil]
39
+ # @scope class
40
+ attach_function :initialize_all_asm_parsers, :LLVMInitializeAllAsmParsers, [], :void
41
+
42
+ # (Not documented)
43
+ #
44
+ # @method initialize_all_asm_printers()
45
+ # @return [nil]
46
+ # @scope class
47
+ attach_function :initialize_all_asm_printers, :LLVMInitializeAllAsmPrinters, [], :void
48
+
49
+ # (Not documented)
50
+ #
51
+ # @method initialize_native_target_asm_parser()
52
+ # @return [nil]
53
+ # @scope class
54
+ attach_function :initialize_native_target_asm_parser, :LLVMInitializeNativeTargetAsmParser, [], :void
55
+
56
+ # (Not documented)
57
+ #
58
+ # @method initialize_native_target_asm_printer()
59
+ # @return [nil]
60
+ # @scope class
61
+ attach_function :initialize_native_target_asm_printer, :LLVMInitializeNativeTargetAsmPrinter, [], :void
62
+
63
+ # (Not documented)
64
+ #
65
+ # @method load_module_from_ir_file(file_name, context)
66
+ # @param [String] file_name
67
+ # @param [FFI::Pointer(ContextRef)] context
68
+ # @return [FFI::Pointer(ModuleRef)]
69
+ # @scope class
70
+ attach_function :load_module_from_ir_file, :LLVMLoadModuleFromIRFile, [:string, :pointer], :pointer
71
+
72
+ # (Not documented)
73
+ #
74
+ # @method print_module(mod, fd)
75
+ # @param [FFI::Pointer(ModuleRef)] mod
76
+ # @param [Integer] fd
77
+ # @return [nil]
78
+ # @scope class
79
+ attach_function :print_module, :LLVMPrintModule, [:pointer, :int], :void
80
+
35
81
  # (Not documented)
36
82
  #
37
83
  # @method load_library_permanently(filename)
@@ -40,4 +86,202 @@ module RLTK::CG::Bindings
40
86
  # @scope class
41
87
  attach_function :load_library_permanently, :LLVMLoadLibraryPermanently, [:string], :int
42
88
 
89
+ # (Not documented)
90
+ #
91
+ # @method print_value(val, fd)
92
+ # @param [FFI::Pointer(ValueRef)] val
93
+ # @param [Integer] fd
94
+ # @return [nil]
95
+ # @scope class
96
+ attach_function :print_value, :LLVMPrintValue, [:pointer, :int], :void
97
+
98
+ # (Not documented)
99
+ #
100
+ # <em>This entry is only for documentation and no real method. The FFI::Enum can be accessed via #enum_type(:code_model).</em>
101
+ #
102
+ # === Options:
103
+ # :default_cmodel ::
104
+ #
105
+ # :kernel ::
106
+ #
107
+ # :small ::
108
+ #
109
+ # :medium ::
110
+ #
111
+ # :large ::
112
+ #
113
+ #
114
+ # @method _enum_code_model_
115
+ # @return [Symbol]
116
+ # @scope class
117
+ enum :code_model, [
118
+ :default_cmodel, 0,
119
+ :kernel, 1,
120
+ :small, 2,
121
+ :medium, 3,
122
+ :large, 4
123
+ ]
124
+
125
+ # (Not documented)
126
+ #
127
+ # <em>This entry is only for documentation and no real method. The FFI::Enum can be accessed via #enum_type(:reloc_model).</em>
128
+ #
129
+ # === Options:
130
+ # :default_rmodel ::
131
+ #
132
+ # :static ::
133
+ #
134
+ # :pic ::
135
+ #
136
+ # :dynamic_no_pic ::
137
+ #
138
+ #
139
+ # @method _enum_reloc_model_
140
+ # @return [Symbol]
141
+ # @scope class
142
+ enum :reloc_model, [
143
+ :default_rmodel, 0,
144
+ :static, 1,
145
+ :pic, 2,
146
+ :dynamic_no_pic, 3
147
+ ]
148
+
149
+ # (Not documented)
150
+ #
151
+ # <em>This entry is only for documentation and no real method. The FFI::Enum can be accessed via #enum_type(:compile_type).</em>
152
+ #
153
+ # === Options:
154
+ # :asm ::
155
+ #
156
+ # :object ::
157
+ #
158
+ #
159
+ # @method _enum_compile_type_
160
+ # @return [Symbol]
161
+ # @scope class
162
+ enum :compile_type, [
163
+ :asm, 0,
164
+ :object, 1
165
+ ]
166
+
167
+ # (Not documented)
168
+ class OpaqueTarget < FFI::Struct
169
+ layout :dummy, :char
170
+ end
171
+
172
+ # (Not documented)
173
+ class OpaqueTargetMachine < FFI::Struct
174
+ layout :dummy, :char
175
+ end
176
+
177
+ # (Not documented)
178
+ class OpaqueTriple < FFI::Struct
179
+ layout :dummy, :char
180
+ end
181
+
182
+ # // Utility
183
+ #
184
+ # @method build_features_string(attrs, num_attrs)
185
+ # @param [FFI::Pointer(**CharS)] attrs
186
+ # @param [Integer] num_attrs
187
+ # @return [String]
188
+ # @scope class
189
+ attach_function :build_features_string, :LLVMBuildFeaturesString, [:pointer, :int], :string
190
+
191
+ # (Not documented)
192
+ #
193
+ # @method compile_module_to_file(mod, machine, pm, file_name, ctype, opt_level, no_verify)
194
+ # @param [FFI::Pointer(ModuleRef)] mod
195
+ # @param [OpaqueTargetMachine] machine
196
+ # @param [FFI::Pointer(PassManagerRef)] pm
197
+ # @param [String] file_name
198
+ # @param [Symbol from _enum_compile_type_] ctype
199
+ # @param [Integer] opt_level
200
+ # @param [Integer] no_verify
201
+ # @return [nil]
202
+ # @scope class
203
+ attach_function :compile_module_to_file, :LLVMCompileModuleToFile, [:pointer, OpaqueTargetMachine, :pointer, :string, :compile_type, :uint, :uint], :void
204
+
205
+ # (Not documented)
206
+ #
207
+ # @method ecb_initialize_all_targets()
208
+ # @return [nil]
209
+ # @scope class
210
+ attach_function :ecb_initialize_all_targets, :LLVMECBInitializeAllTargets, [], :void
211
+
212
+ # (Not documented)
213
+ #
214
+ # @method ecb_initialize_native_target()
215
+ # @return [nil]
216
+ # @scope class
217
+ attach_function :ecb_initialize_native_target, :LLVMECBInitializeNativeTarget, [], :void
218
+
219
+ # // Target
220
+ #
221
+ # @method get_target_from_name(name)
222
+ # @param [String] name
223
+ # @return [OpaqueTarget]
224
+ # @scope class
225
+ attach_function :get_target_from_name, :LLVMGetTargetFromName, [:string], OpaqueTarget
226
+
227
+ # (Not documented)
228
+ #
229
+ # @method get_target_from_triple(triple)
230
+ # @param [OpaqueTriple] triple
231
+ # @return [OpaqueTarget]
232
+ # @scope class
233
+ attach_function :get_target_from_triple, :LLVMGetTargetFromTriple, [OpaqueTriple], OpaqueTarget
234
+
235
+ # // Target Machine
236
+ #
237
+ # @method create_target_machine(target, triple, mcpu, features, rmodel, cmodel)
238
+ # @param [OpaqueTarget] target
239
+ # @param [String] triple
240
+ # @param [String] mcpu
241
+ # @param [String] features
242
+ # @param [Symbol from _enum_reloc_model_] rmodel
243
+ # @param [Symbol from _enum_code_model_] cmodel
244
+ # @return [OpaqueTargetMachine]
245
+ # @scope class
246
+ attach_function :create_target_machine, :LLVMCreateTargetMachine, [OpaqueTarget, :string, :string, :string, :reloc_model, :code_model], OpaqueTargetMachine
247
+
248
+ # (Not documented)
249
+ #
250
+ # @method set_target_machine_asm_verbosity(machine, boolean)
251
+ # @param [OpaqueTargetMachine] machine
252
+ # @param [Integer] boolean
253
+ # @return [nil]
254
+ # @scope class
255
+ attach_function :set_target_machine_asm_verbosity, :LLVMSetTargetMachineASMVerbosity, [OpaqueTargetMachine, :int], :void
256
+
257
+ # // Triple
258
+ #
259
+ # @method get_host_triple()
260
+ # @return [OpaqueTriple]
261
+ # @scope class
262
+ attach_function :get_host_triple, :LLVMGetHostTriple, [], OpaqueTriple
263
+
264
+ # (Not documented)
265
+ #
266
+ # @method get_host_triple_string()
267
+ # @return [String]
268
+ # @scope class
269
+ attach_function :get_host_triple_string, :LLVMGetHostTripleString, [], :string
270
+
271
+ # (Not documented)
272
+ #
273
+ # @method get_triple_string(triple)
274
+ # @param [OpaqueTriple] triple
275
+ # @return [String]
276
+ # @scope class
277
+ attach_function :get_triple_string, :LLVMGetTripleString, [OpaqueTriple], :string
278
+
279
+ # (Not documented)
280
+ #
281
+ # @method triple_create(string)
282
+ # @param [String] string
283
+ # @return [OpaqueTriple]
284
+ # @scope class
285
+ attach_function :triple_create, :LLVMTripleCreate, [:string], OpaqueTriple
286
+
43
287
  end
data/lib/rltk/cg/llvm.rb CHANGED
@@ -19,27 +19,85 @@ module RLTK::CG # :nodoc:
19
19
 
20
20
  # This module contains global operations on the LLVM compiler infrastructure.
21
21
  module LLVM
22
- # Initialize LLVM to generate code for a given architecture.
22
+ # Initialize LLVM to generate code for a given architecture. You may
23
+ # also specify :all to initialize all targets or :native to
24
+ # initialize the host target.
23
25
  #
24
26
  # @see Bindings::ARCHS
25
27
  #
26
28
  # @param [Symbol] arch Architecture to initialize LLVM for.
27
29
  #
28
- # @raise [RuntimeError] An error is raised if an unsupported architecture is specified.
30
+ # @raise [ArgumentError] An error is raised if an unsupported architecture is specified.
29
31
  #
30
- # @return [true]
32
+ # @return [void]
31
33
  def self.init(arch)
32
- if Bindings::ARCHS.include?(arch) or Bindings::ARCHS.map { |sym| sym.to_s.downcase.to_sym }.include?(arch)
34
+ if arch == :all
35
+ Bindings.ecb_initialize_all_targets
36
+
37
+ elsif arch == :native
38
+ Bindings.ecb_initialize_native_target
39
+
40
+ elsif Bindings::ARCHS.include?(arch) or Bindings::ARCHS.map { |sym| sym.to_s.downcase.to_sym }.include?(arch)
33
41
  arch = Bindings.get_bname(arch)
34
42
 
35
43
  Bindings.send("initialize_#{arch}_target".to_sym)
36
44
  Bindings.send("initialize_#{arch}_target_info".to_sym)
37
45
  Bindings.send("initialize_#{arch}_target_mc".to_sym)
38
46
 
39
- true
47
+ else
48
+ raise ArgumentError, "Unsupported architecture specified: #{arch}."
49
+ end
50
+ end
51
+
52
+ # Initialize a given ASM parser inside LLVM. You may also specify
53
+ # :all to initialize all ASM parsers.
54
+ #
55
+ # @see Bindings::ASM_PARSERS
56
+ #
57
+ # @param [Symbol] asm Assembly language type to initialize parser for.
58
+ #
59
+ # @raise [ArgumentError] An error is raised if an unsupported assembler parser is specified.
60
+ #
61
+ # @return [void]
62
+ def self.init_asm_parser(asm)
63
+ if asm == :all
64
+ Bindings.initialize_all_asm_parsers
65
+
66
+ elsif Bindings::ASM_PARSERS.include?(asm) or Bindings::ASM_PARSERS.map { |sym| sym.to_s.downcase.to_sym }.include?(asm)
67
+ asm = Bindings.get_bname(asm)
68
+
69
+ Bindings.send("initialize_#{asm}_asm_parser".to_sym)
70
+
71
+ else
72
+ raise ArgumentError, "Unsupported assembler type specified: #{asm}"
73
+ end
74
+ end
75
+
76
+ # Initialize a given ASM printer inside LLVM. You may also specify
77
+ # :all to initialize all ASM printers or :native to initialize the
78
+ # printer for the host machine's assembly language.
79
+ #
80
+ # @see Bindings::ASM_PRINTERS
81
+ #
82
+ # @param [Symbol] asm Assembly language type to initialize printer for.
83
+ #
84
+ # @raise [ArgumentError] An error is raised if an unsupported assembler printer is specified.
85
+ #
86
+ # @return [void]
87
+ def self.init_asm_printer(asm)
88
+ if asm == :all
89
+ Bindings.initialize_all_asm_printers
90
+
91
+ elsif asm == :native
92
+ Bindings.initialize_native_asm_printer
93
+
94
+ elsif Bindings::ASM_PRINTERS.include?(asm) or Bindings::ASM_PRINTERS.map { |sym| sym.to_s.downcase.to_sym }.include?(asm)
95
+ asm = Bindings.get_bname(asm)
96
+
97
+ Bindings.send("initialize_#{asm}_asm_printer".to_sym)
40
98
 
41
99
  else
42
- raise "Unsupported architecture specified: #{arch}"
100
+ raise ArgumentError, "Unsupported assembler type specified: #{asm}"
43
101
  end
44
102
  end
45
103
 
@@ -22,11 +22,15 @@ module RLTK::CG # :nodoc:
22
22
  class Module
23
23
  include BindingClass
24
24
 
25
+ # @!attribute [rw] engine
26
+ # @return [ExecutionEngine, nil] Execution engine associated with this module.
27
+ attr_accessor :engine
28
+
25
29
  # Load a module from LLVM bitcode.
26
30
  #
27
31
  # @see MemoryBuffer#initialize
28
32
  #
29
- # @param [MemoryBuffer, FFI::Pointer, String, nil] overloaded Where to read the bytecode from.
33
+ # @param [MemoryBuffer, FFI::Pointer, String, nil] overloaded Where to read the bitecode from.
30
34
  #
31
35
  # @return [Module]
32
36
  def self.read_bitcode(overloaded)
@@ -44,6 +48,15 @@ module RLTK::CG # :nodoc:
44
48
  end
45
49
  end
46
50
 
51
+ # Load a Module form an LLVM IR file.
52
+ #
53
+ # @param [String] file_name Name of file containing LLVM IR module.
54
+ #
55
+ # @return [Module]
56
+ def self.read_ir_file(file_name, context = Context.global)
57
+ self.new(Bindings.load_module_from_ir_file(file_name, context))
58
+ end
59
+
47
60
  # Create a new LLVM module.
48
61
  #
49
62
  # @param [FFI::Pointer, String] overloaded Pointer to existing module or name of new module.
@@ -66,6 +79,19 @@ module RLTK::CG # :nodoc:
66
79
  self.instance_exec(&block) if block
67
80
  end
68
81
 
82
+ # Compile this module to an assembly or object file.
83
+ #
84
+ # @param [String] file_name Name of output file.
85
+ # @param [:asm, :object] mode Generate assembly or object file?
86
+ # @param [TargetMachine] machine Machine type to target.
87
+ # @param [0, 1, 2, 3] opt_level Optimization level to use during compilation.
88
+ # @param [Boolean] verify Verify the module before compilation or not.
89
+ #
90
+ # @return [void]
91
+ def compile(file_name, mode = :object, machine = TargetMachine.host, opt_level = 2, verify = true)
92
+ Bindings.compile_module_to_file(@ptr, machine, self.pm, file_name, mode, opt_level, (!verify).to_i)
93
+ end
94
+
69
95
  # @return [Context] Context in which this module exists.
70
96
  def context
71
97
  Context.new(Bindings.get_module_context(@ptr))
@@ -82,13 +108,49 @@ module RLTK::CG # :nodoc:
82
108
  end
83
109
  end
84
110
 
85
- # Print the IR of this module to standard out.
111
+ # Print the LLVM IR representation of this value to standard error.
112
+ # This function is the debugging version of the more general purpose
113
+ # {#print} method.
114
+ #
115
+ # @see #print
86
116
  #
87
117
  # @return [void]
88
118
  def dump
89
119
  Bindings.dump_module(@ptr)
90
120
  end
91
121
 
122
+ # @return [FunctionPassManager] Function pass manager for this module.
123
+ def function_pass_manager
124
+ @function_pass_manager ||= FunctionPassManager.new(self)
125
+ end
126
+ alias :fpm :function_pass_manager
127
+
128
+ # @return [PassManager] Pass manager for this module.
129
+ def pass_manager
130
+ @pass_manager ||= PassManager.new(self)
131
+ end
132
+ alias :pm :pass_manager
133
+
134
+ # Print the LLVM IR representation of this module to a file. The
135
+ # file may be specified via a file name (which will be created or
136
+ # truncated) or an object that responds to #fileno.
137
+ #
138
+ # @LLVMECB
139
+ #
140
+ # @param [String, #fileno] io File name or object with a file descriptor to print to.
141
+ #
142
+ # @return [void]
143
+ def print(io = $stdout)
144
+ case io
145
+ when String
146
+ File.open(io, 'w') do |f|
147
+ Bindings.print_module(@ptr, f.fileno)
148
+ end
149
+ else
150
+ Bindings.print_module(@ptr, io.fileno)
151
+ end
152
+ end
153
+
92
154
  # @return [FunctionCollection] Proxy object for inspecting this module's functions.
93
155
  def functions
94
156
  @functions ||= FunctionCollection.new(self)
@@ -100,6 +162,22 @@ module RLTK::CG # :nodoc:
100
162
  @globals ||= GlobalCollection.new(self)
101
163
  end
102
164
 
165
+ # Set the module's target triple.
166
+ #
167
+ # @param [String] triple Triple value to set.
168
+ #
169
+ # @return [void]
170
+ def target=(triple)
171
+ Bindings.set_target(@ptr, triple)
172
+ end
173
+
174
+ # Get the module's target triple.
175
+ #
176
+ # @return [String]
177
+ def target
178
+ Bindings.get_target(@ptr)
179
+ end
180
+
103
181
  # Write the module as LLVM bitcode to a file.
104
182
  #
105
183
  # @param [#path, #fileno, Integer, String] overloaded Where to write the bitcode.
@@ -68,18 +68,20 @@ module RLTK::CG # :nodoc:
68
68
  :Verifier => :verifier
69
69
  }
70
70
 
71
- # Creat a new pass manager. You should never have to do this as
72
- # {ExecutionEngine ExecutionEngines} creates a PassManager whenever
73
- # one is requested.
71
+ # Create a new pass manager. You should never have to do this as
72
+ # {Module Modules} should create PassManagers for you whenever they
73
+ # are requested.
74
74
  #
75
- # @param [ExecutionEngine] engine ExecutionEngine this pass manager belongs to.
76
- # @param [Module] mod Module this pass manager belongs to.
77
- def initialize(engine, mod)
75
+ # @see Module#pass_manager
76
+ #
77
+ # @param [Module] mod Module this pass manager belongs to.
78
+ def initialize(mod)
78
79
  # LLVM Initialization
79
80
  @ptr = Bindings.create_pass_manager
80
81
  @mod = mod
81
82
 
82
- Bindings.add_target_data(Bindings.get_execution_engine_target_data(engine), @ptr)
83
+ # Set the target data if the module is associated with a execution engine.
84
+ self.target_data = mod.engine.target_data if mod.engine
83
85
 
84
86
  # RLTK Initialization
85
87
  @enabled = Array.new
@@ -152,6 +154,15 @@ module RLTK::CG # :nodoc:
152
154
  Bindings.run_pass_manager(@ptr, @mod).to_bool
153
155
  end
154
156
 
157
+ # Set the target data for this pass manager.
158
+ #
159
+ # @param [TargetData] data
160
+ #
161
+ # @return [void]
162
+ def target_data=(data)
163
+ Bindings.add_target_data(check_type(data, TargetData, 'data'), @ptr)
164
+ end
165
+
155
166
  protected
156
167
  # Empty method used by {FunctionPassManager} to clean up resources.
157
168
  def finalize
@@ -161,19 +172,21 @@ module RLTK::CG # :nodoc:
161
172
  # A FunctionPassManager is responsible for scheduling and running optimization
162
173
  # passes on individual functions inside the context of a module.
163
174
  class FunctionPassManager < PassManager
164
- # Creat a new function pass manager. You should never have to do
165
- # this as {ExecutionEngine ExecutionEngines} creates a
166
- # FunctionPassManager whenever one is requested.
175
+ # Create a new function pass manager. You should never have to do
176
+ # this as {Module Modules} should create FunctionPassManagers for you
177
+ # whenever they are requested.
178
+ #
179
+ # @see Module#function_pass_manager
167
180
  #
168
- # @param [ExecutionEngine] engine ExecutionEngine this pass manager belongs to.
169
- # @param [Module] mod Module this pass manager belongs to.
170
- def initialize(engine, mod)
181
+ # @param [Module] mod Module this pass manager belongs to.
182
+ def initialize(mod)
171
183
  # LLVM Initialization
172
184
  @ptr = Bindings.create_function_pass_manager_for_module(mod)
173
185
 
174
- Bindings.add_target_data(Bindings.get_execution_engine_target_data(engine), @ptr)
186
+ # Set the target data if the module is associated with a execution engine.
187
+ self.target_data = mod.engine.target_data if mod.engine
175
188
 
176
- Bindings.initialize_function_pass_manager(@ptr).to_bool
189
+ Bindings.initialize_function_pass_manager(@ptr)
177
190
 
178
191
  # RLTK Initialization
179
192
  @enabled = Array.new
@@ -21,6 +21,8 @@ module RLTK::CG # :nodoc:
21
21
  # Load a shared library into memory and make its exported symbols
22
22
  # available to execution engines.
23
23
  #
24
+ # @LLVMECB
25
+ #
24
26
  # @param [String] lib Path to the shared library to load.
25
27
  def self.load_library(lib)
26
28
  Bindings.load_library_permanently(lib).to_bool
@@ -0,0 +1,100 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/06/13
4
+ # Description: This file defines the Target class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+ require 'rltk/cg/triple'
13
+
14
+ #######################
15
+ # Classes and Modules #
16
+ #######################
17
+
18
+ module RLTK::CG # :nodoc:
19
+
20
+ # Class binding for the LLVM Triple class.
21
+ class Target
22
+ include BindingClass
23
+
24
+ # @return [Triple] Triple object for this target.
25
+ attr_reader :triple
26
+
27
+ # @return [Target] Target object for the host architecture.
28
+ def self.host
29
+ @host ||= self.new(Triple.host)
30
+ end
31
+
32
+ # Create an object representing a particular code generation target.
33
+ # You can create a target either from a string or a Triple.
34
+ #
35
+ # @param [Triple, String] overloaded Object describing the target.
36
+ def initialize(overloaded)
37
+ @ptr, @triple =
38
+ case overloaded
39
+ when String then [Bindings.get_target_from_string(overloaded), Triple.new(overloaded)]
40
+ when Triple then [Bindings.get_target_from_triple(overloaded), overloaded]
41
+ end
42
+ end
43
+ end
44
+
45
+ # This class represents data about a specific architecture. Currently it
46
+ # is for internal use only and should not be instantiated by users.
47
+ class TargetData
48
+ include BindingClass
49
+
50
+ # @param [FFI::Pointer] ptr
51
+ def initialize(ptr)
52
+ @ptr = ptr
53
+ end
54
+ end
55
+
56
+ # This class represents a specific architecture that wil be targeted by
57
+ # LLVM's compilation process.
58
+ class TargetMachine
59
+ include BindingClass
60
+
61
+ # Convert an array of strings representing features of a target
62
+ # machine into a single string.
63
+ #
64
+ # @param [Array<String>] features Strings representing features of a target machine.
65
+ #
66
+ # @return [String] A single string representing all of the given features.
67
+ def self.build_feature_string(features)
68
+ strings_ptr = FFI::MemoryPointer.new(:pointer, features.length)
69
+ strings_ptr.write_array_of_pointer(features.map { |str| FFI::MemoryPointer.from_string(str) })
70
+
71
+ Bindings.build_features_string(strings_ptr, features.length)
72
+ end
73
+
74
+ # @return [TargetMachine] TargetMachine representation of the host machine.
75
+ def self.host
76
+ @host ||= self.new(Target.host)
77
+ end
78
+
79
+ # Create a new object describing a target machine.
80
+ #
81
+ # @see Bindings._enum_reloc_model_
82
+ # @see Bindings._enum_code_model_
83
+ #
84
+ # @param [Target] target Target description.
85
+ # @param [String] mcpu Specific CPU type to target.
86
+ # @param [Array<String>, String] features Features present for this target machine.
87
+ # @param [Symbol] reloc_model Code relocation model.
88
+ # @param [Symbol] code_model Code generation model.
89
+ def initialize(target, mcpu = '', features = '', reloc_model = :default, code_model = :default)
90
+ # Just to make things easier on developers.
91
+ reloc_model = :default_rmodel if reloc_model == :default
92
+ code_model = :default_cmodel if code_model == :default
93
+
94
+ # Convert the features parameter if necessary.
95
+ features = TargetMachine.build_feature_string(features) if features.is_a?(Array)
96
+
97
+ @ptr = Bindings.create_target_machine(target, target.triple.to_s, mcpu, features, reloc_model, code_model)
98
+ end
99
+ end
100
+ end