1import itertools
2
3from llvmlite import ir
4from llvmlite import binding as llvm
5
6CallOrInvokeInstruction = ir.CallInstr
7
8
9class LLVMException(Exception):
10    pass
11
12
13_icmp_ct = itertools.count()
14
15
16def _icmp_get():
17    return next(_icmp_ct)
18
19
20ICMP_EQ = _icmp_get()
21ICMP_NE = _icmp_get()
22ICMP_SLT = _icmp_get()
23ICMP_SLE = _icmp_get()
24ICMP_SGT = _icmp_get()
25ICMP_SGE = _icmp_get()
26ICMP_ULT = _icmp_get()
27ICMP_ULE = _icmp_get()
28ICMP_UGT = _icmp_get()
29ICMP_UGE = _icmp_get()
30
31FCMP_OEQ = _icmp_get()
32FCMP_OGT = _icmp_get()
33FCMP_OGE = _icmp_get()
34FCMP_OLT = _icmp_get()
35FCMP_OLE = _icmp_get()
36FCMP_ONE = _icmp_get()
37FCMP_ORD = _icmp_get()
38
39FCMP_UEQ = _icmp_get()
40FCMP_UGT = _icmp_get()
41FCMP_UGE = _icmp_get()
42FCMP_ULT = _icmp_get()
43FCMP_ULE = _icmp_get()
44FCMP_UNE = _icmp_get()
45FCMP_UNO = _icmp_get()
46
47INTR_FABS = "llvm.fabs"
48INTR_EXP = "llvm.exp"
49INTR_LOG = "llvm.log"
50INTR_LOG10 = "llvm.log10"
51INTR_SIN = "llvm.sin"
52INTR_COS = "llvm.cos"
53INTR_POWI = 'llvm.powi'
54INTR_POW = 'llvm.pow'
55INTR_FLOOR = 'llvm.floor'
56
57LINKAGE_EXTERNAL = 'external'
58LINKAGE_INTERNAL = 'internal'
59LINKAGE_LINKONCE_ODR = 'linkonce_odr'
60
61ATTR_NO_CAPTURE = 'nocapture'
62
63
64class Type(object):
65    @staticmethod
66    def int(width=32):
67        return ir.IntType(width)
68
69    @staticmethod
70    def float():
71        return ir.FloatType()
72
73    @staticmethod
74    def half():
75        return ir.HalfType()
76
77    @staticmethod
78    def double():
79        return ir.DoubleType()
80
81    @staticmethod
82    def pointer(ty, addrspace=0):
83        return ir.PointerType(ty, addrspace)
84
85    @staticmethod
86    def function(res, args, var_arg=False):
87        return ir.FunctionType(res, args, var_arg=var_arg)
88
89    @staticmethod
90    def struct(members):
91        return ir.LiteralStructType(members)
92
93    @staticmethod
94    def array(element, count):
95        return ir.ArrayType(element, count)
96
97    @staticmethod
98    def void():
99        return ir.VoidType()
100
101
102class Constant(object):
103    @staticmethod
104    def all_ones(ty):
105        if isinstance(ty, ir.IntType):
106            return Constant.int(ty, int('1' * ty.width, 2))
107        else:
108            raise NotImplementedError(ty)
109
110    @staticmethod
111    def int(ty, n):
112        return ir.Constant(ty, n)
113
114    @staticmethod
115    def int_signextend(ty, n):
116        return ir.Constant(ty, n)
117
118    @staticmethod
119    def real(ty, n):
120        return ir.Constant(ty, n)
121
122    @staticmethod
123    def struct(elems):
124        return ir.Constant.literal_struct(elems)
125
126    @staticmethod
127    def null(ty):
128        return ir.Constant(ty, None)
129
130    @staticmethod
131    def undef(ty):
132        return ir.Constant(ty, ir.Undefined)
133
134    @staticmethod
135    def stringz(string):
136        n = (len(string) + 1)
137        buf = bytearray((' ' * n).encode('ascii'))
138        buf[-1] = 0
139        buf[:-1] = string.encode('utf-8')
140        return ir.Constant(ir.ArrayType(ir.IntType(8), n), buf)
141
142    @staticmethod
143    def array(typ, val):
144        return ir.Constant(ir.ArrayType(typ, len(val)), val)
145
146    @staticmethod
147    def bitcast(const, typ):
148        return const.bitcast(typ)
149
150    @staticmethod
151    def inttoptr(const, typ):
152        return const.inttoptr(typ)
153
154    @staticmethod
155    def gep(const, indices):
156        return const.gep(indices)
157
158
159class Module(ir.Module):
160
161    def get_or_insert_function(self, fnty, name):
162        if name in self.globals:
163            return self.globals[name]
164        else:
165            return ir.Function(self, fnty, name)
166
167    def verify(self):
168        llvm.parse_assembly(str(self))
169
170    def add_function(self, fnty, name):
171        return ir.Function(self, fnty, name)
172
173    def add_global_variable(self, ty, name, addrspace=0):
174        return ir.GlobalVariable(self, ty, self.get_unique_name(name),
175                                 addrspace)
176
177    def get_global_variable_named(self, name):
178        try:
179            return self.globals[name]
180        except KeyError:
181            raise LLVMException(name)
182
183    def get_or_insert_named_metadata(self, name):
184        try:
185            return self.get_named_metadata(name)
186        except KeyError:
187            return self.add_named_metadata(name)
188
189
190class Function(ir.Function):
191
192    @classmethod
193    def new(cls, module_obj, functy, name=''):
194        return cls(module_obj, functy, name)
195
196    @staticmethod
197    def intrinsic(module, intrinsic, tys):
198        return module.declare_intrinsic(intrinsic, tys)
199
200
201_icmp_umap = {
202    ICMP_EQ: '==',
203    ICMP_NE: '!=',
204    ICMP_ULT: '<',
205    ICMP_ULE: '<=',
206    ICMP_UGT: '>',
207    ICMP_UGE: '>=',
208}
209
210_icmp_smap = {
211    ICMP_SLT: '<',
212    ICMP_SLE: '<=',
213    ICMP_SGT: '>',
214    ICMP_SGE: '>=',
215}
216
217_fcmp_omap = {
218    FCMP_OEQ: '==',
219    FCMP_OGT: '>',
220    FCMP_OGE: '>=',
221    FCMP_OLT: '<',
222    FCMP_OLE: '<=',
223    FCMP_ONE: '!=',
224    FCMP_ORD: 'ord',
225}
226
227_fcmp_umap = {
228    FCMP_UEQ: '==',
229    FCMP_UGT: '>',
230    FCMP_UGE: '>=',
231    FCMP_ULT: '<',
232    FCMP_ULE: '<=',
233    FCMP_UNE: '!=',
234    FCMP_UNO: 'uno',
235}
236
237
238class Builder(ir.IRBuilder):
239
240    def icmp(self, pred, lhs, rhs, name=''):
241        if pred in _icmp_umap:
242            return self.icmp_unsigned(_icmp_umap[pred], lhs, rhs, name=name)
243        else:
244            return self.icmp_signed(_icmp_smap[pred], lhs, rhs, name=name)
245
246    def fcmp(self, pred, lhs, rhs, name=''):
247        if pred in _fcmp_umap:
248            return self.fcmp_unordered(_fcmp_umap[pred], lhs, rhs, name=name)
249        else:
250            return self.fcmp_ordered(_fcmp_omap[pred], lhs, rhs, name=name)
251
252
253class MetaDataString(ir.MetaDataString):
254    @staticmethod
255    def get(module, text):
256        return MetaDataString(module, text)
257
258
259class MetaData(object):
260    @staticmethod
261    def get(module, values):
262        return module.add_metadata(values)
263
264
265class InlineAsm(ir.InlineAsm):
266    @staticmethod
267    def get(*args, **kwargs):
268        return InlineAsm(*args, **kwargs)
269