mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
ae65e281f3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
641 lines
18 KiB
Python
641 lines
18 KiB
Python
#===- core.py - Python LLVM Bindings -------------------------*- python -*--===#
|
|
#
|
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# See https://llvm.org/LICENSE.txt for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
#
|
|
#===------------------------------------------------------------------------===#
|
|
from __future__ import print_function
|
|
|
|
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
|
|
|
|
import sys
|
|
|
|
__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
|
|
|
|
if sys.version_info.major == 2:
|
|
next = __next__
|
|
|
|
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
|
|
|
|
if sys.version_info.major == 2:
|
|
next = __next__
|
|
|
|
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
|
|
|
|
if sys.version_info.major == 2:
|
|
next = __next__
|
|
|
|
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.LLVMInitializeAggressiveInstCombiner.argtypes = [PassRegistry]
|
|
library.LLVMInitializeAggressiveInstCombiner.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()
|