ruby-llvm 3.5.0 → 13.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +21 -4
  3. data/ext/ruby-llvm-support/Rakefile +17 -6
  4. data/lib/llvm/analysis.rb +2 -0
  5. data/lib/llvm/analysis_ffi.rb +27 -28
  6. data/lib/llvm/config.rb +4 -4
  7. data/lib/llvm/core/bitcode.rb +12 -10
  8. data/lib/llvm/core/bitcode_ffi.rb +89 -65
  9. data/lib/llvm/core/builder.rb +4 -3
  10. data/lib/llvm/core/context.rb +3 -1
  11. data/lib/llvm/core/module.rb +2 -0
  12. data/lib/llvm/core/pass_manager.rb +6 -2
  13. data/lib/llvm/core/type.rb +9 -2
  14. data/lib/llvm/core/value.rb +154 -24
  15. data/lib/llvm/core.rb +47 -2
  16. data/lib/llvm/core_ffi.rb +3863 -3730
  17. data/lib/llvm/execution_engine.rb +39 -35
  18. data/lib/llvm/execution_engine_ffi.rb +238 -276
  19. data/lib/llvm/linker.rb +3 -14
  20. data/lib/llvm/linker_ffi.rb +22 -26
  21. data/lib/llvm/support.rb +2 -0
  22. data/lib/llvm/target.rb +11 -15
  23. data/lib/llvm/target_ffi.rb +301 -293
  24. data/lib/llvm/transforms/builder.rb +3 -1
  25. data/lib/llvm/transforms/builder_ffi.rb +57 -58
  26. data/lib/llvm/transforms/ipo.rb +3 -1
  27. data/lib/llvm/transforms/ipo_ffi.rb +59 -60
  28. data/lib/llvm/transforms/scalar.rb +12 -0
  29. data/lib/llvm/transforms/scalar_ffi.rb +199 -143
  30. data/lib/llvm/transforms/vectorize.rb +2 -0
  31. data/lib/llvm/transforms/vectorize_ffi.rb +15 -16
  32. data/lib/llvm/version.rb +5 -2
  33. data/lib/llvm.rb +2 -0
  34. data/test/array_test.rb +2 -0
  35. data/test/basic_block_test.rb +2 -1
  36. data/test/binary_operations_test.rb +2 -0
  37. data/test/bitcode_test.rb +3 -2
  38. data/test/branch_test.rb +2 -0
  39. data/test/call_test.rb +3 -1
  40. data/test/comparisons_test.rb +2 -0
  41. data/test/conversions_test.rb +2 -0
  42. data/test/double_test.rb +10 -7
  43. data/test/equality_test.rb +4 -4
  44. data/test/function_test.rb +29 -0
  45. data/test/generic_value_test.rb +3 -1
  46. data/test/instruction_test.rb +2 -2
  47. data/test/integer_test.rb +28 -0
  48. data/test/ipo_test.rb +3 -1
  49. data/test/linker_test.rb +2 -9
  50. data/test/mcjit_test.rb +11 -3
  51. data/test/memory_access_test.rb +2 -0
  52. data/test/module_test.rb +18 -1
  53. data/test/parameter_collection_test.rb +2 -0
  54. data/test/pass_manager_builder_test.rb +22 -2
  55. data/test/phi_test.rb +2 -0
  56. data/test/select_test.rb +2 -0
  57. data/test/struct_test.rb +2 -0
  58. data/test/target_test.rb +16 -20
  59. data/test/test_helper.rb +6 -1
  60. data/test/type_test.rb +47 -0
  61. data/test/vector_test.rb +2 -0
  62. metadata +105 -40
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module LLVM
2
4
  class Value
3
5
  include PointerIdentity
@@ -12,7 +14,7 @@ module LLVM
12
14
 
13
15
  # Returns the Value type. This is abstract and is overidden by its subclasses.
14
16
  def self.type
15
- raise NotImplementedError, "#{self.name}.type() is abstract."
17
+ raise NotImplementedError, "#{name}.type() is abstract."
16
18
  end
17
19
 
18
20
  def self.to_ptr
@@ -40,6 +42,10 @@ module LLVM
40
42
  C.dump_value(self)
41
43
  end
42
44
 
45
+ def to_s
46
+ C.print_value_to_string(self)
47
+ end
48
+
43
49
  # Returns whether the value is constant.
44
50
  def constant?
45
51
  case C.is_constant(self)
@@ -66,8 +72,45 @@ module LLVM
66
72
 
67
73
  # Adds attr to this value's attributes.
68
74
  def add_attribute(attr)
69
- C.add_attribute(self, attr)
75
+ fun = param_parent
76
+ return unless fun
77
+
78
+ index = param_index(fun)
79
+ return unless index
80
+
81
+ fun.add_attribute(attr, index)
70
82
  end
83
+
84
+ # Removes the given attribute from the function.
85
+ def remove_attribute(attr)
86
+ fun = param_parent
87
+ return unless fun
88
+
89
+ index = param_index(fun)
90
+ return unless index
91
+
92
+ fun.remove_attribute(attr, index)
93
+ end
94
+
95
+ private
96
+
97
+ # get function this param belongs to
98
+ # return if it is not a param
99
+ def param_parent
100
+ valueref = C.get_param_parent(self)
101
+ return if valueref.null?
102
+ fun = LLVM::Function.from_ptr(valueref)
103
+ return if fun.null?
104
+ fun
105
+ end
106
+
107
+ # get index of this param by llvm count (+1 from parametercollection)
108
+ def param_index(fun)
109
+ index = fun.params.find_index(self)
110
+ return if index.nil?
111
+ index + 1
112
+ end
113
+
71
114
  end
72
115
 
73
116
  class Argument < Value
@@ -76,7 +119,7 @@ module LLVM
76
119
  class BasicBlock < Value
77
120
  # Creates a basic block for the given function with the given name.
78
121
  def self.create(fun = nil, name = "")
79
- self.from_ptr(C.append_basic_block(fun, name))
122
+ from_ptr(C.append_basic_block(fun, name))
80
123
  end
81
124
 
82
125
  # Build the basic block with the given builder. Creates a new one if nil. Yields the builder.
@@ -110,11 +153,13 @@ module LLVM
110
153
  BasicBlock.from_ptr(ptr) unless ptr.null?
111
154
  end
112
155
 
113
- def first_instruction # deprecated
156
+ # deprecated
157
+ def first_instruction
114
158
  instructions.first
115
159
  end
116
160
 
117
- def last_instruction # deprecated
161
+ # deprecated
162
+ def last_instruction
118
163
  instructions.last
119
164
  end
120
165
 
@@ -192,7 +237,7 @@ module LLVM
192
237
  # Iterates through each operand in the collection.
193
238
  def each
194
239
  return to_enum :each unless block_given?
195
- 0.upto(size-1) { |i| yield self[i] }
240
+ 0.upto(size - 1) { |i| yield self[i] }
196
241
  self
197
242
  end
198
243
  end
@@ -444,12 +489,22 @@ module LLVM
444
489
  def int_to_ptr(type)
445
490
  ConstantExpr.from_ptr(C.const_int_to_ptr(self, type))
446
491
  end
492
+
493
+ # constant zext
494
+ def zext(type)
495
+ self.class.from_ptr(C.const_z_ext(self, type))
496
+ end
497
+
498
+ # constant sext
499
+ def sext(type)
500
+ self.class.from_ptr(C.const_s_ext(self, type))
501
+ end
447
502
  end
448
503
 
449
- def LLVM.const_missing(const)
504
+ def self.const_missing(const)
450
505
  case const.to_s
451
506
  when /Int(\d+)/
452
- width = $1.to_i
507
+ width = Regexp.last_match(1).to_i
453
508
  name = "Int#{width}"
454
509
  eval <<-KLASS
455
510
  class #{name} < ConstantInt
@@ -469,7 +524,7 @@ module LLVM
469
524
  ::LLVM::Int = const_get("Int#{bits}")
470
525
 
471
526
  # Creates a LLVM Int (subclass of ConstantInt) at the NATIVE_INT_SIZE from a integer (val).
472
- def LLVM.Int(val)
527
+ def self.Int(val)
473
528
  case val
474
529
  when LLVM::ConstantInt then val
475
530
  when Integer then Int.from_i(val)
@@ -550,7 +605,7 @@ module LLVM
550
605
  end
551
606
 
552
607
  # Create a LLVM::Float from a Ruby Float (val).
553
- def LLVM.Float(val)
608
+ def self.Float(val)
554
609
  Float.from_f(val)
555
610
  end
556
611
 
@@ -560,7 +615,7 @@ module LLVM
560
615
  end
561
616
  end
562
617
 
563
- def LLVM.Double(val)
618
+ def self.Double(val)
564
619
  Double.from_f(val)
565
620
  end
566
621
 
@@ -675,16 +730,6 @@ module LLVM
675
730
  conv
676
731
  end
677
732
 
678
- # Adds the given attribute to the function.
679
- def add_attribute(attr)
680
- C.add_function_attr(self, attr)
681
- end
682
-
683
- # Removes the given attribute from the function.
684
- def remove_attribute(attr)
685
- C.remove_function_attr(self, attr)
686
- end
687
-
688
733
  # Returns an Enumerable of the BasicBlocks in this function.
689
734
  def basic_blocks
690
735
  @basic_block_collection ||= BasicBlockCollection.new(self)
@@ -698,6 +743,90 @@ module LLVM
698
743
  type.element_type
699
744
  end
700
745
 
746
+ # Adds attr to this value's attributes.
747
+ def add_attribute(attr, index = -1)
748
+ AttributeCollection.new(self, index).add(attr)
749
+ end
750
+
751
+ # Removes the given attribute from the function.
752
+ def remove_attribute(attr, index = -1)
753
+ AttributeCollection.new(self, index).remove(attr)
754
+ end
755
+
756
+ def attribute_count
757
+ function_attributes.count
758
+ end
759
+
760
+ def attributes
761
+ function_attributes.to_a
762
+ end
763
+
764
+ def function_attributes
765
+ AttributeCollection.new(self, -1)
766
+ end
767
+
768
+ def return_attributes
769
+ AttributeCollection.new(self, 0)
770
+ end
771
+
772
+ def param_attributes(index)
773
+ AttributeCollection.new(self, index)
774
+ end
775
+
776
+ class AttributeCollection
777
+
778
+ def initialize(fun, index)
779
+ @fun = fun
780
+ @index = index
781
+ end
782
+
783
+ def add(attr)
784
+ attr_kind_id = attribute_id(attr)
785
+ ctx = Context.global
786
+ attr_ref = C.create_enum_attribute(ctx, attr_kind_id, 0)
787
+ C.add_attribute_at_index(@fun, @index, attr_ref)
788
+ end
789
+
790
+ def remove(attr)
791
+ attr_kind_id = attribute_id(attr)
792
+ C.remove_enum_attribute_at_index(@fun, @index, attr_kind_id)
793
+ end
794
+
795
+ def count
796
+ C.get_attribute_count_at_index(@fun, @index)
797
+ end
798
+
799
+ def to_a
800
+ attr_refs = nil
801
+ n = count
802
+ FFI::MemoryPointer.new(:pointer, n) do |p|
803
+ C.get_attributes_at_index(@fun, @index, p)
804
+ attr_refs = p.read_array_of_type(:pointer, :read_pointer, n)
805
+ end
806
+
807
+ attr_refs.map { |e| C.get_enum_attribute_kind(e) }
808
+ end
809
+
810
+ private
811
+
812
+ def attribute_name(attr_name)
813
+ attr_name = attr_name.to_s
814
+ if attr_name =~ /_attribute$/
815
+ attr_name.chomp('_attribute').tr('_', '')
816
+ else
817
+ attr_name
818
+ end
819
+ end
820
+
821
+ def attribute_id(attr_name)
822
+ attr_mem = FFI::MemoryPointer.from_string(attribute_name(attr_name))
823
+ attr_kind_id = C.get_enum_attribute_kind_for_name(attr_mem, attr_mem.size - 1)
824
+
825
+ raise "No attribute named: #{attr_name}" if attr_kind_id.zero?
826
+ attr_kind_id
827
+ end
828
+ end
829
+
701
830
  # @private
702
831
  class BasicBlockCollection
703
832
  include Enumerable
@@ -716,7 +845,7 @@ module LLVM
716
845
  return to_enum :each unless block_given?
717
846
 
718
847
  ptr = C.get_first_basic_block(@fun)
719
- 0.upto(size-1) do |i|
848
+ 0.upto(size - 1) do |i|
720
849
  yield BasicBlock.from_ptr(ptr)
721
850
  ptr = C.get_next_basic_block(ptr)
722
851
  end
@@ -761,7 +890,7 @@ module LLVM
761
890
 
762
891
  # Returns a Value representation of the parameter at the given index.
763
892
  def [](i)
764
- sz = self.size
893
+ sz = size
765
894
  i = sz + i if i < 0
766
895
  return unless 0 <= i && i < sz
767
896
  Value.from_ptr(C.get_param(@fun, i))
@@ -777,7 +906,7 @@ module LLVM
777
906
  # Iteraters through each parameter in the collection.
778
907
  def each
779
908
  return to_enum :each unless block_given?
780
- 0.upto(size-1) { |i| yield self[i] }
909
+ 0.upto(size - 1) { |i| yield self[i] }
781
910
  self
782
911
  end
783
912
  end
@@ -785,6 +914,7 @@ module LLVM
785
914
  def gc=(name)
786
915
  C.set_gc(self, name)
787
916
  end
917
+
788
918
  def gc
789
919
  C.get_gc(self)
790
920
  end
data/lib/llvm/core.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'llvm'
2
4
  require 'llvm/core_ffi'
3
5
  require 'llvm/support'
@@ -6,6 +8,49 @@ module LLVM
6
8
  # @private
7
9
  module C
8
10
  attach_function :dispose_message, :LLVMDisposeMessage, [:pointer], :void
11
+
12
+ # typedef unsigned LLVMAttributeIndex;
13
+ typedef(:uint, :llvmattributeindex)
14
+
15
+ # void LLVMAddAttributeAtIndex
16
+ # (LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef A);
17
+ attach_function :add_attribute_at_index, :LLVMAddAttributeAtIndex, [:pointer, :llvmattributeindex, :pointer], :void
18
+
19
+ # void LLVMRemoveEnumAttributeAtIndex
20
+ # (LLVMValueRef F, LLVMAttributeIndex Idx, unsigned KindID);
21
+ attach_function :remove_enum_attribute_at_index, :LLVMRemoveEnumAttributeAtIndex, [:pointer, :llvmattributeindex, :uint], :void
22
+
23
+ # LLVMAttributeRef LLVMCreateEnumAttribute
24
+ # (LLVMContextRef C, unsigned KindID, uint64_t Val);
25
+ attach_function :create_enum_attribute, :LLVMCreateEnumAttribute, [:pointer, :uint, :uint64], :pointer
26
+
27
+ # unsigned LLVMGetEnumAttributeKindForName
28
+ # (const char *Name, size_t SLen);
29
+ attach_function :get_enum_attribute_kind_for_name, :LLVMGetEnumAttributeKindForName, [:pointer, :size_t], :uint
30
+
31
+ # unsigned LLVMGetAttributeCountAtIndex
32
+ # (LLVMValueRef F, LLVMAttributeIndex Idx);
33
+ attach_function :get_attribute_count_at_index, :LLVMGetAttributeCountAtIndex, [:pointer, :llvmattributeindex], :uint
34
+
35
+ # void LLVMGetAttributesAtIndex
36
+ # (LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef *Attrs);
37
+ attach_function :get_attributes_at_index, :LLVMGetAttributesAtIndex, [:pointer, :llvmattributeindex, :pointer], :void
38
+
39
+ # unsigned LLVMGetEnumAttributeKind
40
+ # (LLVMAttributeRef A);
41
+ attach_function :get_enum_attribute_kind, :LLVMGetEnumAttributeKind, [:pointer], :uint
42
+
43
+ # uint64_t LLVMGetEnumAttributeValue
44
+ # (LLVMAttributeRef A);
45
+ attach_function :get_enum_attribute_value, :LLVMGetEnumAttributeKind, [:pointer], :uint64
46
+
47
+ # const char *LLVMGetStringAttributeKind
48
+ # (LLVMAttributeRef A, unsigned *Length);
49
+ attach_function :get_string_attribute_kind, :LLVMGetStringAttributeKind, [:pointer, :pointer], :pointer
50
+
51
+ # const char *LLVMGetStringAttributeValue
52
+ # (LLVMAttributeRef A, unsigned *Length);
53
+ attach_function :get_string_attribute_value, :LLVMGetStringAttributeValue, [:pointer, :pointer], :pointer
9
54
  end
10
55
 
11
56
  # Yields a pointer suitable for storing an LLVM output message.
@@ -23,7 +68,7 @@ module LLVM
23
68
  msg_ptr = str.read_pointer
24
69
 
25
70
  if result != 0
26
- raise RuntimeError, "Error is signalled, but msg_ptr is null" if msg_ptr.null?
71
+ raise "Error is signalled, but msg_ptr is null" if msg_ptr.null?
27
72
 
28
73
  message = msg_ptr.read_string
29
74
  C.dispose_message msg_ptr
@@ -41,7 +86,7 @@ module LLVM
41
86
  def self.with_error_output(&block)
42
87
  error = with_message_output(&block)
43
88
 
44
- raise RuntimeError, error unless error.nil?
89
+ raise error unless error.nil?
45
90
  end
46
91
 
47
92
  require 'llvm/core/context'