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

Sign up to get free protection for your applications and to get access to all the features.
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