-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
type.cr
134 lines (107 loc) · 2.97 KB
/
type.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
struct LLVM::Type
getter unwrap : LibLLVM::TypeRef
def initialize(@unwrap : LibLLVM::TypeRef)
end
def to_unsafe
@unwrap
end
def self.void : self
new LibLLVM.void_type
end
def self.int(bits) : self
new LibLLVM.int_type(bits)
end
def self.float : self
new LibLLVM.float_type
end
def self.double : self
new LibLLVM.double_type
end
def self.pointer(element_type) : self
new LibLLVM.pointer_type(element_type, 0)
end
def self.array(element_type, count) : self
new LibLLVM.array_type(element_type, count)
end
def self.vector(element_type, count) : self
new LibLLVM.vector_type(element_type, count)
end
def self.struct(name : String, packed = false) : self
llvm_struct = LibLLVM.struct_create_named(Context.global, name)
the_struct = new llvm_struct
element_types = (yield the_struct).as(Array(LLVM::Type))
LibLLVM.struct_set_body(llvm_struct, (element_types.to_unsafe.as(LibLLVM::TypeRef*)), element_types.size, packed ? 1 : 0)
the_struct
end
def self.struct(element_types : Array(LLVM::Type), name = nil, packed = false) : self
if name
self.struct(name, packed) { element_types }
else
new LibLLVM.struct_type((element_types.to_unsafe.as(LibLLVM::TypeRef*)), element_types.size, packed ? 1 : 0)
end
end
def self.function(arg_types : Array(LLVM::Type), return_type, varargs = false) : self
new LibLLVM.function_type(return_type, (arg_types.to_unsafe.as(LibLLVM::TypeRef*)), arg_types.size, varargs ? 1 : 0)
end
def size
# Asking the size of void crashes the program, we definitely don't want that
if void?
LLVM.int(LLVM::Int64, 1)
else
Value.new LibLLVM.size_of(self)
end
end
def kind
LibLLVM.get_type_kind(self)
end
def void?
kind == Kind::Void
end
def null
Value.new LibLLVM.const_null(self)
end
def null_pointer
Value.new LibLLVM.const_pointer_null(self)
end
def undef
Value.new LibLLVM.get_undef(self)
end
def pointer
Type.pointer self
end
def array(count)
Type.array self, count
end
def int_width
raise "not an Integer" unless kind == Kind::Integer
LibLLVM.get_int_type_width(self).to_i32
end
def packed_struct?
raise "not a Struct" unless kind == Kind::Struct
LibLLVM.is_packed_struct(self) != 0
end
def struct_element_types
raise "not a Struct" unless kind == Kind::Struct
count = LibLLVM.count_struct_element_types(self)
Array(LLVM::Type).build(count) do |buffer|
LibLLVM.get_struct_element_types(self, buffer.as(LibLLVM::TypeRef*))
count
end
end
def element_type
case kind
when Kind::Array, Kind::Vector, Kind::Pointer
Type.new LibLLVM.get_element_type(self)
else
raise "not a sequential type"
end
end
def array_size
raise "not an Array" unless kind == Kind::Array
LibLLVM.get_array_length(self).to_i32
end
def inspect(io)
LLVM.to_io(LibLLVM.print_type_to_string(self), io)
self
end
end