ruby-llvm 3.5.0 → 13.0.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.
- checksums.yaml +5 -5
- data/README.md +21 -4
- data/ext/ruby-llvm-support/Rakefile +17 -6
- data/lib/llvm/analysis.rb +2 -0
- data/lib/llvm/analysis_ffi.rb +27 -28
- data/lib/llvm/config.rb +4 -4
- data/lib/llvm/core/bitcode.rb +12 -10
- data/lib/llvm/core/bitcode_ffi.rb +89 -65
- data/lib/llvm/core/builder.rb +4 -3
- data/lib/llvm/core/context.rb +3 -1
- data/lib/llvm/core/module.rb +2 -0
- data/lib/llvm/core/pass_manager.rb +6 -2
- data/lib/llvm/core/type.rb +9 -2
- data/lib/llvm/core/value.rb +154 -24
- data/lib/llvm/core.rb +47 -2
- data/lib/llvm/core_ffi.rb +3863 -3730
- data/lib/llvm/execution_engine.rb +39 -35
- data/lib/llvm/execution_engine_ffi.rb +238 -276
- data/lib/llvm/linker.rb +3 -14
- data/lib/llvm/linker_ffi.rb +22 -26
- data/lib/llvm/support.rb +2 -0
- data/lib/llvm/target.rb +11 -15
- data/lib/llvm/target_ffi.rb +301 -293
- data/lib/llvm/transforms/builder.rb +3 -1
- data/lib/llvm/transforms/builder_ffi.rb +57 -58
- data/lib/llvm/transforms/ipo.rb +3 -1
- data/lib/llvm/transforms/ipo_ffi.rb +59 -60
- data/lib/llvm/transforms/scalar.rb +12 -0
- data/lib/llvm/transforms/scalar_ffi.rb +199 -143
- data/lib/llvm/transforms/vectorize.rb +2 -0
- data/lib/llvm/transforms/vectorize_ffi.rb +15 -16
- data/lib/llvm/version.rb +5 -2
- data/lib/llvm.rb +2 -0
- data/test/array_test.rb +2 -0
- data/test/basic_block_test.rb +2 -1
- data/test/binary_operations_test.rb +2 -0
- data/test/bitcode_test.rb +3 -2
- data/test/branch_test.rb +2 -0
- data/test/call_test.rb +3 -1
- data/test/comparisons_test.rb +2 -0
- data/test/conversions_test.rb +2 -0
- data/test/double_test.rb +10 -7
- data/test/equality_test.rb +4 -4
- data/test/function_test.rb +29 -0
- data/test/generic_value_test.rb +3 -1
- data/test/instruction_test.rb +2 -2
- data/test/integer_test.rb +28 -0
- data/test/ipo_test.rb +3 -1
- data/test/linker_test.rb +2 -9
- data/test/mcjit_test.rb +11 -3
- data/test/memory_access_test.rb +2 -0
- data/test/module_test.rb +18 -1
- data/test/parameter_collection_test.rb +2 -0
- data/test/pass_manager_builder_test.rb +22 -2
- data/test/phi_test.rb +2 -0
- data/test/select_test.rb +2 -0
- data/test/struct_test.rb +2 -0
- data/test/target_test.rb +16 -20
- data/test/test_helper.rb +6 -1
- data/test/type_test.rb +47 -0
- data/test/vector_test.rb +2 -0
- metadata +105 -40
data/lib/llvm/core/value.rb
CHANGED
@@ -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, "#{
|
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
|
-
|
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
|
-
|
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
|
-
|
156
|
+
# deprecated
|
157
|
+
def first_instruction
|
114
158
|
instructions.first
|
115
159
|
end
|
116
160
|
|
117
|
-
|
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
|
504
|
+
def self.const_missing(const)
|
450
505
|
case const.to_s
|
451
506
|
when /Int(\d+)/
|
452
|
-
width =
|
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
|
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
|
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
|
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 =
|
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
|
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
|
89
|
+
raise error unless error.nil?
|
45
90
|
end
|
46
91
|
|
47
92
|
require 'llvm/core/context'
|