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.LLVMInitializeVectorization.argtypes = [PassRegistry]
462    library.LLVMInitializeVectorization.restype = None
463
464    library.LLVMInitializeInstCombine.argtypes = [PassRegistry]
465    library.LLVMInitializeInstCombine.restype = None
466
467    library.LLVMInitializeIPO.argtypes = [PassRegistry]
468    library.LLVMInitializeIPO.restype = None
469
470    library.LLVMInitializeAnalysis.argtypes = [PassRegistry]
471    library.LLVMInitializeAnalysis.restype = None
472
473    library.LLVMInitializeCodeGen.argtypes = [PassRegistry]
474    library.LLVMInitializeCodeGen.restype = None
475
476    library.LLVMInitializeTarget.argtypes = [PassRegistry]
477    library.LLVMInitializeTarget.restype = None
478
479    library.LLVMShutdown.argtypes = []
480    library.LLVMShutdown.restype = None
481
482    # Pass Registry declarations.
483    library.LLVMGetGlobalPassRegistry.argtypes = []
484    library.LLVMGetGlobalPassRegistry.restype = c_object_p
485
486    # Context declarations.
487    library.LLVMContextCreate.argtypes = []
488    library.LLVMContextCreate.restype = c_object_p
489
490    library.LLVMContextDispose.argtypes = [Context]
491    library.LLVMContextDispose.restype = None
492
493    library.LLVMGetGlobalContext.argtypes = []
494    library.LLVMGetGlobalContext.restype = c_object_p
495
496    # Memory buffer declarations
497    library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p,
498            POINTER(c_object_p), POINTER(c_char_p)]
499    library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool
500
501    library.LLVMGetBufferSize.argtypes = [MemoryBuffer]
502
503    library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer]
504
505    # Module declarations
506    library.LLVMModuleCreateWithName.argtypes = [c_char_p]
507    library.LLVMModuleCreateWithName.restype = c_object_p
508
509    library.LLVMDisposeModule.argtypes = [Module]
510    library.LLVMDisposeModule.restype = None
511
512    library.LLVMGetDataLayout.argtypes = [Module]
513    library.LLVMGetDataLayout.restype = c_char_p
514
515    library.LLVMSetDataLayout.argtypes = [Module, c_char_p]
516    library.LLVMSetDataLayout.restype = None
517
518    library.LLVMGetTarget.argtypes = [Module]
519    library.LLVMGetTarget.restype = c_char_p
520
521    library.LLVMSetTarget.argtypes = [Module, c_char_p]
522    library.LLVMSetTarget.restype = None
523
524    library.LLVMDumpModule.argtypes = [Module]
525    library.LLVMDumpModule.restype = None
526
527    library.LLVMPrintModuleToFile.argtypes = [Module, c_char_p,
528                                              POINTER(c_char_p)]
529    library.LLVMPrintModuleToFile.restype = bool
530
531    library.LLVMGetFirstFunction.argtypes = [Module]
532    library.LLVMGetFirstFunction.restype = c_object_p
533
534    library.LLVMGetLastFunction.argtypes = [Module]
535    library.LLVMGetLastFunction.restype = c_object_p
536
537    library.LLVMGetNextFunction.argtypes = [Function]
538    library.LLVMGetNextFunction.restype = c_object_p
539
540    library.LLVMGetPreviousFunction.argtypes = [Function]
541    library.LLVMGetPreviousFunction.restype = c_object_p
542
543    # Value declarations.
544    library.LLVMGetValueName.argtypes = [Value]
545    library.LLVMGetValueName.restype = c_char_p
546
547    library.LLVMDumpValue.argtypes = [Value]
548    library.LLVMDumpValue.restype = None
549
550    library.LLVMGetOperand.argtypes = [Value, c_uint]
551    library.LLVMGetOperand.restype = c_object_p
552
553    library.LLVMSetOperand.argtypes = [Value, Value, c_uint]
554    library.LLVMSetOperand.restype = None
555
556    library.LLVMGetNumOperands.argtypes = [Value]
557    library.LLVMGetNumOperands.restype = c_uint
558
559    # Basic Block Declarations.
560    library.LLVMGetFirstBasicBlock.argtypes = [Function]
561    library.LLVMGetFirstBasicBlock.restype = c_object_p
562
563    library.LLVMGetLastBasicBlock.argtypes = [Function]
564    library.LLVMGetLastBasicBlock.restype = c_object_p
565
566    library.LLVMGetNextBasicBlock.argtypes = [BasicBlock]
567    library.LLVMGetNextBasicBlock.restype = c_object_p
568
569    library.LLVMGetPreviousBasicBlock.argtypes = [BasicBlock]
570    library.LLVMGetPreviousBasicBlock.restype = c_object_p
571
572    library.LLVMGetFirstInstruction.argtypes = [BasicBlock]
573    library.LLVMGetFirstInstruction.restype = c_object_p
574
575    library.LLVMGetLastInstruction.argtypes = [BasicBlock]
576    library.LLVMGetLastInstruction.restype = c_object_p
577
578    library.LLVMBasicBlockAsValue.argtypes = [BasicBlock]
579    library.LLVMBasicBlockAsValue.restype = c_object_p
580
581    library.LLVMCountBasicBlocks.argtypes = [Function]
582    library.LLVMCountBasicBlocks.restype = c_uint
583
584    # Instruction Declarations.
585    library.LLVMGetNextInstruction.argtypes = [Instruction]
586    library.LLVMGetNextInstruction.restype = c_object_p
587
588    library.LLVMGetPreviousInstruction.argtypes = [Instruction]
589    library.LLVMGetPreviousInstruction.restype = c_object_p
590
591    library.LLVMGetInstructionOpcode.argtypes = [Instruction]
592    library.LLVMGetInstructionOpcode.restype = c_uint
593
594def register_enumerations():
595    if Enums:
596        return None
597    enums = [
598        (Attribute, enumerations.Attributes),
599        (OpCode, enumerations.OpCodes),
600        (TypeKind, enumerations.TypeKinds),
601        (Linkage, enumerations.Linkages),
602        (Visibility, enumerations.Visibility),
603        (CallConv, enumerations.CallConv),
604        (IntPredicate, enumerations.IntPredicate),
605        (RealPredicate, enumerations.RealPredicate),
606        (LandingPadClauseTy, enumerations.LandingPadClauseTy),
607    ]
608    for enum_class, enum_spec in enums:
609        for name, value in enum_spec:
610            print(name, value)
611            enum_class.register(name, value)
612    return enums
613
614def initialize_llvm():
615    Context.GetGlobalContext()
616    p = PassRegistry()
617    lib.LLVMInitializeCore(p)
618    lib.LLVMInitializeTransformUtils(p)
619    lib.LLVMInitializeScalarOpts(p)
620    lib.LLVMInitializeVectorization(p)
621    lib.LLVMInitializeInstCombine(p)
622    lib.LLVMInitializeIPO(p)
623    lib.LLVMInitializeAnalysis(p)
624    lib.LLVMInitializeCodeGen(p)
625    lib.LLVMInitializeTarget(p)
626
627register_library(lib)
628Enums = register_enumerations()
629initialize_llvm()
630