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