From a97b26415e7e21d63abfe66ed9c31b3e9a1d1e7d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 18:15:22 -0600 Subject: [PATCH] Update old API to use the new binding. Have not run the testsuite yet. --- llvm/__init__.py | 4 + llvm/core.py | 30 ++++ llvm/ee.py | 334 ++++++++++++++++++++++++++++++++++++++++++ llvm/passes.py | 371 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 739 insertions(+) diff --git a/llvm/__init__.py b/llvm/__init__.py index 23f3f4d..4cf374c 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,5 +1,6 @@ class Wrapper(object): def __init__(self, ptr): + assert ptr self.__ptr = ptr @property @@ -9,3 +10,6 @@ class Wrapper(object): def _extract_ptrs(objs): return [x._ptr for x in objs] + +class LLVMException(Exception): + pass diff --git a/llvm/core.py b/llvm/core.py index 2f7adb5..3c3e027 100644 --- a/llvm/core.py +++ b/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: from cStringIO import StringIO except ImportError: diff --git a/llvm/ee.py b/llvm/ee.py index e69de29..8523998 100644 --- a/llvm/ee.py +++ b/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() + diff --git a/llvm/passes.py b/llvm/passes.py index e69de29..545a19d 100644 --- a/llvm/passes.py +++ b/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() +