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.
- 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'
|