llvm-6502/bindings/python/llvm/core.py
Michael Gottesman abaa85d88d [python-bindings] Added support for getting/setting operands of values and getting the number of operands of a value.
Also in the process did some cleanups for BasicBlock.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190477 91177308-0d34-0410-b5e6-96231b3b80d8
2013-09-11 01:38:12 +00:00

541 lines
16 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",
"OpCode",
"MemoryBuffer",
"Module",
"Value",
"Function",
"BasicBlock",
"Instruction",
"Context",
"PassRegistry"
]
lib = get_library()
class OpCode(object):
"""Represents an individual OpCode enumeration."""
_value_map = {}
def __init__(self, name, value):
self.name = name
self.value = value
def __repr__(self):
return 'OpCode.%s' % self.name
@staticmethod
def from_value(value):
"""Obtain an OpCode instance from a numeric value."""
result = OpCode._value_map.get(value, None)
if result is None:
raise ValueError('Unknown OpCode: %d' % value)
return result
@staticmethod
def register(name, value):
"""Registers a new OpCode 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)
opcode = OpCode(name, value)
OpCode._value_map[value] = opcode
setattr(OpCode, name, opcode)
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))
c = 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)]
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():
for name, value in enumerations.OpCodes:
OpCode.register(name, value)
def initialize_llvm():
c = 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()
initialize_llvm()