264 lines
8.5 KiB
Python
264 lines
8.5 KiB
Python
#
|
|
# 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."
|
|
|
|
import sys
|
|
|
|
import llvm
|
|
from llvm import core
|
|
from llvm.passes import TargetData, TargetTransformInfo
|
|
from llvmpy import api, extra
|
|
|
|
#===----------------------------------------------------------------------===
|
|
# import items which were moved to target module
|
|
#===----------------------------------------------------------------------===
|
|
from llvm.target import (initialize_all, initialize_target,
|
|
print_registered_targets, get_host_cpu_name, get_default_triple,
|
|
TargetMachine,
|
|
BO_BIG_ENDIAN, BO_LITTLE_ENDIAN,
|
|
CM_DEFAULT, CM_JITDEFAULT, CM_SMALL, CM_KERNEL, CM_MEDIUM, CM_LARGE,
|
|
RELOC_DEFAULT, RELOC_STATIC, RELOC_PIC, RELOC_DYNAMIC_NO_PIC)
|
|
|
|
|
|
#===----------------------------------------------------------------------===
|
|
# Generic value
|
|
#===----------------------------------------------------------------------===
|
|
|
|
class GenericValue(llvm.Wrapper):
|
|
|
|
@staticmethod
|
|
def int(ty, intval):
|
|
ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), False)
|
|
return GenericValue(ptr)
|
|
|
|
@staticmethod
|
|
def int_signed(ty, intval):
|
|
ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), True)
|
|
return GenericValue(ptr)
|
|
|
|
@staticmethod
|
|
def real(ty, floatval):
|
|
if str(ty) == 'float':
|
|
ptr = api.llvm.GenericValue.CreateFloat(float(floatval))
|
|
elif str(ty) == 'double':
|
|
ptr = api.llvm.GenericValue.CreateDouble(float(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.GenericValue.CreatePointer(int(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(ty._ptr)
|
|
|
|
def as_pointer(self):
|
|
return self._ptr.toPointer()
|
|
|
|
#===----------------------------------------------------------------------===
|
|
# Engine builder
|
|
#===----------------------------------------------------------------------===
|
|
|
|
class EngineBuilder(llvm.Wrapper):
|
|
@staticmethod
|
|
def new(module):
|
|
ptr = api.llvm.EngineBuilder.new(module._ptr)
|
|
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)
|
|
elif (sys.platform.startswith('win32') and
|
|
getattr(self, '_use_mcjit', False)):
|
|
# force ELF generation on MCJIT on win32
|
|
triple = get_default_triple()
|
|
tm = TargetMachine.new('%s-elf' % triple)
|
|
engine = self._ptr.create(tm._ptr)
|
|
else:
|
|
engine = self._ptr.create()
|
|
ee = ExecutionEngine(engine)
|
|
ee.finalize_object() # no effect for legacy JIT
|
|
return ee
|
|
|
|
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.selectTarget(triple, march, mcpu,
|
|
mattrs.split(','))
|
|
else:
|
|
ptr = self._ptr.selectTarget()
|
|
return TargetMachine(ptr)
|
|
|
|
def mcjit(self, enable):
|
|
'''Enable/disable MCJIT
|
|
'''
|
|
self._ptr.setUseMCJIT(enable)
|
|
self._use_mcjit = True
|
|
return self
|
|
|
|
#===----------------------------------------------------------------------===
|
|
# 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):
|
|
ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args)))
|
|
return GenericValue(ptr)
|
|
|
|
def get_pointer_to_named_function(self, name, abort=True):
|
|
return self._ptr.getPointerToNamedFunction(name, abort)
|
|
|
|
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.runStaticConstructorsDestructors(False)
|
|
|
|
def run_static_dtors(self):
|
|
self._ptr.runStaticConstructorsDestructors(True)
|
|
|
|
def free_machine_code_for(self, fn):
|
|
self._ptr.freeMachineCodeForFunction(fn._ptr)
|
|
|
|
def add_module(self, module):
|
|
self._ptr.addModule(module._ptr)
|
|
|
|
def remove_module(self, module):
|
|
return self._ptr.removeModule(module._ptr)
|
|
|
|
def finalize_object(self):
|
|
return self._ptr.finalizeObject()
|
|
|
|
@property
|
|
def target_data(self):
|
|
ptr = self._ptr.getDataLayout()
|
|
return TargetData(ptr)
|
|
|
|
|
|
#===----------------------------------------------------------------------===
|
|
# Dynamic Library
|
|
#===----------------------------------------------------------------------===
|
|
|
|
def dylib_add_symbol(name, ptr):
|
|
api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr)
|
|
|
|
def dylib_address_of_symbol(name):
|
|
return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name)
|
|
|
|
def dylib_import_library(filename):
|
|
"""Permanently import a dynamic library.
|
|
|
|
Returns a DynamicLibrary object
|
|
|
|
Raises RuntimeError
|
|
"""
|
|
return DynamicLibrary(filename)
|
|
|
|
|
|
class DynamicLibrary(object):
|
|
def __init__(self, filename):
|
|
"""
|
|
Raises RuntimeError
|
|
"""
|
|
self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary(
|
|
filename)
|
|
|
|
def get_address_of_symbol(self, symbol):
|
|
"""
|
|
Get the address of `symbol` (str) as integer
|
|
"""
|
|
return self._ptr.getAddressOfSymbol(symbol)
|