Update old API to use the new binding.
Have not run the testsuite yet.
This commit is contained in:
parent
2d8c6f0a41
commit
a97b26415e
4 changed files with 739 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
class Wrapper(object):
|
class Wrapper(object):
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
|
assert ptr
|
||||||
self.__ptr = ptr
|
self.__ptr = ptr
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -9,3 +10,6 @@ class Wrapper(object):
|
||||||
|
|
||||||
def _extract_ptrs(objs):
|
def _extract_ptrs(objs):
|
||||||
return [x._ptr for x in objs]
|
return [x._ptr for x in objs]
|
||||||
|
|
||||||
|
class LLVMException(Exception):
|
||||||
|
pass
|
||||||
|
|
|
||||||
30
llvm/core.py
30
llvm/core.py
|
|
@ -1,3 +1,33 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008-10, Mahadevan R All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of this software, nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
||||||
334
llvm/ee.py
334
llvm/ee.py
|
|
@ -0,0 +1,334 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008-10, Mahadevan R All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of this software, nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"Execution Engine and related classes."
|
||||||
|
|
||||||
|
try:
|
||||||
|
from cStringIO import StringIO
|
||||||
|
except ImportError:
|
||||||
|
from StringIO import StringIO
|
||||||
|
import contextlib
|
||||||
|
|
||||||
|
import llvm
|
||||||
|
from llvm import core
|
||||||
|
from llvmpy import api
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Enumerations
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
BO_BIG_ENDIAN = 0
|
||||||
|
BO_LITTLE_ENDIAN = 1
|
||||||
|
|
||||||
|
# CodeModel
|
||||||
|
CM_DEFAULT = api.llvm.CodeModel.Model.Default
|
||||||
|
CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault
|
||||||
|
CM_SMALL = api.llvm.CodeModel.Model.Small
|
||||||
|
CM_KERNEL = api.llvm.CodeModel.Model.Kernel
|
||||||
|
CM_MEDIUM = api.llvm.CodeModel.Model.Medium
|
||||||
|
CM_LARGE = api.llvm.CodeModel.Model.Large
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Generic value
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class GenericValue(llvm.Wrapper):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def int(ty, intval):
|
||||||
|
ptr = api.llvm.CreateInt(ty._ptr, intval, False)
|
||||||
|
return GenericValue(ptr)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def int_signed(ty, intval):
|
||||||
|
ptr = api.llvm.CreateInt(ty._ptr, intval, True)
|
||||||
|
return GenericValue(ptr)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def real(ty, floatval):
|
||||||
|
if str(ty) == 'float':
|
||||||
|
ptr = api.llvm.CreateFloat(floatval)
|
||||||
|
elif str(ty) == 'double':
|
||||||
|
ptr = api.llvm.CreateDouble(floatval)
|
||||||
|
else:
|
||||||
|
raise Exception('Unreachable')
|
||||||
|
return GenericValue(ptr)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def pointer(addr):
|
||||||
|
'''
|
||||||
|
One argument version takes (addr).
|
||||||
|
Two argument version takes (ty, addr). [Deprecated]
|
||||||
|
|
||||||
|
`ty` is unused.
|
||||||
|
`addr` is an integer representing an address.
|
||||||
|
|
||||||
|
'''
|
||||||
|
ptr = api.llvm.CreatePointer(addr)
|
||||||
|
return GenericValue(ptr)
|
||||||
|
|
||||||
|
def as_int(self):
|
||||||
|
return self._ptr.toUnsignedInt()
|
||||||
|
|
||||||
|
def as_int_signed(self):
|
||||||
|
return self._ptr.toSignedInt()
|
||||||
|
|
||||||
|
def as_real(self, ty):
|
||||||
|
return self._ptr.toFloat()
|
||||||
|
|
||||||
|
def as_pointer(self):
|
||||||
|
return self._ptr.toPointer()
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Engine builder
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class EngineBuilder(llvm.Wrapper):
|
||||||
|
@staticmethod
|
||||||
|
def new(module):
|
||||||
|
ptr = api.llvm.EngineBuilder.new(module)
|
||||||
|
return EngineBuilder(ptr)
|
||||||
|
|
||||||
|
def force_jit(self):
|
||||||
|
self._ptr.setEngineKind(api.llvm.EngineKind.Kind.JIT)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def force_interpreter(self):
|
||||||
|
self._ptr.setEngineKind(api.llvm.EngineKind.Kind.Interpreter)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def opt(self, level):
|
||||||
|
'''
|
||||||
|
level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive]
|
||||||
|
'''
|
||||||
|
assert 0 <= level <= 3
|
||||||
|
self._ptr.setOptLevel = level
|
||||||
|
return self
|
||||||
|
|
||||||
|
def mattrs(self, string):
|
||||||
|
'''set machine attributes as a comma/space separated string
|
||||||
|
|
||||||
|
e.g: +sse,-3dnow
|
||||||
|
'''
|
||||||
|
self._ptr.setMAttrs(string.split(','))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def create(self, tm=None):
|
||||||
|
'''
|
||||||
|
tm --- Optional. Provide a TargetMachine. Ownership is transfered
|
||||||
|
to the returned execution engine.
|
||||||
|
'''
|
||||||
|
if tm is not None:
|
||||||
|
engine = self._ptr.create(tm._ptr)
|
||||||
|
else:
|
||||||
|
engine = self._ptr.create()
|
||||||
|
return ExecutionEngine(engine)
|
||||||
|
|
||||||
|
def select_target(self, *args):
|
||||||
|
'''get the corresponding target machine
|
||||||
|
|
||||||
|
Accept no arguments or (triple, march, mcpu, mattrs)
|
||||||
|
'''
|
||||||
|
if args:
|
||||||
|
triple, march, mcpu, mattrs = args
|
||||||
|
ptr = self._ptr.select_target(triple, march, mcpu,
|
||||||
|
mattrs.split(','))
|
||||||
|
else:
|
||||||
|
ptr = self._ptr.select_target()
|
||||||
|
return TargetMachine(ptr)
|
||||||
|
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Execution engine
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class ExecutionEngine(llvm.Wrapper):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def new(module, force_interpreter=False):
|
||||||
|
eb = EngineBuilder.new(module)
|
||||||
|
if force_interpreter:
|
||||||
|
eb.force_interpreter()
|
||||||
|
return eb.create()
|
||||||
|
|
||||||
|
def disable_lazy_compilation(self, disabled=True):
|
||||||
|
self._ptr.DisableLazyCompilation(disabled)
|
||||||
|
|
||||||
|
def run_function(self, fn, args):
|
||||||
|
return self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args))
|
||||||
|
|
||||||
|
def get_pointer_to_function(self, fn):
|
||||||
|
return self._ptr.getPointerToFunction(fn._ptr)
|
||||||
|
|
||||||
|
def get_pointer_to_global(self, val):
|
||||||
|
return self._ptr.getPointerToGlobal(val._ptr)
|
||||||
|
|
||||||
|
def add_global_mapping(self, gvar, addr):
|
||||||
|
assert addr >= 0, "Address cannot not be negative"
|
||||||
|
self._ptr.addGlobalMapping(gvar._ptr, addr)
|
||||||
|
|
||||||
|
def run_static_ctors(self):
|
||||||
|
self._ptr.runStaticConstructorDestructors(False)
|
||||||
|
|
||||||
|
def run_static_dtors(self):
|
||||||
|
self._ptr.runStaticConstructorDestructors(True)
|
||||||
|
|
||||||
|
def free_machine_code_for(self, fn):
|
||||||
|
self.freeMachineCodeForFunction(fn._ptr)
|
||||||
|
|
||||||
|
def add_module(self, module):
|
||||||
|
self._ptr.addModule(module._ptr)
|
||||||
|
|
||||||
|
def remove_module(self, module):
|
||||||
|
return self._ptr.removeModule(module._ptr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_data(self):
|
||||||
|
ptr = self._ptr.getDataLayout()
|
||||||
|
return TargetData(ptr)
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Target machine
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
def print_registered_targets():
|
||||||
|
'''
|
||||||
|
Note: print directly to stdout
|
||||||
|
'''
|
||||||
|
llvm.TargetRegistry.printRegisteredTargetsForVersion()
|
||||||
|
|
||||||
|
def get_host_cpu_name():
|
||||||
|
'''return the string name of the host CPU
|
||||||
|
'''
|
||||||
|
return llvm.sys.getHostCPUName()
|
||||||
|
|
||||||
|
def get_default_triple():
|
||||||
|
'''return the target triple of the host in str-rep
|
||||||
|
'''
|
||||||
|
return llvm.sys.getDefaultTargetTriple()
|
||||||
|
|
||||||
|
|
||||||
|
class TargetMachine(llvm.Wrapper):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT):
|
||||||
|
if not triple:
|
||||||
|
triple = get_default_triple()
|
||||||
|
if not cpu:
|
||||||
|
cpu = get_host_cpu_name()
|
||||||
|
with contextlib.closing(StringIO) as error:
|
||||||
|
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
|
||||||
|
if not target:
|
||||||
|
raise llvm.LLVMException(error)
|
||||||
|
if not target.hasTargetMachine():
|
||||||
|
raise llvm.LLVMException(target, "No target machine.")
|
||||||
|
target_options = api.llvm.TargetOptions()
|
||||||
|
tm = target.createTargetMachine(triple, cpu, features,
|
||||||
|
target_options,
|
||||||
|
api.llvm.Reloc.Model.Default,
|
||||||
|
cm, opt)
|
||||||
|
if not tm:
|
||||||
|
raise llvm.LLVMException("Cannot create target machine")
|
||||||
|
return TargetMachine(ptr)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT):
|
||||||
|
'''create a targetmachine given an architecture name
|
||||||
|
|
||||||
|
For a list of architectures,
|
||||||
|
use: `llc -help`
|
||||||
|
|
||||||
|
For a list of available CPUs,
|
||||||
|
use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help`
|
||||||
|
|
||||||
|
For a list of available attributes (features),
|
||||||
|
use: `llvm-as < /dev/null | llc -march=xyz -mattr=help`
|
||||||
|
'''
|
||||||
|
triple = api.llvm.Triple.new()
|
||||||
|
with contextlib.closing(StringIO) as error:
|
||||||
|
target = api.llvm.TargetMachine.lookupTarget(arch, triple, error)
|
||||||
|
if not target:
|
||||||
|
raise llvm.LLVMException(error)
|
||||||
|
if not target.hasTargetMachine():
|
||||||
|
raise llvm.LLVMException(target, "No target machine.")
|
||||||
|
target_options = api.llvm.TargetOptions()
|
||||||
|
tm = target.createTargetMachine(str(triple), cpu, features,
|
||||||
|
target_options,
|
||||||
|
api.llvm.Reloc.Model.Default,
|
||||||
|
cm, opt)
|
||||||
|
if not tm:
|
||||||
|
raise llvm.LLVMException("Cannot create target machine")
|
||||||
|
return TargetMachine(ptr)
|
||||||
|
|
||||||
|
def _emit_file(self, module, cgft):
|
||||||
|
pm = api.llvm.PassManager.new()
|
||||||
|
os = api.extra.make_raw_ostream_for_printing()
|
||||||
|
failed = self._ptr.addPassesToEmitFile(pm, os, cgft)
|
||||||
|
pm.run(module)
|
||||||
|
return os.str()
|
||||||
|
|
||||||
|
def emit_assembly(self, module):
|
||||||
|
'''returns byte string of the module as assembly code of the target machine
|
||||||
|
'''
|
||||||
|
CGFT = api.llvm.TargetMachine.CodeGenFileType
|
||||||
|
return self._emit_file(module, CGFT.CGFT_AssemblyFile)
|
||||||
|
|
||||||
|
def emit_object(self, module):
|
||||||
|
'''returns byte string of the module as native code of the target machine
|
||||||
|
'''
|
||||||
|
CGFT = api.llvm.TargetMachine.CodeGenFileType
|
||||||
|
return self._emit_file(module, CGFT.CGFT_ObjectFile)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_data(self):
|
||||||
|
'''get target data of this machine
|
||||||
|
'''
|
||||||
|
return TargetData(self._ptr.getDataLayout)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_name(self):
|
||||||
|
return self._ptr.getTarget().getName()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_short_description(self):
|
||||||
|
return self._ptr.getTarget().getShortDescription()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def triple(self):
|
||||||
|
return self._ptr.getTargetTriple()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu(self):
|
||||||
|
return self._ptr.getTargetCPU()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def feature_string(self):
|
||||||
|
return self._ptr.getTargetFeatureString()
|
||||||
|
|
||||||
371
llvm/passes.py
371
llvm/passes.py
|
|
@ -0,0 +1,371 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008-10, Mahadevan R All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of this software, nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Pass managers and passes.
|
||||||
|
|
||||||
|
This module provides the LLVM pass managers and the passes themselves.
|
||||||
|
All transformation passes listed at http://www.llvm.org/docs/Passes.html
|
||||||
|
are available.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import llvm # top-level, for common stuff
|
||||||
|
import llvm.core as core # module, function etc.
|
||||||
|
from llvmpy import api
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Pass manager builder
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class PassManagerBuilder(llvm.Wrapper):
|
||||||
|
@staticmethod
|
||||||
|
def new():
|
||||||
|
return PassManagerBuilder(api.llvm.PassManagerBuilder())
|
||||||
|
|
||||||
|
def populate(self, pm):
|
||||||
|
if isinstance(pm, FunctionPassManager):
|
||||||
|
self._ptr.populateFunctionPassManager(pm._ptr)
|
||||||
|
else:
|
||||||
|
self._ptr.populateModulePassManager(pm._ptr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def opt_level(self):
|
||||||
|
return self._ptr.OptLevel
|
||||||
|
|
||||||
|
@opt_level.setter
|
||||||
|
def _set_opt_level(self, optlevel):
|
||||||
|
self._ptr.OptLevel = optlevel
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size_level(self):
|
||||||
|
return self._ptr.SizeLevel
|
||||||
|
|
||||||
|
@size_level.setter
|
||||||
|
def _set_size_level(self, sizelevel):
|
||||||
|
self._ptr.SizeLevel = sizelevel
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vectorize(self):
|
||||||
|
return self._ptr.Vectorize
|
||||||
|
|
||||||
|
@vectorize.setter
|
||||||
|
def _set_vectorize(self, enable):
|
||||||
|
self._ptr.Vectroize = enable
|
||||||
|
|
||||||
|
@property
|
||||||
|
def loop_vectorize(self):
|
||||||
|
try:
|
||||||
|
return self._ptr.LoopVectorize
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@loop_vectorize.setter
|
||||||
|
def loop_vectorize(self, enable):
|
||||||
|
if llvm.version >= (3, 2):
|
||||||
|
self._ptr.LoopVectorize = enable
|
||||||
|
elif enable:
|
||||||
|
warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def disable_unit_at_a_time(self):
|
||||||
|
return self._ptr.DisableUnitAtATime
|
||||||
|
|
||||||
|
@disable_unit_at_a_time.setter
|
||||||
|
def disable_unit_at_a_time(self, disable):
|
||||||
|
self._ptr.DisableUnitAtATime = disable
|
||||||
|
|
||||||
|
@property
|
||||||
|
def disable_unroll_loops(self):
|
||||||
|
return self._ptr.DisableUnrollLoops
|
||||||
|
|
||||||
|
@disable_unroll_loops.setter
|
||||||
|
def disable_unroll_loops(self, disable):
|
||||||
|
self._ptr.DisableUnrollLoops = disable
|
||||||
|
|
||||||
|
@property
|
||||||
|
def disable_simplify_lib_calls(self):
|
||||||
|
return self._ptr.DisableSimplifyLibCalls
|
||||||
|
|
||||||
|
@disable_simplify_lib_calls.setter
|
||||||
|
def disable_simplify_lib_calls(self, disable):
|
||||||
|
self._ptr.DisableSimplifyLibCalls = disable
|
||||||
|
|
||||||
|
def use_inliner_with_threshold(self, threshold):
|
||||||
|
self._ptr.Inliner = api.llvm.createFunctionInliningPass(threshold)
|
||||||
|
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Pass manager
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class PassManager(llvm.Wrapper):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def new():
|
||||||
|
return PassManager(api.llvm.PassManager.new())
|
||||||
|
|
||||||
|
def add(self, pass_obj):
|
||||||
|
'''Add a pass to the pass manager.
|
||||||
|
|
||||||
|
pass_obj --- Either a Pass instance, a string name of a pass
|
||||||
|
'''
|
||||||
|
if isinstance(pass_obj, Pass):
|
||||||
|
self._ptr.add(pass_obj._ptr)
|
||||||
|
else:
|
||||||
|
self._add_pass(str(pass_obj))
|
||||||
|
|
||||||
|
def _add_pass(self, pass_name):
|
||||||
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
|
a_pass = passreg.getPassInfo(pass_name)
|
||||||
|
if not a_pass:
|
||||||
|
assert pass_name not in PASSES, "Registered but not found?"
|
||||||
|
raise llvm.LLVMException('Invalid pass name "%s"' % pass_name)
|
||||||
|
self._ptr.add(a_pass)
|
||||||
|
|
||||||
|
def run(self, module):
|
||||||
|
return self._ptr.run(module._ptr)
|
||||||
|
|
||||||
|
class FunctionPassManager(PassManager):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def new(module):
|
||||||
|
ptr = api.llvm.FunctionPassManager.new(module)
|
||||||
|
return FunctionPassManager(ptr)
|
||||||
|
|
||||||
|
def __init__(self, ptr):
|
||||||
|
PassManager.__init__(self, ptr)
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
self._ptr.doInitization()
|
||||||
|
|
||||||
|
def run(self, fn):
|
||||||
|
return self._ptr.run(fn)
|
||||||
|
|
||||||
|
def finalize(self):
|
||||||
|
self._ptr.doFinalization()
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Passes
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class Pass(llvm.Wrapper):
|
||||||
|
'''Pass Inferface
|
||||||
|
'''
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def new(name):
|
||||||
|
'''Create a new pass by name.
|
||||||
|
|
||||||
|
Note: Not all pass has a default constructor. LLVM will kill
|
||||||
|
the process if an the pass requires arguments to construct.
|
||||||
|
The error cannot be caught.
|
||||||
|
'''
|
||||||
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
|
a_pass = passreg.getPassInfo(pass_name)
|
||||||
|
p = Pass(a_pass)
|
||||||
|
p.__name = name
|
||||||
|
return p
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
'''The name used in PassRegistry.
|
||||||
|
'''
|
||||||
|
return p.__name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def description(self):
|
||||||
|
return self._ptr.getPassName()
|
||||||
|
|
||||||
|
def dump(self):
|
||||||
|
return self._ptr.dump()
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Target data
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class TargetData(Pass):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def new(strrep):
|
||||||
|
ptr = api.llvm.DataLayout.new(strrep)
|
||||||
|
return TargetData(ptr)
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
return TargetData.new(str(self))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self._ptr.getStringRepresentation()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def byte_order(self):
|
||||||
|
if self._ptr.isLittleEndian():
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pointer_size(self):
|
||||||
|
return self._ptr.getPointerSize()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_integer_type(self):
|
||||||
|
return self._ptr.core.IntegerType(core.Type.getInt32Ty())
|
||||||
|
|
||||||
|
def size(self, ty):
|
||||||
|
return self._ptr.getTypeSizeInBits(ty._ptr)
|
||||||
|
|
||||||
|
def store_size(self, ty):
|
||||||
|
return self._ptr.getTypeStoreSize(ty._ptr)
|
||||||
|
|
||||||
|
def abi_size(self, ty):
|
||||||
|
return self._ptr.getTypeAllocSize(ty._ptr)
|
||||||
|
|
||||||
|
def abi_alignment(self, ty):
|
||||||
|
return self._ptr.getABITypeAlignment(ty._ptr)
|
||||||
|
|
||||||
|
def callframe_alignment(self, ty):
|
||||||
|
return self._ptr.getCallFrameTypeAlignment(ty._ptr)
|
||||||
|
|
||||||
|
def preferred_alignment(self, ty_or_gv):
|
||||||
|
if isinstance(ty_or_gv, core.Type):
|
||||||
|
return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr)
|
||||||
|
elif isinstance(ty_or_gv, core.GlobalVariable):
|
||||||
|
return self._ptr._core.getPreferredAlignment(ty_or_gv._ptr)
|
||||||
|
else:
|
||||||
|
raise core.LLVMException("argument is neither a type nor a global variable")
|
||||||
|
|
||||||
|
def element_at_offset(self, ty, ofs):
|
||||||
|
return self._ptr.getStructLayout(ty).getElementContainingOffset(ofs)
|
||||||
|
|
||||||
|
def offset_of_element(self, ty, el):
|
||||||
|
return self._ptr.getStructLayout(ty).getElementOffset(el)
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Target Library Info
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
class TargetLibraryInfo(Pass):
|
||||||
|
@staticmethod
|
||||||
|
def new(triple):
|
||||||
|
triple = api.llvm.Triple.new(str(triple))
|
||||||
|
ptr = api.llvm.TargetLibraryInfo.new(triple)
|
||||||
|
return TargetLibraryInfo(ptr)
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Helpers
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
|
||||||
|
inline_threshold=2000, pm=True, fpm=True, mod=None):
|
||||||
|
'''
|
||||||
|
tm --- The TargetMachine for which the passes are optimizing for.
|
||||||
|
The TargetMachine must stay alive until the pass managers
|
||||||
|
are removed.
|
||||||
|
opt --- [0-3] Optimization level. Default to 2.
|
||||||
|
loop_vectorize --- [boolean] Whether to use loop-vectorizer.
|
||||||
|
vectorize --- [boolean] Whether to use basic-block vectorizer.
|
||||||
|
inline_threshold --- [int] Threshold for the inliner.
|
||||||
|
features --- [str] CPU feature string.
|
||||||
|
pm --- [boolean] Whether to build a module-level pass-manager.
|
||||||
|
fpm --- [boolean] Whether to build a function-level pass-manager.
|
||||||
|
mod --- [Module] The module object for the FunctionPassManager.
|
||||||
|
'''
|
||||||
|
if pm:
|
||||||
|
pm = PassManager.new()
|
||||||
|
if fpm:
|
||||||
|
if not mod:
|
||||||
|
raise TypeError("Keyword 'mod' must be defined")
|
||||||
|
fpm = FunctionPassManager.new(mod)
|
||||||
|
|
||||||
|
# Populate PassManagers with target specific passes
|
||||||
|
pmb = PassManagerBuilder.new()
|
||||||
|
pmb.opt_level = opt
|
||||||
|
pmb.vectorize = vectorize
|
||||||
|
pmb.loop_vectorize = loop_vectorize
|
||||||
|
if inline_threshold:
|
||||||
|
pmb.use_inliner_with_threshold(inline_threshold)
|
||||||
|
if pm:
|
||||||
|
pm.add(tm.target_data.clone())
|
||||||
|
pm.add(TargetLibraryInfo.new(tm.triple))
|
||||||
|
if llvm.version >= (3, 2):
|
||||||
|
pm.add(TargetTransformInfo.new(tm))
|
||||||
|
pmb.populate(pm)
|
||||||
|
|
||||||
|
if fpm:
|
||||||
|
fpm.add(tm.target_data)
|
||||||
|
fpm.add(TargetLibraryInfo.new(tm.triple))
|
||||||
|
if llvm.version >= (3, 2):
|
||||||
|
fpm.add(TargetTransformInfo.new(tm))
|
||||||
|
pmb.populate(fpm)
|
||||||
|
fpm.initialize()
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm)
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Misc.
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
# Intialize passes
|
||||||
|
PASSES = None
|
||||||
|
|
||||||
|
def _dump_all_passes():
|
||||||
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
|
for name, desc in passreg.enumerate():
|
||||||
|
yield name, desc
|
||||||
|
|
||||||
|
def _initialize_passes():
|
||||||
|
global PASSES
|
||||||
|
|
||||||
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
|
|
||||||
|
api.llvm.initializeCore(passreg)
|
||||||
|
api.llvm.initializeScalarOpts(passreg)
|
||||||
|
api.llvm.initializeVectorization(passreg)
|
||||||
|
api.llvm.initializeIPO(passreg)
|
||||||
|
api.llvm.initializeAnalysis(passreg)
|
||||||
|
api.llvm.initializeIPA(passreg)
|
||||||
|
api.llvm.initializeTransformUtils(passreg)
|
||||||
|
api.llvm.initializeInstCombine(passreg)
|
||||||
|
api.llvm.initializeInstrumentation(passreg)
|
||||||
|
api.llvm.initializeTarget(passreg)
|
||||||
|
|
||||||
|
PASSES = dict(_dump_all_passes())
|
||||||
|
|
||||||
|
# build globals
|
||||||
|
def transform(name):
|
||||||
|
return "PASS_%s" % (name.upper().replace('-', '_'))
|
||||||
|
|
||||||
|
global_symbols = globals()
|
||||||
|
for i in PASSES:
|
||||||
|
assert i not in global_symbols
|
||||||
|
global_symbols[transform(i)] = i
|
||||||
|
|
||||||
|
_initialize_passes()
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue