1#===- core.py - Python LLVM Bindings -------------------------*- python -*--===#
2#
3#                     The LLVM Compiler Infrastructure
4#
5# This file is distributed under the University of Illinois Open Source
6# License. See LICENSE.TXT for details.
7#
8#===------------------------------------------------------------------------===#
9
10from .common import LLVMObject
11from .common import c_object_p
12from .common import get_library
13
14from . import enumerations
15
16from ctypes import POINTER
17from ctypes import byref
18from ctypes import c_char_p
19from ctypes import c_uint
20
21__all__ = [
22    "lib",
23    "OpCode",
24    "MemoryBuffer",
25    "Module",
26    "Value",
27    "Function",
28    "BasicBlock",
29    "Instruction",
30    "Context",
31    "PassRegistry"
32]
33
34lib = get_library()
35
36class OpCode(object):
37    """Represents an individual OpCode enumeration."""
38
39    _value_map = {}
40
41    def __init__(self, name, value):
42        self.name = name
43        self.value = value
44
45    def __repr__(self):
46        return 'OpCode.%s' % self.name
47
48    @staticmethod
49    def from_value(value):
50        """Obtain an OpCode instance from a numeric value."""
51        result = OpCode._value_map.get(value, None)
52
53        if result is None:
54            raise ValueError('Unknown OpCode: %d' % value)
55
56        return result
57
58    @staticmethod
59    def register(name, value):
60        """Registers a new OpCode enumeration.
61
62        This is called by this module for each enumeration defined in
63        enumerations. You should not need to call this outside this module.
64        """
65        if value in OpCode._value_map:
66            raise ValueError('OpCode value already registered: %d' % value)
67
68        opcode = OpCode(name, value)
69        OpCode._value_map[value] = opcode
70        setattr(OpCode, name, opcode)
71
72class MemoryBuffer(LLVMObject):
73    """Represents an opaque memory buffer."""
74
75    def __init__(self, filename=None):
76        """Create a new memory buffer.
77
78        Currently, we support creating from the contents of a file at the
79        specified filename.
80        """
81        if filename is None:
82            raise Exception("filename argument must be defined")
83
84        memory = c_object_p()
85        out = c_char_p(None)
86
87        result = lib.LLVMCreateMemoryBufferWithContentsOfFile(filename,
88                byref(memory), byref(out))
89
90        if result:
91            raise Exception("Could not create memory buffer: %s" % out.value)
92
93        LLVMObject.__init__(self, memory, disposer=lib.LLVMDisposeMemoryBuffer)
94
95    def __len__(self):
96        return lib.LLVMGetBufferSize(self)
97
98class Value(LLVMObject):
99
100    def __init__(self, value):
101        LLVMObject.__init__(self, value)
102
103    @property
104    def name(self):
105        return lib.LLVMGetValueName(self)
106
107    def dump(self):
108        lib.LLVMDumpValue(self)
109
110    def get_operand(self, i):
111        return Value(lib.LLVMGetOperand(self, i))
112
113    def set_operand(self, i, v):
114        return lib.LLVMSetOperand(self, i, v)
115
116    def __len__(self):
117        return lib.LLVMGetNumOperands(self)
118
119class Module(LLVMObject):
120    """Represents the top-level structure of an llvm program in an opaque object."""
121
122    def __init__(self, module, name=None, context=None):
123        LLVMObject.__init__(self, module, disposer=lib.LLVMDisposeModule)
124
125    @classmethod
126    def CreateWithName(cls, module_id):
127        m = Module(lib.LLVMModuleCreateWithName(module_id))
128        c = Context.GetGlobalContext().take_ownership(m)
129        return m
130
131    @property
132    def datalayout(self):
133        return lib.LLVMGetDataLayout(self)
134
135    @datalayout.setter
136    def datalayout(self, new_data_layout):
137        """new_data_layout is a string."""
138        lib.LLVMSetDataLayout(self, new_data_layout)
139
140    @property
141    def target(self):
142        return lib.LLVMGetTarget(self)
143
144    @target.setter
145    def target(self, new_target):
146        """new_target is a string."""
147        lib.LLVMSetTarget(self, new_target)
148
149    def dump(self):
150        lib.LLVMDumpModule(self)
151
152    class __function_iterator(object):
153        def __init__(self, module, reverse=False):
154            self.module = module
155            self.reverse = reverse
156            if self.reverse:
157                self.function = self.module.last
158            else:
159                self.function = self.module.first
160
161        def __iter__(self):
162            return self
163
164        def next(self):
165            if not isinstance(self.function, Function):
166                raise StopIteration("")
167            result = self.function
168            if self.reverse:
169                self.function = self.function.prev
170            else:
171                self.function = self.function.next
172            return result
173
174    def __iter__(self):
175        return Module.__function_iterator(self)
176
177    def __reversed__(self):
178        return Module.__function_iterator(self, reverse=True)
179
180    @property
181    def first(self):
182        return Function(lib.LLVMGetFirstFunction(self))
183
184    @property
185    def last(self):
186        return Function(lib.LLVMGetLastFunction(self))
187
188    def print_module_to_file(self, filename):
189        out = c_char_p(None)
190        # Result is inverted so 0 means everything was ok.
191        result = lib.LLVMPrintModuleToFile(self, filename, byref(out))
192        if result:
193            raise RuntimeError("LLVM Error: %s" % out.value)
194
195class Function(Value):
196
197    def __init__(self, value):
198        Value.__init__(self, value)
199
200    @property
201    def next(self):
202        f = lib.LLVMGetNextFunction(self)
203        return f and Function(f)
204
205    @property
206    def prev(self):
207        f = lib.LLVMGetPreviousFunction(self)
208        return f and Function(f)
209
210    @property
211    def first(self):
212        b = lib.LLVMGetFirstBasicBlock(self)
213        return b and BasicBlock(b)
214
215    @property
216    def last(self):
217        b = lib.LLVMGetLastBasicBlock(self)
218        return b and BasicBlock(b)
219
220    class __bb_iterator(object):
221        def __init__(self, function, reverse=False):
222            self.function = function
223            self.reverse = reverse
224            if self.reverse:
225                self.bb = function.last
226            else:
227                self.bb = function.first
228
229        def __iter__(self):
230            return self
231
232        def next(self):
233            if not isinstance(self.bb, BasicBlock):
234                raise StopIteration("")
235            result = self.bb
236            if self.reverse:
237                self.bb = self.bb.prev
238            else:
239                self.bb = self.bb.next
240            return result
241
242    def __iter__(self):
243        return Function.__bb_iterator(self)
244
245    def __reversed__(self):
246        return Function.__bb_iterator(self, reverse=True)
247
248    def __len__(self):
249        return lib.LLVMCountBasicBlocks(self)
250
251class BasicBlock(LLVMObject):
252
253    def __init__(self, value):
254        LLVMObject.__init__(self, value)
255
256    @property
257    def next(self):
258        b = lib.LLVMGetNextBasicBlock(self)
259        return b and BasicBlock(b)
260
261    @property
262    def prev(self):
263        b = lib.LLVMGetPreviousBasicBlock(self)
264        return b and BasicBlock(b)
265
266    @property
267    def first(self):
268        i = lib.LLVMGetFirstInstruction(self)
269        return i and Instruction(i)
270
271    @property
272    def last(self):
273        i = lib.LLVMGetLastInstruction(self)
274        return i and Instruction(i)
275
276    def __as_value(self):
277        return Value(lib.LLVMBasicBlockAsValue(self))
278
279    @property
280    def name(self):
281        return lib.LLVMGetValueName(self.__as_value())
282
283    def dump(self):
284        lib.LLVMDumpValue(self.__as_value())
285
286    def get_operand(self, i):
287        return Value(lib.LLVMGetOperand(self.__as_value(),
288                                        i))
289
290    def set_operand(self, i, v):
291        return lib.LLVMSetOperand(self.__as_value(),
292                                  i, v)
293
294    def __len__(self):
295        return lib.LLVMGetNumOperands(self.__as_value())
296
297    class __inst_iterator(object):
298        def __init__(self, bb, reverse=False):
299            self.bb = bb
300            self.reverse = reverse
301            if self.reverse:
302                self.inst = self.bb.last
303            else:
304                self.inst = self.bb.first
305
306        def __iter__(self):
307            return self
308
309        def next(self):
310            if not isinstance(self.inst, Instruction):
311                raise StopIteration("")
312            result = self.inst
313            if self.reverse:
314                self.inst = self.inst.prev
315            else:
316                self.inst = self.inst.next
317            return result
318
319    def __iter__(self):
320        return BasicBlock.__inst_iterator(self)
321
322    def __reversed__(self):
323        return BasicBlock.__inst_iterator(self, reverse=True)
324
325
326class Instruction(Value):
327
328    def __init__(self, value):
329        Value.__init__(self, value)
330
331    @property
332    def next(self):
333        i = lib.LLVMGetNextInstruction(self)
334        return i and Instruction(i)
335
336    @property
337    def prev(self):
338        i = lib.LLVMGetPreviousInstruction(self)
339        return i and Instruction(i)
340
341    @property
342    def opcode(self):
343        return OpCode.from_value(lib.LLVMGetInstructionOpcode(self))
344
345class Context(LLVMObject):
346
347    def __init__(self, context=None):
348        if context is None:
349            context = lib.LLVMContextCreate()
350            LLVMObject.__init__(self, context, disposer=lib.LLVMContextDispose)
351        else:
352            LLVMObject.__init__(self, context)
353
354    @classmethod
355    def GetGlobalContext(cls):
356        return Context(lib.LLVMGetGlobalContext())
357
358class PassRegistry(LLVMObject):
359    """Represents an opaque pass registry object."""
360
361    def __init__(self):
362        LLVMObject.__init__(self,
363                            lib.LLVMGetGlobalPassRegistry())
364
365def register_library(library):
366    # Initialization/Shutdown declarations.
367    library.LLVMInitializeCore.argtypes = [PassRegistry]
368    library.LLVMInitializeCore.restype = None
369
370    library.LLVMInitializeTransformUtils.argtypes = [PassRegistry]
371    library.LLVMInitializeTransformUtils.restype = None
372
373    library.LLVMInitializeScalarOpts.argtypes = [PassRegistry]
374    library.LLVMInitializeScalarOpts.restype = None
375
376    library.LLVMInitializeObjCARCOpts.argtypes = [PassRegistry]
377    library.LLVMInitializeObjCARCOpts.restype = None
378
379    library.LLVMInitializeVectorization.argtypes = [PassRegistry]
380    library.LLVMInitializeVectorization.restype = None
381
382    library.LLVMInitializeInstCombine.argtypes = [PassRegistry]
383    library.LLVMInitializeInstCombine.restype = None
384
385    library.LLVMInitializeIPO.argtypes = [PassRegistry]
386    library.LLVMInitializeIPO.restype = None
387
388    library.LLVMInitializeInstrumentation.argtypes = [PassRegistry]
389    library.LLVMInitializeInstrumentation.restype = None
390
391    library.LLVMInitializeAnalysis.argtypes = [PassRegistry]
392    library.LLVMInitializeAnalysis.restype = None
393
394    library.LLVMInitializeIPA.argtypes = [PassRegistry]
395    library.LLVMInitializeIPA.restype = None
396
397    library.LLVMInitializeCodeGen.argtypes = [PassRegistry]
398    library.LLVMInitializeCodeGen.restype = None
399
400    library.LLVMInitializeTarget.argtypes = [PassRegistry]
401    library.LLVMInitializeTarget.restype = None
402
403    library.LLVMShutdown.argtypes = []
404    library.LLVMShutdown.restype = None
405
406    # Pass Registry declarations.
407    library.LLVMGetGlobalPassRegistry.argtypes = []
408    library.LLVMGetGlobalPassRegistry.restype = c_object_p
409
410    # Context declarations.
411    library.LLVMContextCreate.argtypes = []
412    library.LLVMContextCreate.restype = c_object_p
413
414    library.LLVMContextDispose.argtypes = [Context]
415    library.LLVMContextDispose.restype = None
416
417    library.LLVMGetGlobalContext.argtypes = []
418    library.LLVMGetGlobalContext.restype = c_object_p
419
420    # Memory buffer declarations
421    library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p,
422            POINTER(c_object_p), POINTER(c_char_p)]
423    library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool
424
425    library.LLVMGetBufferSize.argtypes = [MemoryBuffer]
426
427    library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer]
428
429    # Module declarations
430    library.LLVMModuleCreateWithName.argtypes = [c_char_p]
431    library.LLVMModuleCreateWithName.restype = c_object_p
432
433    library.LLVMDisposeModule.argtypes = [Module]
434    library.LLVMDisposeModule.restype = None
435
436    library.LLVMGetDataLayout.argtypes = [Module]
437    library.LLVMGetDataLayout.restype = c_char_p
438
439    library.LLVMSetDataLayout.argtypes = [Module, c_char_p]
440    library.LLVMSetDataLayout.restype = None
441
442    library.LLVMGetTarget.argtypes = [Module]
443    library.LLVMGetTarget.restype = c_char_p
444
445    library.LLVMSetTarget.argtypes = [Module, c_char_p]
446    library.LLVMSetTarget.restype = None
447
448    library.LLVMDumpModule.argtypes = [Module]
449    library.LLVMDumpModule.restype = None
450
451    library.LLVMPrintModuleToFile.argtypes = [Module, c_char_p,
452                                              POINTER(c_char_p)]
453    library.LLVMPrintModuleToFile.restype = bool
454
455    library.LLVMGetFirstFunction.argtypes = [Module]
456    library.LLVMGetFirstFunction.restype = c_object_p
457
458    library.LLVMGetLastFunction.argtypes = [Module]
459    library.LLVMGetLastFunction.restype = c_object_p
460
461    library.LLVMGetNextFunction.argtypes = [Function]
462    library.LLVMGetNextFunction.restype = c_object_p
463
464    library.LLVMGetPreviousFunction.argtypes = [Function]
465    library.LLVMGetPreviousFunction.restype = c_object_p
466
467    # Value declarations.
468    library.LLVMGetValueName.argtypes = [Value]
469    library.LLVMGetValueName.restype = c_char_p
470
471    library.LLVMDumpValue.argtypes = [Value]
472    library.LLVMDumpValue.restype = None
473
474    library.LLVMGetOperand.argtypes = [Value, c_uint]
475    library.LLVMGetOperand.restype = c_object_p
476
477    library.LLVMSetOperand.argtypes = [Value, Value, c_uint]
478    library.LLVMSetOperand.restype = None
479
480    library.LLVMGetNumOperands.argtypes = [Value]
481    library.LLVMGetNumOperands.restype = c_uint
482
483    # Basic Block Declarations.
484    library.LLVMGetFirstBasicBlock.argtypes = [Function]
485    library.LLVMGetFirstBasicBlock.restype = c_object_p
486
487    library.LLVMGetLastBasicBlock.argtypes = [Function]
488    library.LLVMGetLastBasicBlock.restype = c_object_p
489
490    library.LLVMGetNextBasicBlock.argtypes = [BasicBlock]
491    library.LLVMGetNextBasicBlock.restype = c_object_p
492
493    library.LLVMGetPreviousBasicBlock.argtypes = [BasicBlock]
494    library.LLVMGetPreviousBasicBlock.restype = c_object_p
495
496    library.LLVMGetFirstInstruction.argtypes = [BasicBlock]
497    library.LLVMGetFirstInstruction.restype = c_object_p
498
499    library.LLVMGetLastInstruction.argtypes = [BasicBlock]
500    library.LLVMGetLastInstruction.restype = c_object_p
501
502    library.LLVMBasicBlockAsValue.argtypes = [BasicBlock]
503    library.LLVMBasicBlockAsValue.restype = c_object_p
504
505    library.LLVMCountBasicBlocks.argtypes = [Function]
506    library.LLVMCountBasicBlocks.restype = c_uint
507
508    # Instruction Declarations.
509    library.LLVMGetNextInstruction.argtypes = [Instruction]
510    library.LLVMGetNextInstruction.restype = c_object_p
511
512    library.LLVMGetPreviousInstruction.argtypes = [Instruction]
513    library.LLVMGetPreviousInstruction.restype = c_object_p
514
515    library.LLVMGetInstructionOpcode.argtypes = [Instruction]
516    library.LLVMGetInstructionOpcode.restype = c_uint
517
518def register_enumerations():
519    for name, value in enumerations.OpCodes:
520        OpCode.register(name, value)
521
522def initialize_llvm():
523    c = Context.GetGlobalContext()
524    p = PassRegistry()
525    lib.LLVMInitializeCore(p)
526    lib.LLVMInitializeTransformUtils(p)
527    lib.LLVMInitializeScalarOpts(p)
528    lib.LLVMInitializeObjCARCOpts(p)
529    lib.LLVMInitializeVectorization(p)
530    lib.LLVMInitializeInstCombine(p)
531    lib.LLVMInitializeIPO(p)
532    lib.LLVMInitializeInstrumentation(p)
533    lib.LLVMInitializeAnalysis(p)
534    lib.LLVMInitializeIPA(p)
535    lib.LLVMInitializeCodeGen(p)
536    lib.LLVMInitializeTarget(p)
537
538register_library(lib)
539register_enumerations()
540initialize_llvm()
541