folding the code into the main Analysis library. There already wasn't much of a distinction between Analysis and IPA. A number of the passes in Analysis are actually IPA passes, and there doesn't seem to be any advantage to separating them. Moreover, it makes it hard to have interactions between analyses that are both local and interprocedural. In trying to make the Alias Analysis infrastructure work with the new pass manager, it becomes particularly awkward to navigate this split. I've tried to find all the places where we referenced this, but I may have missed some. I have also adjusted the C API to continue to be equivalently functional after this change. Differential Revision: http://reviews.llvm.org/D12075 llvm-svn: 245318
627 lines
18 KiB
Python
627 lines
18 KiB
Python
#===- core.py - Python LLVM Bindings -------------------------*- python -*--===#
|
|
#
|
|
# The LLVM Compiler Infrastructure
|
|
#
|
|
# This file is distributed under the University of Illinois Open Source
|
|
# License. See LICENSE.TXT for details.
|
|
#
|
|
#===------------------------------------------------------------------------===#
|
|
|
|
from .common import LLVMObject
|
|
from .common import c_object_p
|
|
from .common import get_library
|
|
|
|
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 LLVMEnumeration(object):
|
|
"""Represents an individual LLVM enumeration."""
|
|
|
|
def __init__(self, name, value):
|
|
self.name = name
|
|
self.value = value
|
|
|
|
def __repr__(self):
|
|
return '%s.%s' % (self.__class__.__name__,
|
|
self.name)
|
|
|
|
@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 %s: %d' % (cls.__name__,
|
|
value))
|
|
|
|
return result
|
|
|
|
@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 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."""
|
|
|
|
_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."""
|
|
|
|
def __init__(self, filename=None):
|
|
"""Create a new memory buffer.
|
|
|
|
Currently, we support creating from the contents of a file at the
|
|
specified filename.
|
|
"""
|
|
if filename is None:
|
|
raise Exception("filename argument must be defined")
|
|
|
|
memory = c_object_p()
|
|
out = c_char_p(None)
|
|
|
|
result = lib.LLVMCreateMemoryBufferWithContentsOfFile(filename,
|
|
byref(memory), byref(out))
|
|
|
|
if result:
|
|
raise Exception("Could not create memory buffer: %s" % out.value)
|
|
|
|
LLVMObject.__init__(self, memory, disposer=lib.LLVMDisposeMemoryBuffer)
|
|
|
|
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.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)]
|
|
library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool
|
|
|
|
library.LLVMGetBufferSize.argtypes = [MemoryBuffer]
|
|
|
|
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():
|
|
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.LLVMInitializeCodeGen(p)
|
|
lib.LLVMInitializeTarget(p)
|
|
|
|
register_library(lib)
|
|
Enums = register_enumerations()
|
|
initialize_llvm()
|