ruby-llvm 3.1.0.beta.1 → 3.2.0.beta.1

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.
Files changed (53) hide show
  1. data/LICENSE +30 -0
  2. data/README.md +49 -0
  3. data/ext/ruby-llvm-support/Rakefile +30 -7
  4. data/ext/ruby-llvm-support/support.cpp +48 -1
  5. data/lib/llvm.rb +26 -3
  6. data/lib/llvm/analysis.rb +8 -11
  7. data/lib/llvm/analysis_ffi.rb +1 -1
  8. data/lib/llvm/core.rb +36 -1
  9. data/lib/llvm/core/bitcode_ffi.rb +1 -1
  10. data/lib/llvm/core/builder.rb +20 -14
  11. data/lib/llvm/core/module.rb +87 -63
  12. data/lib/llvm/core/pass_manager.rb +30 -30
  13. data/lib/llvm/core/type.rb +34 -51
  14. data/lib/llvm/core/value.rb +13 -25
  15. data/lib/llvm/core_ffi.rb +62 -21
  16. data/lib/llvm/execution_engine.rb +13 -19
  17. data/lib/llvm/execution_engine_ffi.rb +1 -1
  18. data/lib/llvm/linker.rb +35 -0
  19. data/lib/llvm/linker_ffi.rb +45 -0
  20. data/lib/llvm/support.rb +32 -6
  21. data/lib/llvm/target.rb +318 -1
  22. data/lib/llvm/target_ffi.rb +302 -14
  23. data/lib/llvm/transforms/ipo_ffi.rb +1 -1
  24. data/lib/llvm/transforms/scalar_ffi.rb +1 -1
  25. data/lib/llvm/transforms/vectorize.rb +17 -0
  26. data/lib/llvm/transforms/vectorize_ffi.rb +31 -0
  27. data/lib/llvm/version.rb +21 -2
  28. data/test/array_test.rb +1 -1
  29. data/test/basic_block_test.rb +1 -1
  30. data/test/basic_test.rb +1 -1
  31. data/test/binary_operations_test.rb +1 -1
  32. data/test/bitcode_test.rb +2 -2
  33. data/test/branch_test.rb +1 -1
  34. data/test/call_test.rb +1 -1
  35. data/test/comparisons_test.rb +1 -1
  36. data/test/conversions_test.rb +1 -1
  37. data/test/double_test.rb +2 -2
  38. data/test/equality_test.rb +5 -5
  39. data/test/generic_value_test.rb +1 -1
  40. data/test/instruction_test.rb +1 -1
  41. data/test/ipo_test.rb +1 -1
  42. data/test/linker_test.rb +46 -0
  43. data/test/memory_access_test.rb +1 -1
  44. data/test/module_test.rb +50 -1
  45. data/test/phi_test.rb +1 -1
  46. data/test/select_test.rb +1 -1
  47. data/test/struct_test.rb +3 -3
  48. data/test/target_test.rb +124 -0
  49. data/test/test_helper.rb +10 -1
  50. data/test/type_test.rb +1 -1
  51. data/test/vector_test.rb +1 -1
  52. metadata +33 -22
  53. data/README.rdoc +0 -34
data/LICENSE ADDED
@@ -0,0 +1,30 @@
1
+ Copyright (c) 2010-2011 Jeremy Voorhis
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the author nor the names of his contributors
17
+ may be used to endorse or promote products derived from this software
18
+ without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
24
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,49 @@
1
+ Ruby-LLVM
2
+ =========
3
+
4
+ Ruby-LLVM is a Ruby language binding to the LLVM compiler infrastructure
5
+ library. LLVM allows users to create just-in-time (JIT) compilers, ahead-of-time
6
+ (AOT) compilers for multiple architectures, code analyzers and more. LLVM
7
+ bindings can also be used to speed up Ruby code by compiling Ruby methods on the
8
+ fly.
9
+
10
+ Requirements
11
+ ------------
12
+ * LLVM 3.2, including libLLVM-3.2 (compile LLVM with --enable-shared).
13
+ * In order to ensure the usability of JIT features (i.e. create_jit_compiler), compile LLVM with --enable-jit as well.
14
+
15
+ About version numbers
16
+ ---------------------
17
+
18
+ The first two digits of ruby-llvm's version number refer to the required
19
+ major and minor version of LLVM. The third digit refers to the ruby-llvm
20
+ release itself. Because LLVM's api changes often, this coupling between
21
+ LLVM and ruby-llvm versions is useful.
22
+
23
+ Homebrew
24
+ --------
25
+ LLVM can be installed with Homebrew by executing `brew install llvm --shared`
26
+
27
+ See Also
28
+ --------
29
+ * [The LLVM project](http://llvm.org)
30
+ * [ffi-gen](https://github.com/neelance/ffi-gen) – Generate
31
+ [FFI](https://github.com/ffi/ffi) bindings with LLVM and Clang
32
+
33
+ License
34
+ -------
35
+ Ruby-LLVM is available under the BSD 3-clause (see LICENSE), Copyright (c) 2010-2013 Jeremy Voorhis
36
+
37
+ Ruby-LLVM is possible because of its contributors:
38
+
39
+ * Evan Phoenix
40
+ * David Holroyd
41
+ * Takanori Ishikawa
42
+ * Ronaldo M. Ferraz
43
+ * Mac Malone
44
+ * Chris Wailes
45
+ * Ary Borenszweig
46
+ * Richard Musiol
47
+ * Juan Wajnerman
48
+ * Steven Farlie
49
+ * Peter Zotov
@@ -2,12 +2,35 @@ require 'rake/clean'
2
2
  require 'rubygems'
3
3
  require 'ffi'
4
4
 
5
- CC = "g++"
6
- LLVM_CONFIG = `llvm-config --cxxflags --ldflags --libs all`.gsub("\n"," ")
7
- OUTPUT = FFI.map_library_name "RubyLLVMSupport-3.1.0"
8
- OUTPUT_DIR = "../../lib"
9
- SRC = "support.cpp"
10
- CLOBBER.include(OUTPUT)
5
+ # Change this when updating for a newer LLVM.
6
+ LLVM_VERSION = '3.2'
7
+
8
+ def check_llvm_config(name)
9
+ actual_version = `#{name} --version`
10
+ actual_version.strip == LLVM_VERSION
11
+ rescue Errno::ENOENT
12
+ false
13
+ end
14
+
15
+ def invoke_llvm_config(options)
16
+ variants = %W(llvm-config-#{LLVM_VERSION} llvm-config)
17
+
18
+ variants.each do |name|
19
+ if check_llvm_config(name)
20
+ return `#{name} #{options}`.gsub("\n", " ")
21
+ end
22
+ end
23
+
24
+ raise RuntimeError, "No valid llvm-config found. Tried: #{variants}"
25
+ end
26
+
27
+ LLVM_CONFIG = invoke_llvm_config('--cxxflags --ldflags')
28
+
29
+ CXX = "g++"
30
+ SRC = "support.cpp"
31
+ OUTPUT = FFI.map_library_name("RubyLLVMSupport-#{LLVM_VERSION}")
32
+
33
+ CLEAN.include(OUTPUT)
11
34
 
12
35
  task :default => [:build]
13
36
 
@@ -15,5 +38,5 @@ desc "Build the shared library"
15
38
  task :build => [OUTPUT]
16
39
 
17
40
  file OUTPUT => [SRC] do
18
- sh "#{CC} -shared #{SRC} #{LLVM_CONFIG} -o #{OUTPUT_DIR}/#{OUTPUT}"
41
+ sh "#{CXX} -shared -lLLVM-#{LLVM_VERSION} #{SRC} #{LLVM_CONFIG} -o #{OUTPUT}"
19
42
  end
@@ -2,12 +2,59 @@
2
2
  * Extended bindings for LLVM.
3
3
  */
4
4
 
5
- #include <llvm/ADT/StringRef.h>
5
+ #include <llvm-c/Core.h>
6
+ #include <llvm/Type.h>
7
+ #include <llvm/GlobalValue.h>
6
8
  #include <llvm/Support/DynamicLibrary.h>
9
+ #include <llvm/Support/TargetSelect.h>
10
+ #include <llvm/Support/raw_ostream.h>
7
11
 
8
12
  extern "C" {
13
+ using namespace llvm;
14
+
9
15
  int LLVMLoadLibraryPermanently(const char* filename) {
10
16
  return llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename);
11
17
  }
18
+
19
+ LLVMBool LLVMHasUnnamedAddr(LLVMValueRef global) {
20
+ return unwrap<GlobalValue>(global)->hasUnnamedAddr();
21
+ }
22
+
23
+ void LLVMSetUnnamedAddr(LLVMValueRef global, LLVMBool val) {
24
+ unwrap<GlobalValue>(global)->setUnnamedAddr(val != 0);
25
+ }
26
+
27
+ void LLVMDumpType(LLVMTypeRef type) {
28
+ unwrap<Type>(type)->dump();
29
+ }
30
+
31
+ int LLVMPrintModuleToFD(LLVMModuleRef module, int fd, LLVMBool shouldClose, LLVMBool unbuffered) {
32
+ raw_fd_ostream os(fd, shouldClose, unbuffered);
33
+ unwrap(module)->print(os, 0);
34
+ }
35
+
36
+ void LLVMInitializeAllTargetInfos() {
37
+ llvm::InitializeAllTargetInfos();
38
+ }
39
+
40
+ void LLVMInitializeAllTargets() {
41
+ llvm::InitializeAllTargets();
42
+ }
43
+
44
+ void LLVMInitializeAllTargetMCs() {
45
+ llvm::InitializeAllTargetMCs();
46
+ }
47
+
48
+ void LLVMInitializeAllAsmPrinters() {
49
+ llvm::InitializeAllAsmPrinters();
50
+ }
51
+
52
+ void LLVMInitializeNativeTarget() {
53
+ llvm::InitializeNativeTarget();
54
+ }
55
+
56
+ void LLVMInitializeNativeTargetAsmPrinter() {
57
+ llvm::InitializeNativeTargetAsmPrinter();
58
+ }
12
59
  }
13
60
 
@@ -1,12 +1,35 @@
1
1
  require 'rubygems'
2
2
  require 'ffi'
3
3
 
4
- require 'llvm/support'
5
-
6
4
  module LLVM
5
+ require 'llvm/support'
6
+
7
7
  # @private
8
8
  module C
9
9
  extend ::FFI::Library
10
- ffi_lib ['LLVM-3.1']
10
+ ffi_lib ['LLVM-3.2']
11
+ end
12
+
13
+ module PointerIdentity
14
+ # @private
15
+ def to_ptr
16
+ @ptr
17
+ end
18
+
19
+ # Checks if the value is equal to other.
20
+ def ==(other)
21
+ other.respond_to?(:to_ptr) &&
22
+ @ptr == other.to_ptr
23
+ end
24
+
25
+ # Computes hash.
26
+ def hash
27
+ @ptr.address.hash
28
+ end
29
+
30
+ # Checks if the value is equivalent to other.
31
+ def eql?(other)
32
+ self == other
33
+ end
11
34
  end
12
35
  end
@@ -11,25 +11,22 @@ module LLVM
11
11
  def verify
12
12
  do_verification(:return_status)
13
13
  end
14
-
14
+
15
15
  # Verify that a module is valid, and abort the process if not.
16
16
  # @return [nil]
17
17
  def verify!
18
18
  do_verification(:abort_process)
19
19
  end
20
-
20
+
21
21
  private
22
- def do_verification(action)
23
- result = nil
24
- FFI::MemoryPointer.new(FFI.type_size(:pointer)) do |str|
25
- status = C.verify_module(self, action, str)
26
- result = str.read_string if status == 1
27
- C.dispose_message str.read_pointer
28
- end
29
- result
22
+
23
+ def do_verification(action)
24
+ LLVM.with_message_output do |str|
25
+ C.verify_module(self, action, str)
30
26
  end
27
+ end
31
28
  end
32
-
29
+
33
30
  class Function
34
31
  # Verify that a function is valid.
35
32
  # @return [true, false]
@@ -4,7 +4,7 @@ require 'ffi'
4
4
 
5
5
  module LLVM::C
6
6
  extend FFI::Library
7
- ffi_lib 'LLVM-3.1'
7
+ ffi_lib 'LLVM-3.2'
8
8
 
9
9
  def self.attach_function(name, *_)
10
10
  begin; super; rescue FFI::NotFoundError => e
@@ -1,12 +1,47 @@
1
1
  require 'llvm'
2
2
  require 'llvm/core_ffi'
3
+ require 'llvm/support'
3
4
 
4
5
  module LLVM
5
6
  # @private
6
7
  module C
7
8
  attach_function :dispose_message, :LLVMDisposeMessage, [:pointer], :void
8
9
  end
9
-
10
+
11
+ # Yields a pointer suitable for storing an LLVM output message.
12
+ # If the message pointer is non-NULL (an error has happened), converts
13
+ # the result to a string and returns it. Otherwise, returns +nil+.
14
+ #
15
+ # @yield [FFI::MemoryPointer]
16
+ # @return [String, nil]
17
+ def self.with_message_output
18
+ result = nil
19
+
20
+ FFI::MemoryPointer.new(FFI.type_size(:pointer)) do |str|
21
+ yield str
22
+
23
+ msg_ptr = str.read_pointer
24
+
25
+ unless msg_ptr.null?
26
+ result = msg_ptr.read_string
27
+ C.dispose_message msg_ptr
28
+ end
29
+ end
30
+
31
+ result
32
+ end
33
+
34
+ # Same as #with_message_output, but raises a RuntimeError with the
35
+ # resulting message.
36
+ #
37
+ # @yield [FFI::MemoryPointer]
38
+ # @return [nil]
39
+ def self.with_error_output(&block)
40
+ error = with_message_output(&block)
41
+
42
+ raise RuntimeError, error unless error.nil?
43
+ end
44
+
10
45
  require 'llvm/core/context'
11
46
  require 'llvm/core/module'
12
47
  require 'llvm/core/type'
@@ -4,7 +4,7 @@ require 'ffi'
4
4
 
5
5
  module LLVM::C
6
6
  extend FFI::Library
7
- ffi_lib 'LLVM-3.1'
7
+ ffi_lib 'LLVM-3.2'
8
8
 
9
9
  def self.attach_function(name, *_)
10
10
  begin; super; rescue FFI::NotFoundError => e
@@ -4,7 +4,7 @@ module LLVM
4
4
  def initialize
5
5
  @ptr = C.create_builder()
6
6
  end
7
-
7
+
8
8
  def dispose
9
9
  return if @ptr.nil?
10
10
  C.dispose_builder(@ptr)
@@ -17,8 +17,9 @@ module LLVM
17
17
  end
18
18
 
19
19
  # Position the builder at the given Instruction within the given BasicBlock.
20
- # @param [LLVM::BasicBlock]
21
- # @param [LLVM::Instruction]
20
+ #
21
+ # @param [LLVM::BasicBlock] block
22
+ # @param [LLVM::Instruction] instruction
22
23
  # @return [LLVM::Builder]
23
24
  def position(block, instruction)
24
25
  raise "Block must not be nil" if block.nil?
@@ -27,7 +28,8 @@ module LLVM
27
28
  end
28
29
 
29
30
  # Positions the builder before the given Instruction.
30
- # @param [LLVM::Instruction]
31
+ #
32
+ # @param [LLVM::Instruction] instruction
31
33
  # @return [LLVM::Builder]
32
34
  def position_before(instruction)
33
35
  raise "Instruction must not be nil" if instruction.nil?
@@ -36,7 +38,8 @@ module LLVM
36
38
  end
37
39
 
38
40
  # Positions the builder at the end of the given BasicBlock.
39
- # @param [LLVM::BasicBlock]
41
+ #
42
+ # @param [LLVM::BasicBlock] block
40
43
  # @return [LLVM::Builder]
41
44
  def position_at_end(block)
42
45
  raise "Block must not be nil" if block.nil?
@@ -45,6 +48,7 @@ module LLVM
45
48
  end
46
49
 
47
50
  # The BasicBlock at which the Builder is currently positioned.
51
+ #
48
52
  # @return [LLVM::BasicBlock]
49
53
  def insert_block
50
54
  BasicBlock.from_ptr(C.get_insert_block(self))
@@ -434,7 +438,7 @@ module LLVM
434
438
  end
435
439
 
436
440
  # Builds a inbounds getelementptr instruction. If the indices are outside
437
- # the allocated pointer the value is undefined.
441
+ # the allocated pointer the value is undefined.
438
442
  # @param [LLVM::Value] ptr A pointer to an aggregate value
439
443
  # @param [Array<LLVM::Value>] indices Ruby array of LLVM::Value representing
440
444
  # indices into the aggregate
@@ -452,11 +456,12 @@ module LLVM
452
456
  end
453
457
 
454
458
  # Builds a struct getelementptr Instruction.
455
- # @param [LLVM::Value] ptr A pointer to a structure
456
- # @param [LLVM::Value] idx Unsigned integer representing the index of a
459
+ #
460
+ # @param [LLVM::Value] pointer A pointer to a structure
461
+ # @param [LLVM::Value] idx Unsigned integer representing the index of a
457
462
  # structure member
458
- # @param [String] name The name of the result in LLVM IR
459
- # @return [LLVM::Instruction] The resulting pointer
463
+ # @param [String] name The name of the result in LLVM IR
464
+ # @return [LLVM::Instruction] The resulting pointer
460
465
  # @LLVMinst gep
461
466
  # @see http://llvm.org/docs/GetElementPtr.html
462
467
  def struct_gep(pointer, idx, name = "")
@@ -484,7 +489,7 @@ module LLVM
484
489
  # @param [LLVM::Value] val Integer or vector of integers to be truncated
485
490
  # @param [LLVM::Type, #type] ty Integer or vector of integers of equal size
486
491
  # to val
487
- # @param [String] name The name of the result in LLVM IR
492
+ # @param [String] name The name of the result in LLVM IR
488
493
  # @return [LLVM::Instruction] The truncated value
489
494
  # @LLVMinst trunc
490
495
  def trunc(val, ty, name = "")
@@ -496,7 +501,7 @@ module LLVM
496
501
  # @param [LLVM::Value] val Integer or vector of integers to be extended
497
502
  # @param [LLVM::Type, #type] ty Integer or vector of integer type of
498
503
  # greater size than val
499
- # @param [String] name The name of the result in LLVM IR
504
+ # @param [String] name The name of the result in LLVM IR
500
505
  # @return [LLVM::Instruction] The extended value
501
506
  # @LLVMinst zext
502
507
  def zext(val, ty, name = "")
@@ -508,7 +513,7 @@ module LLVM
508
513
  # @param [LLVM::Value] val Integer or vector of integers to be extended
509
514
  # @param [LLVM::Type] ty Integer or vector of integer type of greater size
510
515
  # than the size of val
511
- # @param [String] name The name of the result in LLVM IR
516
+ # @param [String] name The name of the result in LLVM IR
512
517
  # @return [LLVM::Instruction] The extended value
513
518
  # @LLVMinst sext
514
519
  def sext(val, ty, name = "")
@@ -741,7 +746,8 @@ module LLVM
741
746
 
742
747
  # Builds a call Instruction. Calls the given Function with the given
743
748
  # args (Instructions).
744
- # @param [LLVM::Function] fun
749
+ #
750
+ # @param [LLVM::Function] fun
745
751
  # @param [Array<LLVM::Value>] args
746
752
  # @param [LLVM::Instruction]
747
753
  # @LLVMinst call
@@ -1,5 +1,7 @@
1
- module LLVM
1
+ module LLVM
2
2
  class Module
3
+ include PointerIdentity
4
+
3
5
  # @private
4
6
  def self.from_ptr(ptr)
5
7
  return if ptr.null?
@@ -7,111 +9,113 @@ module LLVM
7
9
  mod.instance_variable_set(:@ptr, ptr)
8
10
  mod
9
11
  end
10
-
12
+
11
13
  # Important: Call #dispose to free backend memory after use, but not when using JITCompiler with this module.
12
14
  def initialize(name)
13
15
  @ptr = C.module_create_with_name(name)
14
16
  end
15
-
17
+
16
18
  def dispose
17
19
  return if @ptr.nil?
18
20
  C.dispose_module(@ptr)
19
21
  @ptr = nil
20
22
  end
21
-
22
- # @private
23
- def to_ptr
24
- @ptr
23
+
24
+ # Get module triple.
25
+ #
26
+ # @return [String]
27
+ def triple
28
+ C.get_target(self)
25
29
  end
26
-
27
- # Checks if the module is equal to other.
28
- def ==(other)
29
- case other
30
- when LLVM::Module
31
- @ptr == other.to_ptr
32
- else
33
- false
34
- end
30
+
31
+ # Set module triple.
32
+ #
33
+ # @param [String] triple
34
+ def triple=(triple)
35
+ C.set_target(self, triple.to_s)
36
+ end
37
+
38
+ # Get module data layout.
39
+ #
40
+ # @return [String]
41
+ def data_layout
42
+ C.get_data_layout(self)
35
43
  end
36
44
 
37
- # Checks if the module is equal to other.
38
- def eql?(other)
39
- other.instance_of?(self.class) && self == other
45
+ # Set module data layout.
46
+ #
47
+ # @param [String, TargetDataLayout] data_layout
48
+ def data_layout=(data_layout)
49
+ C.set_data_layout(self, data_layout.to_s)
40
50
  end
41
51
 
42
52
  # Returns a TypeCollection of all the Types in the module.
43
53
  def types
44
54
  @types ||= TypeCollection.new(self)
45
55
  end
46
-
56
+
47
57
  class TypeCollection
48
58
  def initialize(mod)
49
59
  @module = mod
50
60
  end
51
-
61
+
52
62
  # Returns the Type with the given name (symbol or string).
53
63
  def named(name)
54
64
  Type.from_ptr(C.get_type_by_name(@module, name.to_s), nil)
55
65
  end
56
-
57
- # Returns the Type with the a name equal to key (symbol or string).
58
- def [](key)
59
- named(key)
60
- end
61
-
62
- # Adds the given Type to the collection with a name equal to key (symbol or string).
63
- def []=(key, type)
64
- add(key, type)
65
- end
66
+
67
+ alias [] named
66
68
  end
67
-
69
+
68
70
  # Returns an Enumerable of all the GlobalVariables in the module.
69
71
  def globals
70
72
  @globals ||= GlobalCollection.new(self)
71
73
  end
72
-
74
+
73
75
  class GlobalCollection
74
76
  include Enumerable
75
-
77
+
76
78
  def initialize(mod)
77
79
  @module = mod
78
80
  end
79
-
81
+
80
82
  # Adds a GlobalVariable with the given type and name to the collection (symbol or string).
81
83
  def add(ty, name)
82
- GlobalVariable.from_ptr(C.add_global(@module, LLVM::Type(ty), name.to_s))
84
+ GlobalVariable.from_ptr(C.add_global(@module, LLVM::Type(ty), name.to_s)).tap do |gvar|
85
+ yield gvar if block_given?
86
+ end
83
87
  end
84
-
88
+
85
89
  # Returns the GlobalVariable with the given name (symbol or string).
86
90
  def named(name)
87
91
  GlobalValue.from_ptr(C.get_named_global(@module, name.to_s))
88
92
  end
89
-
93
+
90
94
  # Returns the first GlobalVariable in the collection.
91
95
  def first
92
96
  GlobalValue.from_ptr(C.get_first_global(@module))
93
97
  end
94
-
98
+
95
99
  # Returns the last GlobalVariable in the collection.
96
100
  def last
97
101
  GlobalValue.from_ptr(C.get_last_global(@module))
98
102
  end
99
-
103
+
100
104
  # Returns the next GlobalVariable in the collection after global.
101
105
  def next(global)
102
106
  GlobalValue.from_ptr(C.get_next_global(global))
103
107
  end
104
-
108
+
105
109
  # Returns the previous GlobalVariable in the collection before global.
106
110
  def previous(global)
107
111
  GlobalValue.from_ptr(C.get_previous_global(global))
108
112
  end
109
-
113
+
110
114
  # Deletes the GlobalVariable from the collection.
111
115
  def delete(global)
112
116
  C.delete_global(global)
113
117
  end
114
-
118
+
115
119
  # Returns the GlobalVariable with a name equal to key (symbol or string) or at key (integer).
116
120
  def [](key)
117
121
  case key
@@ -126,7 +130,7 @@ module LLVM
126
130
  g
127
131
  end
128
132
  end
129
-
133
+
130
134
  # Iterates through each GlobalVariable in the collection.
131
135
  def each
132
136
  g = first
@@ -136,19 +140,19 @@ module LLVM
136
140
  end
137
141
  end
138
142
  end
139
-
143
+
140
144
  # Returns a FunctionCollection of all the Functions in the module.
141
145
  def functions
142
146
  @functions ||= FunctionCollection.new(self)
143
147
  end
144
-
148
+
145
149
  class FunctionCollection
146
150
  include Enumerable
147
-
151
+
148
152
  def initialize(mod)
149
153
  @module = mod
150
154
  end
151
-
155
+
152
156
  # Adds a Function with the given name (symbol or string) and args (Types).
153
157
  def add(name, *args)
154
158
  if args.first.kind_of? FunctionType
@@ -157,45 +161,45 @@ module LLVM
157
161
  type = Type.function(*args)
158
162
  end
159
163
  function = Function.from_ptr(C.add_function(@module, name.to_s, type))
160
-
164
+
161
165
  if block_given?
162
166
  params = (0...function.params.size).map { |i| function.params[i] }
163
167
  yield function, *params
164
168
  end
165
-
166
- function
169
+
170
+ function
167
171
  end
168
-
172
+
169
173
  # Returns the Function with the given name (symbol or string).
170
174
  def named(name)
171
175
  Function.from_ptr(C.get_named_function(@module, name.to_s))
172
176
  end
173
-
177
+
174
178
  # Returns the first Function in the collection.
175
179
  def first
176
180
  Function.from_ptr(C.get_first_function(@module))
177
181
  end
178
-
182
+
179
183
  # Returns the last Function in the collection.
180
184
  def last
181
185
  Function.from_ptr(C.get_last_function(@module))
182
186
  end
183
-
187
+
184
188
  # Returns the next Function in the collection after function.
185
189
  def next(function)
186
190
  Function.from_ptr(C.get_next_function(function))
187
191
  end
188
-
192
+
189
193
  # Returns the previous Function in the collection before function.
190
194
  def previous(function)
191
195
  Function.from_ptr(C.get_previous_function(function))
192
196
  end
193
-
197
+
194
198
  # Deletes the Function from the collection.
195
199
  def delete(function)
196
200
  C.delete_function(function)
197
201
  end
198
-
202
+
199
203
  # Returns the Function with a name equal to key (symbol or string) or at key (integer).
200
204
  def [](key)
201
205
  case key
@@ -210,7 +214,7 @@ module LLVM
210
214
  f
211
215
  end
212
216
  end
213
-
217
+
214
218
  # Iterates through each Function in the collection.
215
219
  def each
216
220
  f = first
@@ -220,10 +224,30 @@ module LLVM
220
224
  end
221
225
  end
222
226
  end
223
-
224
- # Print the module's IR to stdout.
225
- def dump
226
- C.dump_module(self)
227
+
228
+ # Print the module's IR to the given IO object or integer file descriptor.
229
+ #
230
+ # The IO object#fileno must not be nil. If fd_or_io is nil or omitted,
231
+ # dump the module to the output stream for debugging (stderr).
232
+ def dump(fd_or_io=nil)
233
+ if fd_or_io.nil?
234
+ C.dump_module(self)
235
+ else
236
+ fd = if fd_or_io.kind_of? ::Integer
237
+ fd_or_io
238
+ elsif fd_or_io.respond_to? :fileno
239
+ fd_or_io.fileno
240
+ end
241
+
242
+ raise ArgumentError, 'Expected IO object or Integer file descriptor' if fd.nil?
243
+ Support::C.print_module(
244
+ self,
245
+ fd,
246
+ 0, # should_close=false : not be closed automatically
247
+ 0 # unbuffered=false : buffered internally
248
+ )
249
+ end
227
250
  end
251
+
228
252
  end
229
253
  end