IR: Return unique_ptr from MDNode::getTemporary()
[oota-llvm.git] / bindings / python / llvm / core.py
index bd61a6ac993e7273fb98dfe450ac0fb151ab4bbe..c95952db6fc5a283cf8c14d3087890c8a8712f9d 100644 (file)
@@ -16,49 +16,132 @@ from . import enumerations
 from ctypes import POINTER
 from ctypes import byref
 from ctypes import c_char_p
+from ctypes import c_uint
 
 __all__ = [
     "lib",
+    "Enums",
+    "OpCode",
     "MemoryBuffer",
+    "Module",
+    "Value",
+    "Function",
+    "BasicBlock",
+    "Instruction",
+    "Context",
+    "PassRegistry"
 ]
 
 lib = get_library()
+Enums = []
 
-class OpCode(object):
-    """Represents an individual OpCode enumeration."""
-
-    _value_map = {}
+class LLVMEnumeration(object):
+    """Represents an individual LLVM enumeration."""
 
     def __init__(self, name, value):
         self.name = name
         self.value = value
 
     def __repr__(self):
-        return 'OpCode.%s' % self.name
+        return '%s.%s' % (self.__class__.__name__,
+                          self.name)
 
-    @staticmethod
-    def from_value(value):
-        """Obtain an OpCode instance from a numeric value."""
-        result = OpCode._value_map.get(value, None)
+    @classmethod
+    def from_value(cls, value):
+        """Obtain an enumeration instance from a numeric value."""
+        result = cls._value_map.get(value, None)
 
         if result is None:
-            raise ValueError('Unknown OpCode: %d' % value)
+            raise ValueError('Unknown %s: %d' % (cls.__name__,
+                                                 value))
 
         return result
 
-    @staticmethod
-    def register(name, value):
-        """Registers a new OpCode enumeration.
+    @classmethod
+    def register(cls, name, value):
+        """Registers a new enumeration.
 
         This is called by this module for each enumeration defined in
         enumerations. You should not need to call this outside this module.
         """
-        if value in OpCode._value_map:
-            raise ValueError('OpCode value already registered: %d' % value)
+        if value in cls._value_map:
+            raise ValueError('%s value already registered: %d' % (cls.__name__,
+                                                                  value))
+        enum = cls(name, value)
+        cls._value_map[value] = enum
+        setattr(cls, name, enum)
+
+class Attribute(LLVMEnumeration):
+    """Represents an individual Attribute enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(Attribute, self).__init__(name, value)
+
+class OpCode(LLVMEnumeration):
+    """Represents an individual OpCode enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(OpCode, self).__init__(name, value)
+
+class TypeKind(LLVMEnumeration):
+    """Represents an individual TypeKind enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(TypeKind, self).__init__(name, value)
+
+class Linkage(LLVMEnumeration):
+    """Represents an individual Linkage enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(Linkage, self).__init__(name, value)
+
+class Visibility(LLVMEnumeration):
+    """Represents an individual visibility enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(Visibility, self).__init__(name, value)
+
+class CallConv(LLVMEnumeration):
+    """Represents an individual calling convention enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(CallConv, self).__init__(name, value)
+
+class IntPredicate(LLVMEnumeration):
+    """Represents an individual IntPredicate enumeration."""
 
-        opcode = OpCode(name, value)
-        OpCode._value_map[value] = opcode
-        setattr(OpCode, name, opcode)
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(IntPredicate, self).__init__(name, value)
+
+class RealPredicate(LLVMEnumeration):
+    """Represents an individual RealPredicate enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(RealPredicate, self).__init__(name, value)
+
+class LandingPadClauseTy(LLVMEnumeration):
+    """Represents an individual LandingPadClauseTy enumeration."""
+
+    _value_map = {}
+
+    def __init__(self, name, value):
+        super(LandingPadClauseTy, self).__init__(name, value)
 
 class MemoryBuffer(LLVMObject):
     """Represents an opaque memory buffer."""
@@ -86,7 +169,328 @@ class MemoryBuffer(LLVMObject):
     def __len__(self):
         return lib.LLVMGetBufferSize(self)
 
+class Value(LLVMObject):
+    
+    def __init__(self, value):
+        LLVMObject.__init__(self, value)
+
+    @property
+    def name(self):
+        return lib.LLVMGetValueName(self)
+
+    def dump(self):
+        lib.LLVMDumpValue(self)
+    
+    def get_operand(self, i):
+        return Value(lib.LLVMGetOperand(self, i))
+    
+    def set_operand(self, i, v):
+        return lib.LLVMSetOperand(self, i, v)
+    
+    def __len__(self):
+        return lib.LLVMGetNumOperands(self)
+
+class Module(LLVMObject):
+    """Represents the top-level structure of an llvm program in an opaque object."""
+
+    def __init__(self, module, name=None, context=None):
+        LLVMObject.__init__(self, module, disposer=lib.LLVMDisposeModule)
+
+    @classmethod
+    def CreateWithName(cls, module_id):
+        m = Module(lib.LLVMModuleCreateWithName(module_id))
+        Context.GetGlobalContext().take_ownership(m)
+        return m
+
+    @property
+    def datalayout(self):
+        return lib.LLVMGetDataLayout(self)
+
+    @datalayout.setter
+    def datalayout(self, new_data_layout):
+        """new_data_layout is a string."""
+        lib.LLVMSetDataLayout(self, new_data_layout)
+
+    @property
+    def target(self):
+        return lib.LLVMGetTarget(self)
+
+    @target.setter
+    def target(self, new_target):
+        """new_target is a string."""
+        lib.LLVMSetTarget(self, new_target)
+
+    def dump(self):
+        lib.LLVMDumpModule(self)
+
+    class __function_iterator(object):
+        def __init__(self, module, reverse=False):
+            self.module = module
+            self.reverse = reverse
+            if self.reverse:
+                self.function = self.module.last
+            else:
+                self.function = self.module.first
+        
+        def __iter__(self):
+            return self
+        
+        def next(self):
+            if not isinstance(self.function, Function):
+                raise StopIteration("")
+            result = self.function
+            if self.reverse:
+                self.function = self.function.prev
+            else:
+                self.function = self.function.next
+            return result
+    
+    def __iter__(self):
+        return Module.__function_iterator(self)
+
+    def __reversed__(self):
+        return Module.__function_iterator(self, reverse=True)
+
+    @property
+    def first(self):
+        return Function(lib.LLVMGetFirstFunction(self))
+
+    @property
+    def last(self):
+        return Function(lib.LLVMGetLastFunction(self))
+
+    def print_module_to_file(self, filename):
+        out = c_char_p(None)
+        # Result is inverted so 0 means everything was ok.
+        result = lib.LLVMPrintModuleToFile(self, filename, byref(out))        
+        if result:
+            raise RuntimeError("LLVM Error: %s" % out.value)
+
+class Function(Value):
+
+    def __init__(self, value):
+        Value.__init__(self, value)
+    
+    @property
+    def next(self):
+        f = lib.LLVMGetNextFunction(self)
+        return f and Function(f)
+    
+    @property
+    def prev(self):
+        f = lib.LLVMGetPreviousFunction(self)
+        return f and Function(f)
+    
+    @property
+    def first(self):
+        b = lib.LLVMGetFirstBasicBlock(self)
+        return b and BasicBlock(b)
+
+    @property
+    def last(self):
+        b = lib.LLVMGetLastBasicBlock(self)
+        return b and BasicBlock(b)
+
+    class __bb_iterator(object):
+        def __init__(self, function, reverse=False):
+            self.function = function
+            self.reverse = reverse
+            if self.reverse:
+                self.bb = function.last
+            else:
+                self.bb = function.first
+        
+        def __iter__(self):
+            return self
+        
+        def next(self):
+            if not isinstance(self.bb, BasicBlock):
+                raise StopIteration("")
+            result = self.bb
+            if self.reverse:
+                self.bb = self.bb.prev
+            else:
+                self.bb = self.bb.next
+            return result
+    
+    def __iter__(self):
+        return Function.__bb_iterator(self)
+
+    def __reversed__(self):
+        return Function.__bb_iterator(self, reverse=True)
+    
+    def __len__(self):
+        return lib.LLVMCountBasicBlocks(self)
+
+class BasicBlock(LLVMObject):
+    
+    def __init__(self, value):
+        LLVMObject.__init__(self, value)
+
+    @property
+    def next(self):
+        b = lib.LLVMGetNextBasicBlock(self)
+        return b and BasicBlock(b)
+
+    @property
+    def prev(self):
+        b = lib.LLVMGetPreviousBasicBlock(self)
+        return b and BasicBlock(b)
+    
+    @property
+    def first(self):
+        i = lib.LLVMGetFirstInstruction(self)
+        return i and Instruction(i)
+
+    @property
+    def last(self):
+        i = lib.LLVMGetLastInstruction(self)
+        return i and Instruction(i)
+
+    def __as_value(self):
+        return Value(lib.LLVMBasicBlockAsValue(self))
+    
+    @property
+    def name(self):
+        return lib.LLVMGetValueName(self.__as_value())
+
+    def dump(self):
+        lib.LLVMDumpValue(self.__as_value())
+
+    def get_operand(self, i):
+        return Value(lib.LLVMGetOperand(self.__as_value(),
+                                        i))
+    
+    def set_operand(self, i, v):
+        return lib.LLVMSetOperand(self.__as_value(),
+                                  i, v)
+    
+    def __len__(self):
+        return lib.LLVMGetNumOperands(self.__as_value())
+
+    class __inst_iterator(object):
+        def __init__(self, bb, reverse=False):            
+            self.bb = bb
+            self.reverse = reverse
+            if self.reverse:
+                self.inst = self.bb.last
+            else:
+                self.inst = self.bb.first
+        
+        def __iter__(self):
+            return self
+        
+        def next(self):
+            if not isinstance(self.inst, Instruction):
+                raise StopIteration("")
+            result = self.inst
+            if self.reverse:
+                self.inst = self.inst.prev
+            else:
+                self.inst = self.inst.next
+            return result
+    
+    def __iter__(self):
+        return BasicBlock.__inst_iterator(self)
+
+    def __reversed__(self):
+        return BasicBlock.__inst_iterator(self, reverse=True)
+
+
+class Instruction(Value):
+
+    def __init__(self, value):
+        Value.__init__(self, value)
+
+    @property
+    def next(self):
+        i = lib.LLVMGetNextInstruction(self)
+        return i and Instruction(i)
+
+    @property
+    def prev(self):
+        i = lib.LLVMGetPreviousInstruction(self)
+        return i and Instruction(i)
+
+    @property
+    def opcode(self):
+        return OpCode.from_value(lib.LLVMGetInstructionOpcode(self))
+
+class Context(LLVMObject):
+
+    def __init__(self, context=None):
+        if context is None:
+            context = lib.LLVMContextCreate()
+            LLVMObject.__init__(self, context, disposer=lib.LLVMContextDispose)
+        else:
+            LLVMObject.__init__(self, context)
+
+    @classmethod
+    def GetGlobalContext(cls):
+        return Context(lib.LLVMGetGlobalContext())
+
+class PassRegistry(LLVMObject):
+    """Represents an opaque pass registry object."""
+
+    def __init__(self):
+        LLVMObject.__init__(self,
+                            lib.LLVMGetGlobalPassRegistry())
+
 def register_library(library):
+    # Initialization/Shutdown declarations.
+    library.LLVMInitializeCore.argtypes = [PassRegistry]
+    library.LLVMInitializeCore.restype = None
+
+    library.LLVMInitializeTransformUtils.argtypes = [PassRegistry]
+    library.LLVMInitializeTransformUtils.restype = None
+
+    library.LLVMInitializeScalarOpts.argtypes = [PassRegistry]
+    library.LLVMInitializeScalarOpts.restype = None
+
+    library.LLVMInitializeObjCARCOpts.argtypes = [PassRegistry]
+    library.LLVMInitializeObjCARCOpts.restype = None
+
+    library.LLVMInitializeVectorization.argtypes = [PassRegistry]
+    library.LLVMInitializeVectorization.restype = None
+
+    library.LLVMInitializeInstCombine.argtypes = [PassRegistry]
+    library.LLVMInitializeInstCombine.restype = None
+
+    library.LLVMInitializeIPO.argtypes = [PassRegistry]
+    library.LLVMInitializeIPO.restype = None
+
+    library.LLVMInitializeInstrumentation.argtypes = [PassRegistry]
+    library.LLVMInitializeInstrumentation.restype = None
+
+    library.LLVMInitializeAnalysis.argtypes = [PassRegistry]
+    library.LLVMInitializeAnalysis.restype = None
+
+    library.LLVMInitializeIPA.argtypes = [PassRegistry]
+    library.LLVMInitializeIPA.restype = None
+
+    library.LLVMInitializeCodeGen.argtypes = [PassRegistry]
+    library.LLVMInitializeCodeGen.restype = None
+
+    library.LLVMInitializeTarget.argtypes = [PassRegistry]
+    library.LLVMInitializeTarget.restype = None
+
+    library.LLVMShutdown.argtypes = []
+    library.LLVMShutdown.restype = None
+
+    # Pass Registry declarations.
+    library.LLVMGetGlobalPassRegistry.argtypes = []
+    library.LLVMGetGlobalPassRegistry.restype = c_object_p
+
+    # Context declarations.
+    library.LLVMContextCreate.argtypes = []
+    library.LLVMContextCreate.restype = c_object_p
+
+    library.LLVMContextDispose.argtypes = [Context]
+    library.LLVMContextDispose.restype = None
+
+    library.LLVMGetGlobalContext.argtypes = []
+    library.LLVMGetGlobalContext.restype = c_object_p
+
     # Memory buffer declarations
     library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p,
             POINTER(c_object_p), POINTER(c_char_p)]
@@ -96,9 +500,131 @@ def register_library(library):
 
     library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer]
 
+    # Module declarations
+    library.LLVMModuleCreateWithName.argtypes = [c_char_p]
+    library.LLVMModuleCreateWithName.restype = c_object_p
+
+    library.LLVMDisposeModule.argtypes = [Module]
+    library.LLVMDisposeModule.restype = None
+
+    library.LLVMGetDataLayout.argtypes = [Module]
+    library.LLVMGetDataLayout.restype = c_char_p
+
+    library.LLVMSetDataLayout.argtypes = [Module, c_char_p]
+    library.LLVMSetDataLayout.restype = None
+
+    library.LLVMGetTarget.argtypes = [Module]
+    library.LLVMGetTarget.restype = c_char_p
+
+    library.LLVMSetTarget.argtypes = [Module, c_char_p]
+    library.LLVMSetTarget.restype = None
+
+    library.LLVMDumpModule.argtypes = [Module]
+    library.LLVMDumpModule.restype = None
+
+    library.LLVMPrintModuleToFile.argtypes = [Module, c_char_p,
+                                              POINTER(c_char_p)]
+    library.LLVMPrintModuleToFile.restype = bool
+
+    library.LLVMGetFirstFunction.argtypes = [Module]
+    library.LLVMGetFirstFunction.restype = c_object_p
+
+    library.LLVMGetLastFunction.argtypes = [Module]
+    library.LLVMGetLastFunction.restype = c_object_p
+
+    library.LLVMGetNextFunction.argtypes = [Function]
+    library.LLVMGetNextFunction.restype = c_object_p
+
+    library.LLVMGetPreviousFunction.argtypes = [Function]
+    library.LLVMGetPreviousFunction.restype = c_object_p
+
+    # Value declarations.
+    library.LLVMGetValueName.argtypes = [Value]
+    library.LLVMGetValueName.restype = c_char_p
+
+    library.LLVMDumpValue.argtypes = [Value]
+    library.LLVMDumpValue.restype = None
+
+    library.LLVMGetOperand.argtypes = [Value, c_uint]
+    library.LLVMGetOperand.restype = c_object_p
+
+    library.LLVMSetOperand.argtypes = [Value, Value, c_uint]
+    library.LLVMSetOperand.restype = None
+
+    library.LLVMGetNumOperands.argtypes = [Value]
+    library.LLVMGetNumOperands.restype = c_uint
+
+    # Basic Block Declarations.
+    library.LLVMGetFirstBasicBlock.argtypes = [Function]
+    library.LLVMGetFirstBasicBlock.restype = c_object_p
+
+    library.LLVMGetLastBasicBlock.argtypes = [Function]
+    library.LLVMGetLastBasicBlock.restype = c_object_p
+
+    library.LLVMGetNextBasicBlock.argtypes = [BasicBlock]
+    library.LLVMGetNextBasicBlock.restype = c_object_p
+
+    library.LLVMGetPreviousBasicBlock.argtypes = [BasicBlock]
+    library.LLVMGetPreviousBasicBlock.restype = c_object_p
+
+    library.LLVMGetFirstInstruction.argtypes = [BasicBlock]
+    library.LLVMGetFirstInstruction.restype = c_object_p
+
+    library.LLVMGetLastInstruction.argtypes = [BasicBlock]
+    library.LLVMGetLastInstruction.restype = c_object_p
+
+    library.LLVMBasicBlockAsValue.argtypes = [BasicBlock]
+    library.LLVMBasicBlockAsValue.restype = c_object_p
+
+    library.LLVMCountBasicBlocks.argtypes = [Function]
+    library.LLVMCountBasicBlocks.restype = c_uint
+
+    # Instruction Declarations.
+    library.LLVMGetNextInstruction.argtypes = [Instruction]
+    library.LLVMGetNextInstruction.restype = c_object_p
+
+    library.LLVMGetPreviousInstruction.argtypes = [Instruction]
+    library.LLVMGetPreviousInstruction.restype = c_object_p
+
+    library.LLVMGetInstructionOpcode.argtypes = [Instruction]
+    library.LLVMGetInstructionOpcode.restype = c_uint
+
 def register_enumerations():
-    for name, value in enumerations.OpCodes:
-        OpCode.register(name, value)
+    if Enums:
+        return None
+    enums = [
+        (Attribute, enumerations.Attributes),
+        (OpCode, enumerations.OpCodes),
+        (TypeKind, enumerations.TypeKinds),
+        (Linkage, enumerations.Linkages),
+        (Visibility, enumerations.Visibility),
+        (CallConv, enumerations.CallConv),
+        (IntPredicate, enumerations.IntPredicate),
+        (RealPredicate, enumerations.RealPredicate),
+        (LandingPadClauseTy, enumerations.LandingPadClauseTy),
+    ]
+    for enum_class, enum_spec in enums:
+        for name, value in enum_spec:
+            print name, value
+            enum_class.register(name, value)
+    return enums
+
+def initialize_llvm():
+    Context.GetGlobalContext()
+    p = PassRegistry()
+    lib.LLVMInitializeCore(p)
+    lib.LLVMInitializeTransformUtils(p)
+    lib.LLVMInitializeScalarOpts(p)
+    lib.LLVMInitializeObjCARCOpts(p)
+    lib.LLVMInitializeVectorization(p)
+    lib.LLVMInitializeInstCombine(p)
+    lib.LLVMInitializeIPO(p)
+    lib.LLVMInitializeInstrumentation(p)
+    lib.LLVMInitializeAnalysis(p)
+    lib.LLVMInitializeIPA(p)
+    lib.LLVMInitializeCodeGen(p)
+    lib.LLVMInitializeTarget(p)
 
 register_library(lib)
-register_enumerations()
+Enums = register_enumerations()
+initialize_llvm()