From 020032b57881968ba477be80dc365e8eba2b2a48 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 25 Apr 2013 14:10:57 -0500 Subject: [PATCH 001/155] Update docs --- docs/gh-pages.py | 2 +- docs/source/doc/getting_started.rst | 51 ++++++++++++++++------------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/docs/gh-pages.py b/docs/gh-pages.py index dd30e28..3ee5d20 100755 --- a/docs/gh-pages.py +++ b/docs/gh-pages.py @@ -30,7 +30,7 @@ from subprocess import Popen, PIPE, CalledProcessError, check_call pages_dir = 'gh-pages' html_dir = '_build/html' pdf_dir = '_build/latex' -pages_repo = 'git@github.com:llvmpy/llvmpy-doc.git' +pages_repo = 'https://github.com/llvmpy/llvmpy-doc.git' #----------------------------------------------------------------------------- # Functions diff --git a/docs/source/doc/getting_started.rst b/docs/source/doc/getting_started.rst index f9b9c56..53c2982 100644 --- a/docs/source/doc/getting_started.rst +++ b/docs/source/doc/getting_started.rst @@ -38,7 +38,7 @@ supported, for a variety of reasons. Versions -------- -llvmpy 0.9 requires version 3.1 of LLVM. It may not work with +llvmpy 0.11.2 uses LLVM 3.2 (or at least 3.1). It may not work with previous versions. llvmpy has been built and tested with Python 2.7 and 3.2. It should work with @@ -65,22 +65,6 @@ It does not matter which compiler LLVM itself was built with (``g++``, ``llvm-g++`` or any other); llvmpy can be built with any compiler. It has been tried only with gcc/g++ though. - -LLVM and ``--enable-pic`` -------------------------- - -The result of an LLVM build is a set of static libraries and object -files. The llvmpy contains an extension package that is built into a -shared object (\_core.so) which links to these static libraries and -object files. It is therefore required that the LLVM libraries and -object files be built with the ``-fPIC`` option (generate position -independent code). Be sure to use the ``--enable-pic`` option while -configuring LLVM (default is no PIC), like this: - -.. code-block:: bash - - $ ~/llvm ./configure --enable-pic --enable-optimized - llvm-config ----------- @@ -98,13 +82,34 @@ is different from that of 'root', so even if ``llvm-config`` is in your Steps ----- -Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to -LLVM's 'configure'. +1. Get and extract LLVM 3.2 source tarball from + `llvm.org `_. Then, ``cd`` into + the extracted directory. -Get llvmpy and install it: +2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``. + **Note**: Without the ``--enable-optimized`` flag, debug build will be + selected. Unless you are developing LLVM or llvmpy, it is recommended + that the flag is used to reduce build time and binary size. + + **Note**: Use prefix to select the installation path. It is recommended + to separate your custom build from the default system package. Please + replace ``LLVM_INSTALL_PATH`` with your own path. -.. code-block:: bash +3. Run ``REQUIRES_RTTI=1 make`` to build. - $ git clone git@github.com:numba/llvmpy.git - $ cd llvmpy $ python setup.py install + **Note**: With LLVM 3.2, the default build configuration has C++ RTTI + disabled. However, llvmpy requires RTTI. + +4. Get llvm-py and install it:: + + $ git clone git@github.com:llvmpy/llvmpy.git + $ cd llvmpy + $ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install + + Run the tests:: + + $ python -c "import llvm; llvm.test()" + +5. See documentation at 'http://www.llvmpy.org' and examples + under 'test'. From e74b26f84c8f7431df5e5e3e3e5992ec0494b5bb Mon Sep 17 00:00:00 2001 From: Conner Bryan Date: Sat, 27 Apr 2013 09:01:32 -0300 Subject: [PATCH 002/155] Add methods to instructions to retrieve metadata and determine if metadata exists for the instruction. --- llvm/core.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/core.py b/llvm/core.py index 719c8a4..d621579 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1688,6 +1688,12 @@ class Instruction(User): def set_metadata(self, kind, metadata): self._ptr.setMetadata(kind, metadata._ptr) + + def has_metadata(self): + return self._ptr.hasMetadata() + + def get_metadata(self, kind): + return self._ptr.getMetadata(kind) @property def opcode(self): From a5f6f2596f56986e9c3f2959415500a642a3b5f9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 25 Apr 2013 17:52:40 -0500 Subject: [PATCH 003/155] Fix ignored name arg --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index d621579..a51a3b3 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -730,7 +730,7 @@ class Type(llvm.Wrapper): otherwise, creates a literal type.""" context = api.llvm.getGlobalContext() is_packed = True - ptr = api.llvm.StructType.create(context) + ptr = api.llvm.StructType.create(context, name) ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) return StructType(ptr) From b754e803ec3fa02b196982496073167bb014e290 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 2 May 2013 12:17:38 -0500 Subject: [PATCH 004/155] Cleanup --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index a51a3b3..0d0d1ae 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1688,7 +1688,7 @@ class Instruction(User): def set_metadata(self, kind, metadata): self._ptr.setMetadata(kind, metadata._ptr) - + def has_metadata(self): return self._ptr.hasMetadata() From a357987597832a9c24d195302404328fd1f8e436 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 May 2013 10:45:02 -0500 Subject: [PATCH 005/155] Allow initialization of other targets. - Remove PTX/NVPTX targets from default built and init --- llvm/core.py | 25 ------------------ llvm/ee.py | 18 +++++++++++++ llvm/test_llvmpy.py | 7 ++--- llvmpy/gen/binding.py | 3 ++- llvmpy/src/Support/TargetSelect.py | 20 +++++++------- setup.py | 42 +++++++++++------------------- 6 files changed, 48 insertions(+), 67 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 0d0d1ae..478728b 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2305,28 +2305,3 @@ if api.llvm.InitializeNativeTargetAsmPrinter(): # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") -#===----------------------------------------------------------------------=== -# Initialization -#===----------------------------------------------------------------------=== - -HAS_PTX = HAS_NVPTX = False - -if True: # use PTX? - try: - api.LLVMInitializePTXTarget() - api.LLVMInitializePTXTargetInfo() - api.LLVMInitializePTXTargetMC() - api.LLVMInitializePTXAsmPrinter() - HAS_PTX = True - except AttributeError: - try: - api.LLVMInitializeNVPTXTarget() - api.LLVMInitializeNVPTXTargetInfo() - api.LLVMInitializeNVPTXTargetMC() - api.LLVMInitializeNVPTXAsmPrinter() - HAS_NVPTX = True - except AttributeError: - pass - - - diff --git a/llvm/ee.py b/llvm/ee.py index 1ef16ae..017d0e0 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -222,6 +222,24 @@ class ExecutionEngine(llvm.Wrapper): # Target machine #===----------------------------------------------------------------------=== +def initialize_target(target, noraise=False): + """Initialize target by name. + It is safe to initialize the same target multiple times. + """ + prefix = 'LLVMInitialize' + postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter'] + try: + for postfix in postfixes: + getattr(api, '%s%s%s' % (prefix, target, postfix))() + except AttributeError: + if noraise: + return False + else: + raise + else: + return True + + def print_registered_targets(): ''' Note: print directly to stdout diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 945ac41..b228138 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -636,12 +636,13 @@ class TestTargetMachines(TestCase): self.assertTrue(le.get_host_cpu_name()) def test_ptx(self): - if lc.HAS_PTX: + if le.initialize_target('PTX', noraise=True): arch = 'ptx64' - elif lc.HAS_NVPTX: + elif le.initialize_target('NVPTX', noraise=True): arch = 'nvptx64' else: return # skip this test + print(arch) m, func = self._build_module() func.calling_convention = lc.CC_PTX_KERNEL # set calling conv @@ -650,7 +651,7 @@ class TestTargetMachines(TestCase): self.assertTrue(ptxtm.cpu) ptxasm = ptxtm.emit_assembly(m) self.assertIn('foo', ptxasm) - if lc.HAS_NVPTX: + if arch == 'nvptx64': self.assertIn('.address_size 64', ptxasm) self.assertIn('sm_20', ptxasm) diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index eeccab1..8006fd9 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -841,7 +841,8 @@ class Attr(object): # # Pick-up environ var # -PTX_SUPPORT = os.environ.get('LLVMPY_PTX_SUPPORT', '') + +TARGETS_BUILT = os.environ.get('LLVM_TARGETS_BUILT', '').split() def _parse_llvm_version(ver): import re diff --git a/llvmpy/src/Support/TargetSelect.py b/llvmpy/src/Support/TargetSelect.py index 85e1d74..3e638bc 100644 --- a/llvmpy/src/Support/TargetSelect.py +++ b/llvmpy/src/Support/TargetSelect.py @@ -1,8 +1,11 @@ +import os from binding import * from ..namespace import llvm, default llvm.includes.add('llvm/Support/TargetSelect.h') + + InitializeNativeTarget = llvm.Function('InitializeNativeTarget') InitializeNativeTargetAsmPrinter = llvm.Function( 'InitializeNativeTargetAsmPrinter', cast(Bool, bool)) @@ -11,20 +14,15 @@ InitializeNativeTargetAsmParser = llvm.Function( InitializeNativeTargetDisassembler = llvm.Function( 'InitializeNativeTargetDisassembler', cast(Bool, bool)) - #InitializeAllTargets = llvm.Function('InitializeAllTargets') #InitializeAllTargetInfos = llvm.Function('InitializeAllTargetInfos') #InitializeAllTargetMCs = llvm.Function('InitializeAllTargetMCs') #InitializeAllAsmPrinters = llvm.Function('InitializeAllAsmPrinters') -if PTX_SUPPORT == 'PTX': - LLVMInitializePTXTarget = default.Function('LLVMInitializePTXTarget') - LLVMInitializePTXTargetInfo = default.Function('LLVMInitializePTXTargetInfo') - LLVMInitializePTXTargetMC = default.Function('LLVMInitializePTXTargetMC') - LLVMInitializePTXAsmPrinter = default.Function('LLVMInitializePTXAsmPrinter') +for target in TARGETS_BUILT: + decls = 'Target', 'TargetInfo', 'TargetMC', 'AsmPrinter' + for k in map(lambda x: 'LLVMInitialize%s%s' % (target, x), decls): + if k == 'LLVMInitializeCppBackendAsmPrinter': + continue + globals()[k] = default.Function(k) -if PTX_SUPPORT == 'NVPTX': - LLVMInitializeNVPTXTarget = default.Function('LLVMInitializeNVPTXTarget') - LLVMInitializeNVPTXTargetInfo = default.Function('LLVMInitializeNVPTXTargetInfo') - LLVMInitializeNVPTXTargetMC = default.Function('LLVMInitializeNVPTXTargetMC') - LLVMInitializeNVPTXAsmPrinter = default.Function('LLVMInitializeNVPTXAsmPrinter') diff --git a/setup.py b/setup.py index 8202c5f..b74ec71 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,4 @@ +from __future__ import print_function import os import sys from subprocess import Popen, PIPE, check_call @@ -37,6 +38,11 @@ def run_llvm_config(extra_args): llvm_version = run_llvm_config(['--version']) print('LLVM version = %r' % llvm_version) +targets_built = run_llvm_config(['--targets-built']) +include_targets = set(os.environ.get('LLVMPY_TARGETS', '').split()) +targets_built = ' '.join(set(targets_built.split()) & include_targets) +print('LLVM targets = %s' % targets_built) + def get_libs_and_objs(components): parts = run_llvm_config(['--libs'] + components).split() libs = [] @@ -97,36 +103,20 @@ def determine_to_use_dynlink(libdir, llvm_version): dynlink = determine_to_use_dynlink(libdir, llvm_version) -ptx_support = '' + if dynlink: print('Using dynamic linking') libs_core = ['LLVM-%s' % llvm_version] objs_core = [] else: + extra_components = set() + for tm in map(lambda s: s.lower(), targets_built.split()): + postfixes = ['', 'asmprinter', 'codegen', 'desc', 'info'] + for postfix in postfixes: + extra_components.add(tm + postfix) enabled_components = set(get_enabled_components()) - ptx_components = set(['ptx', - 'ptxasmprinter', - 'ptxcodegen', - 'ptxdesc', - 'ptxinfo']) - nvptx_components = set(['nvptx', - 'nvptxasmprinter', - 'nvptxcodegen', - 'nvptxdesc', - 'nvptxinfo']) - - extra_components = [] - if (nvptx_components & enabled_components) == nvptx_components: - print("Using NVPTX") - extra_components.extend(nvptx_components) - ptx_support = 'NVPTX' - elif (ptx_components & enabled_components) == ptx_components: - print("Using PTX") - extra_components.extend(ptx_components) - ptx_support = 'PTX' - else: - print("No CUDA support") + extra_components = list(extra_components & enabled_components) libs_core, objs_core = get_libs_and_objs( ['core', 'analysis', 'scalaropts', 'executionengine', @@ -136,15 +126,13 @@ else: + extra_components) if sys.platform == 'win32': - # If no PTX lib got added, disable PTX in the build - if 'LLVMPTXCodeGen' in libs_core: - ptx_support = 'ptx' + pass else: macros.append(('_GNU_SOURCE', None)) # auto generate bindings -os.environ['LLVMPY_PTX_SUPPORT'] = ptx_support os.environ['LLVMPY_LLVM_VERSION'] = llvm_version +os.environ['LLVM_TARGETS_BUILT'] = targets_built check_call([sys.executable, 'llvmpy/build.py']) # generate shared objects From 489d8056b944cd583a6f436d79535a7b75a1d548 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 May 2013 10:57:38 -0500 Subject: [PATCH 006/155] Fix error msg --- llvm/ee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/ee.py b/llvm/ee.py index 017d0e0..e4ee4bc 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -298,7 +298,7 @@ class TargetMachine(llvm.Wrapper): with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error) if not target: - raise llvm.LLVMException(error) + raise llvm.LLVMException(error.getvalue()) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") target_options = api.llvm.TargetOptions.new() From 3e0dc2507010b8f655ff07c698de387ac1ffb187 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 10 May 2013 10:58:51 -0500 Subject: [PATCH 007/155] Silent capsule memory logger. --- llvmpy/capsule.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 9c1e86a..f66836f 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -3,6 +3,15 @@ from collections import defaultdict import logging logger = logging.getLogger(__name__) +def silent_logger(): + ''' + Silent logger for unless we have a error message. + ''' + logger.setLevel(logging.ERROR) + +# comment out the line below to re-enable logging at DEBUG level. +silent_logger() + def set_debug(enabled): ''' Side-effect: configure logger with it is not configured. From c1184271188a0c7d4cea1a74d241fc2e53b89936 Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Tue, 14 May 2013 04:26:10 -0500 Subject: [PATCH 008/155] Don't get name field from literal structure and avoid a segfault. --- llvm/core.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index 478728b..453f1a8 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -879,7 +879,10 @@ class StructType(Type): self._ptr.setName(name) def _get_name(self): - return self._ptr.getName() + if self._ptr.isLiteral(): + return "" + else: + return self._ptr.getName() name = property(_get_name, _set_name) From 08bed7dd7432692e681f2a2e9d3fe773d7943162 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 May 2013 10:32:37 -0500 Subject: [PATCH 009/155] Fix bug with Module.to_bitcode() (Reported by Jun Koi) --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index 453f1a8..b085339 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -535,7 +535,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = BytesIO + fileobj = BytesIO() api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() From f4b320ff09e7b9756e1b799b4df20fd4e7482520 Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Tue, 14 May 2013 00:51:45 -0500 Subject: [PATCH 010/155] Fix a few erros. Add an array type --- llvm_array/__init__.py | 2 + llvm_array/array.py | 144 +++++++++++++++++++++++++++++++++ llvmpy/src/Function.py | 7 +- llvmpy/src/Value.py | 1 + llvmpy/src/ValueSymbolTable.py | 13 +++ setup.py | 1 + 6 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 llvm_array/__init__.py create mode 100644 llvm_array/array.py create mode 100644 llvmpy/src/ValueSymbolTable.py diff --git a/llvm_array/__init__.py b/llvm_array/__init__.py new file mode 100644 index 0000000..f6a0f3f --- /dev/null +++ b/llvm_array/__init__.py @@ -0,0 +1,2 @@ +from __future__ import absolute_imports +from .array.py import * diff --git a/llvm_array/array.py b/llvm_array/array.py new file mode 100644 index 0000000..12df60e --- /dev/null +++ b/llvm_array/array.py @@ -0,0 +1,144 @@ +# This should be moved to llvmpy +# +# There are different array kinds parameterized by eltype and nd +# +# Contiguous or Fortran +# struct { +# eltype *data; +# intp shape[nd]; +# } contiguous_array(eltype, nd) +# +# struct { +# eltype *data; +# diminfo shape[nd]; +# } strided_array(eltype, nd) +# +# struct { +# eltype *data; +# intp shape[nd]; +# intp stride[nd]; +# } strided_soa_array(eltype, nd) +# +# struct { +# intp dim; +# intp stride; +#} diminfo +# + +import llvm.core as lc +from llvm.core import Type +import llvm_cbuilder.shortnames as C + +CONTIGUOUS = 1 << 8 +STRIDED = CONTIGUOUS + 1 +STRIDED_SOA = CONTIGUOUS + 2 + +array_kinds = (CONTIGUOUS, STRIDED, STRIDED_SOA) + +void_type = C.void +int_type = C.int +char_type = C.char +int16_type = C.int16 +intp_type = C.intp + +diminfo_type = Type.struct([intp_type, # shape + intp_type # stride + ], name='diminfo') + +# This is the way we define LLVM arrays. +def cont_array_type(nd, el_type=char_type, name=''): + terms = [Type.pointer(el_type), # data + Type.array(intp_type, nd) # shape + ] + return Type.struct(terms, name=name) + +def strided_array_type(nd, el_type=char_type, name=''): + terms = [Type.pointer(el_type), # data + Type.array(diminfo_type, nd) # diminfo + ] + return Type.struct(terms, name=name) + +def strided_soa_type(nd, el_type=char_type, name=''): + terms = [Type.pointer(el_type), # data + Type.array(intp_type, nd), # shape[nd] + Type.array(intp_type, nd) # strides[nd] + ] + return Type.struct(terms, name=name) + +def check_array(arrtyp): + if not isinstance(arrtyp, lc.StructType): + return None + if arrtyp.element_count not in [2, 3]: + return None + if not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType): + return None + + data_type = arrtyp.elements[0].pointee + s1 = arrtyp.elements[1] + nd = s1.count + + if arrtyp.element_count == 3: + if not isinstance(arrtyp.elements[2], lc.ArrayType): + return None + s2 = arrtyp.elements[2] + if s1.element != intp_type or s2.element != intp_type: + return None + if s1.count != s2.count: + return None + return STRIDED_SOA, nd, data_type + + if s1.element == diminfo_type: + return STRIDED, nd, data_type + elif s1.element == intp_type: + return CONTIGUOUS, nd, data_type + else: + return None + +def is_cont_array(arrtyp): + if not isinstance(arrtyp, lc.StructType): + return False + if arrtyp.element_count != 2 or \ + not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType): + return False + if arrtyp.elements[1].element != intp_type: + return False + return True + +def is_strided_array(arrtyp, kind=diminfo_type): + if not isinstance(arrtyp, lc.StructType): + return False + if arrtyp.element_count != 2 or \ + not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType): + return False + if arrtyp.elements[1].element != kind: + return False + return True + +def is_strided_soa_array(arrtyp): + if not isinstance(arrtyp, lc.StructType): + return False + if arrtyp.element_count != 3 or \ + not isinstance(arrtyp.elements[0], lc.PointerType) or \ + not isinstance(arrtyp.elements[1], lc.ArrayType) or \ + not isinstance(arrtyp.elements[2], lc.ArrayType): + return False + s1, s2 = arrtyp.elements[1:] + if s1.element != intp_type or s2.element != intp_type: + return False + if s1.count != s2.count: + return False + return True + +def test(): + arr = cont_array_type(5) + assert check_array(arr) == (CONTIGUOUS, 5, char_type) + arr = strided_array_type(4) + assert check_array(arr) == (STRIDED, 4, char_type) + arr = strided_soa_type(3) + assert check_array(arr) == (STRIDED_SOA, 3, char_type) + +if __name__ == '__main__': + test() \ No newline at end of file diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index 55a50d9..c453fd1 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -2,6 +2,7 @@ from binding import * from .namespace import llvm from .Value import GlobalValue, Constant, Function, Argument, Value from .BasicBlock import BasicBlock +from .ValueSymbolTable import ValueSymbolTable from .Attributes import Attributes from .Type import Type from .DerivedTypes import FunctionType @@ -23,7 +24,7 @@ class Function: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) - hasGC = Method(cast(bool, Bool)) + hasGC = Method(cast(Bool, bool)) getGC = Method(cast(ConstCharPtr, str)) setGC = Method(Void, cast(str, ConstCharPtr)) @@ -31,6 +32,7 @@ class Function: getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) getEntryBlock = Method(ref(BasicBlock)) + getValueSymbolTable = Method(ref(ValueSymbolTable)) copyAttributesFrom = Method(Void, ptr(GlobalValue)) @@ -49,6 +51,9 @@ class Function: addFnAttr = Method(Void, Attributes.AttrVal) removeFnAttr = Method(Void, ref(Attributes)) + #hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal) + + Create = Method(ptr(Function)) eraseFromParent = Method() eraseFromParent.disowning = True diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index fb9c3cc..922850f 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -8,6 +8,7 @@ MDNode = llvm.Class(Value) MDString = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) +ValueSymbolTable = llvm.Class() Constant = llvm.Class(User) GlobalValue = llvm.Class(Constant) Function = llvm.Class(GlobalValue) diff --git a/llvmpy/src/ValueSymbolTable.py b/llvmpy/src/ValueSymbolTable.py new file mode 100644 index 0000000..862febc --- /dev/null +++ b/llvmpy/src/ValueSymbolTable.py @@ -0,0 +1,13 @@ +from binding import * +from .Value import ValueSymbolTable, Value +from .ADT.StringRef import StringRef + +@ValueSymbolTable +class ValueSymbolTable: + new = Constructor() + delete = Destructor() + lookup = Method(ptr(Value), cast(str, StringRef)) + empty = Method(cast(Bool, bool)) + size = Method(cast(Unsigned, int)) + dump = Method(Void) + diff --git a/setup.py b/setup.py index b74ec71..1dc8af8 100644 --- a/setup.py +++ b/setup.py @@ -180,6 +180,7 @@ setup( packages = ['llvm', 'llvm.workaround', 'llvm_cbuilder', 'llpython', + 'llvm_array', 'llvmpy.api', 'llvmpy.api.llvm'], py_modules = ['llvmpy', 'llvmpy._capsule', From db7323771fbc72b9dd08781445797f906be43915 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 14 May 2013 11:23:50 -0500 Subject: [PATCH 011/155] Fix PR --- llvmpy/src/Function.py | 7 ++++++- llvmpy/src/ValueSymbolTable.py | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index c453fd1..04c3e65 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -1,6 +1,7 @@ from binding import * from .namespace import llvm from .Value import GlobalValue, Constant, Function, Argument, Value +from .Module import Module from .BasicBlock import BasicBlock from .ValueSymbolTable import ValueSymbolTable from .Attributes import Attributes @@ -53,7 +54,11 @@ class Function: removeFnAttr = Method(Void, ref(Attributes)) #hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal) - Create = Method(ptr(Function)) + Create = StaticMethod(ptr(Function), + ptr(FunctionType), + GlobalValue.LinkageTypes, + cast(str, ConstCharPtr), + ptr(Module)).require_only(2) eraseFromParent = Method() eraseFromParent.disowning = True diff --git a/llvmpy/src/ValueSymbolTable.py b/llvmpy/src/ValueSymbolTable.py index 862febc..7e8890c 100644 --- a/llvmpy/src/ValueSymbolTable.py +++ b/llvmpy/src/ValueSymbolTable.py @@ -4,6 +4,7 @@ from .ADT.StringRef import StringRef @ValueSymbolTable class ValueSymbolTable: + _include_ = 'llvm/ValueSymbolTable.h' new = Constructor() delete = Destructor() lookup = Method(ptr(Value), cast(str, StringRef)) From 331f71f26f13431b07c9c5d37dda935fdbcd8059 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 16 May 2013 11:34:27 -0500 Subject: [PATCH 012/155] Fix hashing of llvm type --- llvm/core.py | 4 +++- llvm/test_llvmpy.py | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index b085339..d25dec1 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -800,6 +800,9 @@ class Type(llvm.Wrapper): def __str__(self): return str(self._ptr) + def __hash__(self): + return hash(self._ptr) + def __eq__(self, rhs): return self._ptr is rhs._ptr @@ -901,7 +904,6 @@ class StructType(Type): def is_layout_identical(self, other): return self._ptr.isLayoutIdentical(other._ptr) - class ArrayType(Type): """Represents an array type.""" _type_ = api.llvm.ArrayType diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index b228138..36ea022 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1258,6 +1258,32 @@ class TestStruct(TestCase): tests.append(TestStruct) +# --------------------------------------------------------------------------- + +class TestTypeHash(TestCase): + def test_scalar_type(self): + i32a = Type.int(32) + i32b = Type.int(32) + i64a = Type.int(64) + i64b = Type.int(64) + ts = set([i32a, i32b, i64a, i64b]) + self.assertTrue(len(ts)) + self.assertTrue(i32a in ts) + self.assertTrue(i64b in ts) + + def test_struct_type(self): + ta = Type.struct([Type.int(32), Type.float()]) + tb = Type.struct([Type.int(32), Type.float()]) + tc = Type.struct([Type.int(32), Type.int(32), Type.float()]) + ts = set([ta, tb, tc]) + self.assertTrue(len(ts) == 2) + self.assertTrue(ta in ts) + self.assertTrue(tb in ts) + self.assertTrue(tc in ts) + +tests.append(TestTypeHash) + + # --------------------------------------------------------------------------- def run(verbosity=1): From 592f9c698819e9efacd7d340eb27a03fd887770f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 16 May 2013 13:45:59 -0500 Subject: [PATCH 013/155] Allow retrieving argument attributes --- llvm/core.py | 38 ++++++++++++++++++++++++++++++++++++++ llvm/test_llvmpy.py | 18 ++++++++++++++++++ llvmpy/src/Argument.py | 10 ++++++++++ 3 files changed, 66 insertions(+) diff --git a/llvm/core.py b/llvm/core.py index d25dec1..74d7101 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1372,6 +1372,8 @@ class GlobalVariable(GlobalValue): class Argument(Value): _type_ = api.llvm.Argument + _valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS, + ATTR_NO_CAPTURE, ATTR_STRUCT_RET]) def add_attribute(self, attr): context = api.llvm.getGlobalContext() @@ -1379,6 +1381,9 @@ class Argument(Value): attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttr(attrs) + if attr not in self: + raise ValueError("Attribute %s is not valid for arg %s" % + (attr, self)) def remove_attribute(self, attr): context = api.llvm.getGlobalContext() @@ -1400,6 +1405,39 @@ class Argument(Value): alignment = property(_get_alignment, _set_alignment) + def __contains__(self, attr): + if attr == ATTR_BY_VAL: + return self.has_by_val() + elif attr == ATTR_NEST: + return self.has_nest() + elif attr == ATTR_NO_ALIAS: + return self.has_no_alias() + elif attr == ATTR_NO_CAPTURE: + return self.has_no_capture() + elif attr == ATTR_STRUCT_RET: + return self.has_struct_ret() + else: + raise ValueError('invalid attribute for argument') + + @property + def arg_no(self): + return self._ptr.getArgNo() + + def has_by_val(self): + return self._ptr.hasByValAttr() + + def has_nest(self): + return self._ptr.hasNestAttr() + + def has_no_alias(self): + return self._ptr.hasNoAliasAttr() + + def has_no_capture(self): + return self._ptr.hasNoCaptureAttr() + + def has_struct_ret(self): + return self._ptr.hasStructRetAttr() + class Function(GlobalValue): _type_ = api.llvm.Function diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 36ea022..3ecffff 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1283,6 +1283,24 @@ class TestTypeHash(TestCase): tests.append(TestTypeHash) +# --------------------------------------------------------------------------- + +class TestArgAttr(TestCase): + def test_arg_attr(self): + m = Module.new('oifjda') + vptr = Type.pointer(Type.float()) + sptr = Type.pointer(Type.struct([])) + fnty = Type.function(Type.void(), [vptr] * 5) + func = m.add_function(fnty, 'foo') + attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST, + lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE] + for i, attr in enumerate(attrs): + arg = func.args[i] + self.assertEqual(i, arg.arg_no) + arg.add_attribute(attr) + self.assertTrue(attr in func.args[i]) + +tests.append(TestArgAttr) # --------------------------------------------------------------------------- diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index babbd1c..6262147 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -13,3 +13,13 @@ class Argument: removeAttr = Method(Void, ref(Attributes)) getParamAlignment = Method(cast(Unsigned, int)) + getArgNo = Method(cast(Unsigned, int)) + + hasByValAttr = Method(cast(Bool, bool)) + hasNestAttr = Method(cast(Bool, bool)) + hasNoAliasAttr = Method(cast(Bool, bool)) + hasNoCaptureAttr = Method(cast(Bool, bool)) + hasStructRetAttr = Method(cast(Bool, bool)) + + if LLVM_VERSION > (3, 2): + hasReturnedAttr = Method(cast(Bool, bool)) From 96dc9076134a7507e88cdf7d715f937d09a8a083 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 16 May 2013 13:46:57 -0500 Subject: [PATCH 014/155] Make enum integer constants prints name --- llvm/core.py | 451 +++++++++++++++++++++++++++++---------------------- 1 file changed, 256 insertions(+), 195 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 74d7101..9cb1946 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -47,144 +47,189 @@ from llvmpy import api #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== +class Enum(int): + '''Overload integer to print the name of the enum. + ''' + def __repr__(self): + return '%s(%d)' % (type(self).__name__, self) + + @classmethod + def declare(cls): + scope = globals() + for name in filter(lambda s: s.startswith(cls.prefix), dir(cls)): + n = getattr(cls, name) + typ = type(name, (cls,), {}) + scope[name] = typ(n) + # type id (llvm::Type::TypeID) -TYPE_VOID = api.llvm.Type.TypeID.VoidTyID -TYPE_HALF = api.llvm.Type.TypeID.HalfTyID -TYPE_FLOAT = api.llvm.Type.TypeID.FloatTyID -TYPE_DOUBLE = api.llvm.Type.TypeID.DoubleTyID -TYPE_X86_FP80 = api.llvm.Type.TypeID.X86_FP80TyID -TYPE_FP128 = api.llvm.Type.TypeID.FP128TyID -TYPE_PPC_FP128 = api.llvm.Type.TypeID.PPC_FP128TyID -TYPE_LABEL = api.llvm.Type.TypeID.LabelTyID -TYPE_INTEGER = api.llvm.Type.TypeID.IntegerTyID -TYPE_FUNCTION = api.llvm.Type.TypeID.FunctionTyID -TYPE_STRUCT = api.llvm.Type.TypeID.StructTyID -TYPE_ARRAY = api.llvm.Type.TypeID.ArrayTyID -TYPE_POINTER = api.llvm.Type.TypeID.PointerTyID -TYPE_VECTOR = api.llvm.Type.TypeID.VectorTyID -TYPE_METADATA = api.llvm.Type.TypeID.MetadataTyID -TYPE_X86_MMX = api.llvm.Type.TypeID.X86_MMXTyID +class TypeEnum(Enum): + prefix = 'TYPE_' + TypeID = api.llvm.Type.TypeID + + TYPE_VOID = TypeID.VoidTyID + TYPE_HALF = TypeID.HalfTyID + TYPE_FLOAT = TypeID.FloatTyID + TYPE_DOUBLE = TypeID.DoubleTyID + TYPE_X86_FP80 = TypeID.X86_FP80TyID + TYPE_FP128 = TypeID.FP128TyID + TYPE_PPC_FP128 = TypeID.PPC_FP128TyID + TYPE_LABEL = TypeID.LabelTyID + TYPE_INTEGER = TypeID.IntegerTyID + TYPE_FUNCTION = TypeID.FunctionTyID + TYPE_STRUCT = TypeID.StructTyID + TYPE_ARRAY = TypeID.ArrayTyID + TYPE_POINTER = TypeID.PointerTyID + TYPE_VECTOR = TypeID.VectorTyID + TYPE_METADATA = TypeID.MetadataTyID + TYPE_X86_MMX = TypeID.X86_MMXTyID + +TypeEnum.declare() # value IDs (llvm::Value::ValueTy enum) # According to the doxygen docs, it is not a good idea to use these enums. # There are more values than those declared. -VALUE_ARGUMENT = api.llvm.Value.ValueTy.ArgumentVal -VALUE_BASIC_BLOCK = api.llvm.Value.ValueTy.BasicBlockVal -VALUE_FUNCTION = api.llvm.Value.ValueTy.FunctionVal -VALUE_GLOBAL_ALIAS = api.llvm.Value.ValueTy.GlobalAliasVal -VALUE_GLOBAL_VARIABLE = api.llvm.Value.ValueTy.GlobalVariableVal -VALUE_UNDEF_VALUE = api.llvm.Value.ValueTy.UndefValueVal -VALUE_BLOCK_ADDRESS = api.llvm.Value.ValueTy.BlockAddressVal -VALUE_CONSTANT_EXPR = api.llvm.Value.ValueTy.ConstantExprVal -VALUE_CONSTANT_AGGREGATE_ZERO = api.llvm.Value.ValueTy.ConstantAggregateZeroVal -VALUE_CONSTANT_DATA_ARRAY = api.llvm.Value.ValueTy.ConstantDataArrayVal -VALUE_CONSTANT_DATA_VECTOR = api.llvm.Value.ValueTy.ConstantDataVectorVal -VALUE_CONSTANT_INT = api.llvm.Value.ValueTy.ConstantIntVal -VALUE_CONSTANT_FP = api.llvm.Value.ValueTy.ConstantFPVal -VALUE_CONSTANT_ARRAY = api.llvm.Value.ValueTy.ConstantArrayVal -VALUE_CONSTANT_STRUCT = api.llvm.Value.ValueTy.ConstantStructVal -VALUE_CONSTANT_VECTOR = api.llvm.Value.ValueTy.ConstantVectorVal -VALUE_CONSTANT_POINTER_NULL = api.llvm.Value.ValueTy.ConstantPointerNullVal -VALUE_MD_NODE = api.llvm.Value.ValueTy.MDNodeVal -VALUE_MD_STRING = api.llvm.Value.ValueTy.MDStringVal -VALUE_INLINE_ASM = api.llvm.Value.ValueTy.InlineAsmVal -VALUE_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.PseudoSourceValueVal -VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.FixedStackPseudoSourceValueVal -VALUE_INSTRUCTION = api.llvm.Value.ValueTy.InstructionVal +class ValueEnum(Enum): + prefix = 'VALUE_' + ValueTy = api.llvm.Value.ValueTy + + VALUE_ARGUMENT = ValueTy.ArgumentVal + VALUE_BASIC_BLOCK = ValueTy.BasicBlockVal + VALUE_FUNCTION = ValueTy.FunctionVal + VALUE_GLOBAL_ALIAS = ValueTy.GlobalAliasVal + VALUE_GLOBAL_VARIABLE = ValueTy.GlobalVariableVal + VALUE_UNDEF_VALUE = ValueTy.UndefValueVal + VALUE_BLOCK_ADDRESS = ValueTy.BlockAddressVal + VALUE_CONSTANT_EXPR = ValueTy.ConstantExprVal + VALUE_CONSTANT_AGGREGATE_ZERO = ValueTy.ConstantAggregateZeroVal + VALUE_CONSTANT_DATA_ARRAY = ValueTy.ConstantDataArrayVal + VALUE_CONSTANT_DATA_VECTOR = ValueTy.ConstantDataVectorVal + VALUE_CONSTANT_INT = ValueTy.ConstantIntVal + VALUE_CONSTANT_FP = ValueTy.ConstantFPVal + VALUE_CONSTANT_ARRAY = ValueTy.ConstantArrayVal + VALUE_CONSTANT_STRUCT = ValueTy.ConstantStructVal + VALUE_CONSTANT_VECTOR = ValueTy.ConstantVectorVal + VALUE_CONSTANT_POINTER_NULL = ValueTy.ConstantPointerNullVal + VALUE_MD_NODE = ValueTy.MDNodeVal + VALUE_MD_STRING = ValueTy.MDStringVal + VALUE_INLINE_ASM = ValueTy.InlineAsmVal + VALUE_PSEUDO_SOURCE_VALUE = ValueTy.PseudoSourceValueVal + VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = ValueTy.FixedStackPseudoSourceValueVal + VALUE_INSTRUCTION = ValueTy.InstructionVal + +ValueEnum.declare() # instruction opcodes (from include/llvm/Instruction.def) -OPCODE_RET = 1 -OPCODE_BR = 2 -OPCODE_SWITCH = 3 -OPCODE_INDIRECT_BR = 4 -OPCODE_INVOKE = 5 -OPCODE_RESUME = 6 -OPCODE_UNREACHABLE = 7 -OPCODE_ADD = 8 -OPCODE_FADD = 9 -OPCODE_SUB = 10 -OPCODE_FSUB = 11 -OPCODE_MUL = 12 -OPCODE_FMUL = 13 -OPCODE_UDIV = 14 -OPCODE_SDIV = 15 -OPCODE_FDIV = 16 -OPCODE_UREM = 17 -OPCODE_SREM = 18 -OPCODE_FREM = 19 -OPCODE_SHL = 20 -OPCODE_LSHR = 21 -OPCODE_ASHR = 22 -OPCODE_AND = 23 -OPCODE_OR = 24 -OPCODE_XOR = 25 -OPCODE_ALLOCA = 26 -OPCODE_LOAD = 27 -OPCODE_STORE = 28 -OPCODE_GETELEMENTPTR = 29 -OPCODE_FENCE = 30 -OPCODE_ATOMICCMPXCHG = 31 -OPCODE_ATOMICRMW = 32 -OPCODE_TRUNC = 33 -OPCODE_ZEXT = 34 -OPCODE_SEXT = 35 -OPCODE_FPTOUI = 36 -OPCODE_FPTOSI = 37 -OPCODE_UITOFP = 38 -OPCODE_SITOFP = 39 -OPCODE_FPTRUNC = 40 -OPCODE_FPEXT = 41 -OPCODE_PTRTOINT = 42 -OPCODE_INTTOPTR = 43 -OPCODE_BITCAST = 44 -OPCODE_ICMP = 45 -OPCODE_FCMP = 46 -OPCODE_PHI = 47 -OPCODE_CALL = 48 -OPCODE_SELECT = 49 -OPCODE_USEROP1 = 50 -OPCODE_USEROP2 = 51 -OPCODE_VAARG = 52 -OPCODE_EXTRACTELEMENT = 53 -OPCODE_INSERTELEMENT = 54 -OPCODE_SHUFFLEVECTOR = 55 -OPCODE_EXTRACTVALUE = 56 -OPCODE_INSERTVALUE = 57 -OPCODE_LANDINGPAD = 58 +class OpcodeEnum(Enum): + prefix = 'OPCODE_' + + OPCODE_RET = 1 + OPCODE_BR = 2 + OPCODE_SWITCH = 3 + OPCODE_INDIRECT_BR = 4 + OPCODE_INVOKE = 5 + OPCODE_RESUME = 6 + OPCODE_UNREACHABLE = 7 + OPCODE_ADD = 8 + OPCODE_FADD = 9 + OPCODE_SUB = 10 + OPCODE_FSUB = 11 + OPCODE_MUL = 12 + OPCODE_FMUL = 13 + OPCODE_UDIV = 14 + OPCODE_SDIV = 15 + OPCODE_FDIV = 16 + OPCODE_UREM = 17 + OPCODE_SREM = 18 + OPCODE_FREM = 19 + OPCODE_SHL = 20 + OPCODE_LSHR = 21 + OPCODE_ASHR = 22 + OPCODE_AND = 23 + OPCODE_OR = 24 + OPCODE_XOR = 25 + OPCODE_ALLOCA = 26 + OPCODE_LOAD = 27 + OPCODE_STORE = 28 + OPCODE_GETELEMENTPTR = 29 + OPCODE_FENCE = 30 + OPCODE_ATOMICCMPXCHG = 31 + OPCODE_ATOMICRMW = 32 + OPCODE_TRUNC = 33 + OPCODE_ZEXT = 34 + OPCODE_SEXT = 35 + OPCODE_FPTOUI = 36 + OPCODE_FPTOSI = 37 + OPCODE_UITOFP = 38 + OPCODE_SITOFP = 39 + OPCODE_FPTRUNC = 40 + OPCODE_FPEXT = 41 + OPCODE_PTRTOINT = 42 + OPCODE_INTTOPTR = 43 + OPCODE_BITCAST = 44 + OPCODE_ICMP = 45 + OPCODE_FCMP = 46 + OPCODE_PHI = 47 + OPCODE_CALL = 48 + OPCODE_SELECT = 49 + OPCODE_USEROP1 = 50 + OPCODE_USEROP2 = 51 + OPCODE_VAARG = 52 + OPCODE_EXTRACTELEMENT = 53 + OPCODE_INSERTELEMENT = 54 + OPCODE_SHUFFLEVECTOR = 55 + OPCODE_EXTRACTVALUE = 56 + OPCODE_INSERTVALUE = 57 + OPCODE_LANDINGPAD = 58 + +OpcodeEnum.declare() # calling conventions -CC_C = api.llvm.CallingConv.ID.C -CC_FASTCALL = api.llvm.CallingConv.ID.Fast -CC_COLDCALL = api.llvm.CallingConv.ID.Cold -CC_GHC = api.llvm.CallingConv.ID.GHC -CC_X86_STDCALL = api.llvm.CallingConv.ID.X86_StdCall -CC_X86_FASTCALL = api.llvm.CallingConv.ID.X86_FastCall -CC_ARM_APCS = api.llvm.CallingConv.ID.ARM_APCS -CC_ARM_AAPCS = api.llvm.CallingConv.ID.ARM_AAPCS -CC_ARM_AAPCS_VFP = api.llvm.CallingConv.ID.ARM_AAPCS_VFP -CC_MSP430_INTR = api.llvm.CallingConv.ID.MSP430_INTR -CC_X86_THISCALL = api.llvm.CallingConv.ID.X86_ThisCall -CC_PTX_KERNEL = api.llvm.CallingConv.ID.PTX_Kernel -CC_PTX_DEVICE = api.llvm.CallingConv.ID.PTX_Device -CC_MBLAZE_INTR = api.llvm.CallingConv.ID.MBLAZE_INTR -CC_MBLAZE_SVOL = api.llvm.CallingConv.ID.MBLAZE_SVOL +class CCEnum(Enum): + prefix = 'CC_' + + ID = api.llvm.CallingConv.ID + + CC_C = ID.C + CC_FASTCALL = ID.Fast + CC_COLDCALL = ID.Cold + CC_GHC = ID.GHC + CC_X86_STDCALL = ID.X86_StdCall + CC_X86_FASTCALL = ID.X86_FastCall + CC_ARM_APCS = ID.ARM_APCS + CC_ARM_AAPCS = ID.ARM_AAPCS + CC_ARM_AAPCS_VFP = ID.ARM_AAPCS_VFP + CC_MSP430_INTR = ID.MSP430_INTR + CC_X86_THISCALL = ID.X86_ThisCall + CC_PTX_KERNEL = ID.PTX_Kernel + CC_PTX_DEVICE = ID.PTX_Device + CC_MBLAZE_INTR = ID.MBLAZE_INTR + CC_MBLAZE_SVOL = ID.MBLAZE_SVOL + +CCEnum.declare() # int predicates -ICMP_EQ = api.llvm.CmpInst.Predicate.ICMP_EQ -ICMP_NE = api.llvm.CmpInst.Predicate.ICMP_NE -ICMP_UGT = api.llvm.CmpInst.Predicate.ICMP_UGT -ICMP_UGE = api.llvm.CmpInst.Predicate.ICMP_UGE -ICMP_ULT = api.llvm.CmpInst.Predicate.ICMP_ULT -ICMP_ULE = api.llvm.CmpInst.Predicate.ICMP_ULE -ICMP_SGT = api.llvm.CmpInst.Predicate.ICMP_SGT -ICMP_SGE = api.llvm.CmpInst.Predicate.ICMP_SGE -ICMP_SLT = api.llvm.CmpInst.Predicate.ICMP_SLT -ICMP_SLE = api.llvm.CmpInst.Predicate.ICMP_SLE +class ICMPEnum(Enum): + prefix = 'ICMP_' + + Predicate = api.llvm.CmpInst.Predicate + ICMP_EQ = Predicate.ICMP_EQ + ICMP_NE = Predicate.ICMP_NE + ICMP_UGT = Predicate.ICMP_UGT + ICMP_UGE = Predicate.ICMP_UGE + ICMP_ULT = Predicate.ICMP_ULT + ICMP_ULE = Predicate.ICMP_ULE + ICMP_SGT = Predicate.ICMP_SGT + ICMP_SGE = Predicate.ICMP_SGE + ICMP_SLT = Predicate.ICMP_SLT + ICMP_SLE = Predicate.ICMP_SLE + +ICMPEnum.declare() # same as ICMP_xx, for backward compatibility + IPRED_EQ = ICMP_EQ IPRED_NE = ICMP_NE IPRED_UGT = ICMP_UGT @@ -197,24 +242,33 @@ IPRED_SLT = ICMP_SLT IPRED_SLE = ICMP_SLE # real predicates -FCMP_FALSE = api.llvm.CmpInst.Predicate.FCMP_FALSE -FCMP_OEQ = api.llvm.CmpInst.Predicate.FCMP_OEQ -FCMP_OGT = api.llvm.CmpInst.Predicate.FCMP_OGT -FCMP_OGE = api.llvm.CmpInst.Predicate.FCMP_OGE -FCMP_OLT = api.llvm.CmpInst.Predicate.FCMP_OLT -FCMP_OLE = api.llvm.CmpInst.Predicate.FCMP_OLE -FCMP_ONE = api.llvm.CmpInst.Predicate.FCMP_ONE -FCMP_ORD = api.llvm.CmpInst.Predicate.FCMP_ORD -FCMP_UNO = api.llvm.CmpInst.Predicate.FCMP_UNO -FCMP_UEQ = api.llvm.CmpInst.Predicate.FCMP_UEQ -FCMP_UGT = api.llvm.CmpInst.Predicate.FCMP_UGT -FCMP_UGE = api.llvm.CmpInst.Predicate.FCMP_UGE -FCMP_ULT = api.llvm.CmpInst.Predicate.FCMP_ULT -FCMP_ULE = api.llvm.CmpInst.Predicate.FCMP_ULE -FCMP_UNE = api.llvm.CmpInst.Predicate.FCMP_UNE -FCMP_TRUE = api.llvm.CmpInst.Predicate.FCMP_TRUE + +class FCMPEnum(Enum): + prefix = 'FCMP_' + + Predicate = api.llvm.CmpInst.Predicate + + FCMP_FALSE = Predicate.FCMP_FALSE + FCMP_OEQ = Predicate.FCMP_OEQ + FCMP_OGT = Predicate.FCMP_OGT + FCMP_OGE = Predicate.FCMP_OGE + FCMP_OLT = Predicate.FCMP_OLT + FCMP_OLE = Predicate.FCMP_OLE + FCMP_ONE = Predicate.FCMP_ONE + FCMP_ORD = Predicate.FCMP_ORD + FCMP_UNO = Predicate.FCMP_UNO + FCMP_UEQ = Predicate.FCMP_UEQ + FCMP_UGT = Predicate.FCMP_UGT + FCMP_UGE = Predicate.FCMP_UGE + FCMP_ULT = Predicate.FCMP_ULT + FCMP_ULE = Predicate.FCMP_ULE + FCMP_UNE = Predicate.FCMP_UNE + FCMP_TRUE = Predicate.FCMP_TRUE + +FCMPEnum.declare() # real predicates + RPRED_FALSE = FCMP_FALSE RPRED_OEQ = FCMP_OEQ RPRED_OGT = FCMP_OGT @@ -233,68 +287,69 @@ RPRED_UNE = FCMP_UNE RPRED_TRUE = FCMP_TRUE # linkages (see llvm::GlobalValue::LinkageTypes) -LINKAGE_EXTERNAL = \ - api.llvm.GlobalValue.LinkageTypes.ExternalLinkage -LINKAGE_AVAILABLE_EXTERNALLY = \ - api.llvm.GlobalValue.LinkageTypes.AvailableExternallyLinkage -LINKAGE_LINKONCE_ANY = \ - api.llvm.GlobalValue.LinkageTypes.LinkOnceAnyLinkage -LINKAGE_LINKONCE_ODR = \ - api.llvm.GlobalValue.LinkageTypes.LinkOnceODRLinkage -LINKAGE_WEAK_ANY = \ - api.llvm.GlobalValue.LinkageTypes.WeakAnyLinkage -LINKAGE_WEAK_ODR = \ - api.llvm.GlobalValue.LinkageTypes.WeakODRLinkage -LINKAGE_APPENDING = \ - api.llvm.GlobalValue.LinkageTypes.AppendingLinkage -LINKAGE_INTERNAL = \ - api.llvm.GlobalValue.LinkageTypes.InternalLinkage -LINKAGE_PRIVATE = \ - api.llvm.GlobalValue.LinkageTypes.PrivateLinkage -LINKAGE_DLLIMPORT = \ - api.llvm.GlobalValue.LinkageTypes.DLLImportLinkage -LINKAGE_DLLEXPORT = \ - api.llvm.GlobalValue.LinkageTypes.DLLExportLinkage -LINKAGE_EXTERNAL_WEAK = \ - api.llvm.GlobalValue.LinkageTypes.ExternalWeakLinkage -LINKAGE_COMMON = \ - api.llvm.GlobalValue.LinkageTypes.CommonLinkage -LINKAGE_LINKER_PRIVATE = \ - api.llvm.GlobalValue.LinkageTypes.LinkerPrivateLinkage -LINKAGE_LINKER_PRIVATE_WEAK = \ - api.llvm.GlobalValue.LinkageTypes.LinkerPrivateWeakLinkage +class LinkageEnum(Enum): + prefix = 'LINKAGE_' + LinkageTypes = api.llvm.GlobalValue.LinkageTypes + + LINKAGE_EXTERNAL = LinkageTypes.ExternalLinkage + LINKAGE_AVAILABLE_EXTERNALLY = LinkageTypes.AvailableExternallyLinkage + LINKAGE_LINKONCE_ANY = LinkageTypes.LinkOnceAnyLinkage + LINKAGE_LINKONCE_ODR = LinkageTypes.LinkOnceODRLinkage + LINKAGE_WEAK_ANY = LinkageTypes.WeakAnyLinkage + LINKAGE_WEAK_ODR = LinkageTypes.WeakODRLinkage + LINKAGE_APPENDING = LinkageTypes.AppendingLinkage + LINKAGE_INTERNAL = LinkageTypes.InternalLinkage + LINKAGE_PRIVATE = LinkageTypes.PrivateLinkage + LINKAGE_DLLIMPORT = LinkageTypes.DLLImportLinkage + LINKAGE_DLLEXPORT = LinkageTypes.DLLExportLinkage + LINKAGE_EXTERNAL_WEAK = LinkageTypes.ExternalWeakLinkage + LINKAGE_COMMON = LinkageTypes.CommonLinkage + LINKAGE_LINKER_PRIVATE = LinkageTypes.LinkerPrivateLinkage + LINKAGE_LINKER_PRIVATE_WEAK = LinkageTypes.LinkerPrivateWeakLinkage + +LinkageEnum.declare() # visibility (see llvm/GlobalValue.h) -VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility -VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility -VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility +class VisibilityEnum(Enum): + prefix = 'VISIBILITY_' + + VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility + VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility + VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility + +VisibilityEnum.declare() # parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) -ATTR_NONE = api.llvm.Attributes.AttrVal.None_ -ATTR_ZEXT = api.llvm.Attributes.AttrVal.ZExt -ATTR_SEXT = api.llvm.Attributes.AttrVal.SExt -ATTR_NO_RETURN = api.llvm.Attributes.AttrVal.NoReturn -ATTR_IN_REG = api.llvm.Attributes.AttrVal.InReg -ATTR_STRUCT_RET = api.llvm.Attributes.AttrVal.StructRet -ATTR_NO_UNWIND = api.llvm.Attributes.AttrVal.NoUnwind -ATTR_NO_ALIAS = api.llvm.Attributes.AttrVal.NoAlias -ATTR_BY_VAL = api.llvm.Attributes.AttrVal.ByVal -ATTR_NEST = api.llvm.Attributes.AttrVal.Nest -ATTR_READ_NONE = api.llvm.Attributes.AttrVal.ReadNone -ATTR_READONLY = api.llvm.Attributes.AttrVal.ReadOnly -ATTR_NO_INLINE = api.llvm.Attributes.AttrVal.NoInline -ATTR_ALWAYS_INLINE = api.llvm.Attributes.AttrVal.AlwaysInline -ATTR_OPTIMIZE_FOR_SIZE = api.llvm.Attributes.AttrVal.OptimizeForSize -ATTR_STACK_PROTECT = api.llvm.Attributes.AttrVal.StackProtect -ATTR_STACK_PROTECT_REQ = api.llvm.Attributes.AttrVal.StackProtectReq -ATTR_ALIGNMENT = api.llvm.Attributes.AttrVal.Alignment -ATTR_NO_CAPTURE = api.llvm.Attributes.AttrVal.NoCapture -ATTR_NO_REDZONE = api.llvm.Attributes.AttrVal.NoRedZone -ATTR_NO_IMPLICIT_FLOAT = api.llvm.Attributes.AttrVal.NoImplicitFloat -ATTR_NAKED = api.llvm.Attributes.AttrVal.Naked -ATTR_INLINE_HINT = api.llvm.Attributes.AttrVal.InlineHint -ATTR_STACK_ALIGNMENT = api.llvm.Attributes.AttrVal.StackAlignment +class AttrEnum(Enum): + prefix = 'ATTR_' + AttrVal = api.llvm.Attributes.AttrVal + ATTR_NONE = AttrVal.None_ + ATTR_ZEXT = AttrVal.ZExt + ATTR_SEXT = AttrVal.SExt + ATTR_NO_RETURN = AttrVal.NoReturn + ATTR_IN_REG = AttrVal.InReg + ATTR_STRUCT_RET = AttrVal.StructRet + ATTR_NO_UNWIND = AttrVal.NoUnwind + ATTR_NO_ALIAS = AttrVal.NoAlias + ATTR_BY_VAL = AttrVal.ByVal + ATTR_NEST = AttrVal.Nest + ATTR_READ_NONE = AttrVal.ReadNone + ATTR_READONLY = AttrVal.ReadOnly + ATTR_NO_INLINE = AttrVal.NoInline + ATTR_ALWAYS_INLINE = AttrVal.AlwaysInline + ATTR_OPTIMIZE_FOR_SIZE = AttrVal.OptimizeForSize + ATTR_STACK_PROTECT = AttrVal.StackProtect + ATTR_STACK_PROTECT_REQ = AttrVal.StackProtectReq + ATTR_ALIGNMENT = AttrVal.Alignment + ATTR_NO_CAPTURE = AttrVal.NoCapture + ATTR_NO_REDZONE = AttrVal.NoRedZone + ATTR_NO_IMPLICIT_FLOAT = AttrVal.NoImplicitFloat + ATTR_NAKED = AttrVal.Naked + ATTR_INLINE_HINT = AttrVal.InlineHint + ATTR_STACK_ALIGNMENT = AttrVal.StackAlignment + +AttrEnum.declare() class Module(llvm.Wrapper): """A Module instance stores all the information related to an LLVM module. @@ -1405,6 +1460,12 @@ class Argument(Value): alignment = property(_get_alignment, _set_alignment) + @property + def attributes(self): + '''Returns a set of defined attributes. + ''' + return set(attr for attr in self._valid_attrs if attr in self) + def __contains__(self, attr): if attr == ATTR_BY_VAL: return self.has_by_val() From edab81ed7e75006fbc490e691b212295aef3723f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 17 May 2013 14:05:40 -0500 Subject: [PATCH 015/155] Fix GC problem with Module when it is GCed but re-instantiate from GlobalValue.module. --- llvmpy/src/GlobalValue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index ff499f7..d954ed0 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -46,4 +46,4 @@ class GlobalValue: eraseFromParent = Method() eraseFromParent.disowning = True - getParent = Method(ptr(Module)) + getParent = Method(ownedptr(Module)) From 5b2b878f24cc5e56d8aaf5bf01757ff0594139db Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 22 May 2013 15:17:59 -0500 Subject: [PATCH 016/155] Enable MCJIT --- llvm/ee.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm/ee.py b/llvm/ee.py index e4ee4bc..7ea90d0 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -167,6 +167,11 @@ class EngineBuilder(llvm.Wrapper): ptr = self._ptr.selectTarget() return TargetMachine(ptr) + def mcjit(self, enable): + '''Enable/disable MCJIT + ''' + self._ptr.setUseMCJIT(enable) + return self #===----------------------------------------------------------------------=== # Execution engine From a0eb03b23950b9095f30e0bf15cd48d03166ab6e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 23 May 2013 11:45:15 -0500 Subject: [PATCH 017/155] Fix CompareInstruction.predicate --- llvm/core.py | 18 ++++++++++++++-- llvm/test_llvmpy.py | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 9cb1946..fd72902 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -55,12 +55,18 @@ class Enum(int): @classmethod def declare(cls): + declared = cls._declared_ = {} scope = globals() for name in filter(lambda s: s.startswith(cls.prefix), dir(cls)): n = getattr(cls, name) typ = type(name, (cls,), {}) - scope[name] = typ(n) + obj = typ(n) + declared[n] = obj + scope[name] = obj + @classmethod + def get(cls, num): + return cls._declared_[num] # type id (llvm::Type::TypeID) class TypeEnum(Enum): @@ -1872,16 +1878,24 @@ class PHINode(Instruction): class SwitchInstruction(Instruction): + _type_ = api.llvm.SwitchInst def add_case(self, const, bblk): self._ptr.addCase(const._ptr, bblk._ptr) class CompareInstruction(Instruction): + _type_ = api.llvm.CmpInst @property def predicate(self): - return self._ptr.getPredicate() + n = self._ptr.getPredicate() + try: + return ICMPEnum.get(n) + except KeyError: + return FCMPEnum.get(n) + + #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 3ecffff..e21a825 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1302,6 +1302,57 @@ class TestArgAttr(TestCase): tests.append(TestArgAttr) +# --------------------------------------------------------------------------- + +class TestSwitch(TestCase): + def test_arg_attr(self): + m = Module.new('oifjda') + fnty = Type.function(Type.void(), [Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bbdef = func.append_basic_block('') + bbsw1 = func.append_basic_block('') + bbsw2 = func.append_basic_block('') + bldr = Builder.new(bb) + + swt = bldr.switch(func.args[0], bbdef, n=2) + swt.add_case(Constant.int(Type.int(), 0), bbsw1) + swt.add_case(Constant.int(Type.int(), 1), bbsw2) + + bldr.position_at_end(bbsw1) + bldr.ret_void() + + bldr.position_at_end(bbsw2) + bldr.ret_void() + + bldr.position_at_end(bbdef) + bldr.ret_void() + + func.verify() + +tests.append(TestSwitch) + +# --------------------------------------------------------------------------- + +class TestCmp(TestCase): + def test_arg_attr(self): + m = Module.new('oifjda') + fnty = Type.function(Type.void(), [Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bldr = Builder.new(bb) + + cmpinst = bldr.icmp(lc.ICMP_ULE, func.args[0], + Constant.int(Type.int(), 123)) + self.assertTrue(repr(cmpinst.predicate).startswith('ICMP_ULE')) + self.assertEqual(cmpinst.predicate, lc.ICMP_ULE) + bldr.ret_void() + + func.verify() + +tests.append(TestCmp) + + # --------------------------------------------------------------------------- def run(verbosity=1): From 1812cff2d0e23eaaccbe609d1bd9ae69b0af568f Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Sat, 25 May 2013 13:34:14 -0500 Subject: [PATCH 018/155] Fix import problem. --- llvm_array/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_array/__init__.py b/llvm_array/__init__.py index f6a0f3f..5e807c2 100644 --- a/llvm_array/__init__.py +++ b/llvm_array/__init__.py @@ -1,2 +1,2 @@ from __future__ import absolute_imports -from .array.py import * +from .array import * From 009239713eb97ead506584652325f9ddf260557a Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Sat, 25 May 2013 13:35:37 -0500 Subject: [PATCH 019/155] Update llvm_array concepts. --- llvm_array/array.py | 261 +++++++++++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 74 deletions(-) diff --git a/llvm_array/array.py b/llvm_array/array.py index 12df60e..3cac244 100644 --- a/llvm_array/array.py +++ b/llvm_array/array.py @@ -24,19 +24,98 @@ # intp stride; #} diminfo # +# These are for low-level array-routines that need to know the number +# of dimensions at run-time (not just code-generation time): +# +# The first two are recommended +# +# struct { +# eltype *data; +# int32 nd; +# intp shape[nd]; +# } contiguous_array_nd(eltype) +# +# struct { +# eltype *data; +# int32 nd; +# diminfo shape[nd]; +# } strided_array_nd(eltype) +# +# +# Backward compatible but deprecated: +# struct { +# eltype *data; +# int32 nd; +# intp shape[nd]; +# intp stride[nd]; +# } strided_soa_array_nd(eltype) +# +# +# The most general (where the kind of array is stored as well as number +# of dimensions) +# Rarely needed. +# +# struct { +# eltype *data; +# int16 nd; +# int16 dimkind; +# ??? +# } array_nd(eltype) +# +# where ??? is run-time interpreted based on the dimkind to either: +# intp shape[nd]; for dimkind = C_CONTIGUOUS or F_CONTIGUOUS +# +# diminfo shape[nd]; for dimkind = STRIDED +# +# intp shape[ind]; +# intp strides[ind]; dimkind = STRIDED_SOA +# import llvm.core as lc from llvm.core import Type import llvm_cbuilder.shortnames as C -CONTIGUOUS = 1 << 8 -STRIDED = CONTIGUOUS + 1 -STRIDED_SOA = CONTIGUOUS + 2 +# Different Array Types +ARRAYBIT = 1<<4 +C_CONTIGUOUS = ARRAYBIT + 0 +F_CONTIGUOUS = ARRAYBIT + 1 +STRIDED = ARRAYBIT + 2 +STRIDED_SOA = ARRAYBIT + 3 -array_kinds = (CONTIGUOUS, STRIDED, STRIDED_SOA) +HAS_ND = 1<<5 +C_CONTIGUOUS_ND = C_CONTIGUOUS + HAS_ND +F_CONTIGUOUS_ND = F_CONTIGUOUS + HAS_ND +STRIDED_ND = STRIDED + HAS_ND +STRIDED_SOA_ND = STRIDED_SOA + HAS_ND + +HAS_DIMKIND = 1<<6 +C_CONTIGUOUS_DK = C_CONTIGUOUS + HAS_DIMKIND +F_CONTIGUOUS_DK = F_CONTIGUOUS + HAS_DIMKIND +STRIDED_DK = STRIDED + HAS_DIMKIND +STRIDED_SOA_DK = STRIDED_SOA + HAS_DIMKIND + +array_kinds = (C_CONTIGUOUS, F_CONTIGUOUS, STRIDED, STRIDED_SOA, + C_CONTIGUOUS_ND, F_CONTIGUOUS_ND, STRIDED_ND, STRIDED_SOA_DK, + C_CONTIGUOUS_DK, F_CONTIGUOUS_DK, STRIDED_DK, STRIDED_SOA_DK) + +_invmap = {} + +def kind_to_str(kind): + global _invmap + if not _invmap: + for key, value in globals().items(): + if isinstance(value, int) and value in array_kinds: + _invmap[value] = key + return _invmap[kind] + +def str_to_kind(str): + trial = eval(str) + if trial not in array_kinds: + raise ValueError("Invalid Array Kind") + return trial void_type = C.void -int_type = C.int +int32_type = C.int32 char_type = C.char int16_type = C.int16 intp_type = C.intp @@ -45,99 +124,133 @@ diminfo_type = Type.struct([intp_type, # shape intp_type # stride ], name='diminfo') -# This is the way we define LLVM arrays. -def cont_array_type(nd, el_type=char_type, name=''): - terms = [Type.pointer(el_type), # data - Type.array(intp_type, nd) # shape - ] - return Type.struct(terms, name=name) +_cache = {} +# This is the way we define LLVM arrays. +# CONTIGUOUS and STRIDED are strongly encouraged... +def array_type(nd, kind, el_type=char_type): + key = (kind, nd, el_type) + if _cache.has_key(key): + return _cache[key] -def strided_array_type(nd, el_type=char_type, name=''): - terms = [Type.pointer(el_type), # data - Type.array(diminfo_type, nd) # diminfo - ] - return Type.struct(terms, name=name) + base = kind & (~(HAS_ND | HAS_DIMKIND)) + if base == C_CONTIGUOUS: + dimstr = 'Array_C' + elif base == F_CONTIGUOUS: + dimstr = 'Array_F' + elif base == STRIDED: + dimstr = 'Array_S' + elif base == STRIDED_SOA: + dimstr = 'Array_A' + else: + raise TypeError("Do not understand Array kind of %d" % kind) + + terms = [Type.pointer(el_type)] # data + + if (kind & HAS_ND): + terms.append(int32_type) # nd + dimstr += '_ND' + elif (kind & HAS_DIMKIND): + terms.extend([int16_type, int16_type]) # nd, dimkind + dimstr += '_DK' + + if base in [C_CONTIGUOUS, F_CONTIGUOUS]: + terms.append(Type.array(intp_type, nd)) # shape + elif base == STRIDED: + terms.append(Type.array(diminfo_type, nd)) # diminfo + elif base == STRIDED_SOA: + terms.extend([Type.array(intp_type, nd), # shape + Type.array(intp_type, nd)]) # strides + + ret = Type.struct(terms, name=dimstr) + _cache[key] = ret + return ret -def strided_soa_type(nd, el_type=char_type, name=''): - terms = [Type.pointer(el_type), # data - Type.array(intp_type, nd), # shape[nd] - Type.array(intp_type, nd) # strides[nd] - ] - return Type.struct(terms, name=name) def check_array(arrtyp): if not isinstance(arrtyp, lc.StructType): return None - if arrtyp.element_count not in [2, 3]: - return None - if not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType): + if arrtyp.element_count not in [2, 3, 4, 5]: return None - data_type = arrtyp.elements[0].pointee - s1 = arrtyp.elements[1] + # Look through _cache and see if it's there + for key, value in _cache.items(): + if arrtyp is value: + return key + + return _raw_check_array(arrtyp) + +# Manual check +def _raw_check_array(arrtyp): + a0 = arrtyp.elements[0] + a1 = arrtyp.elements[1] + if not isinstance(a0, lc.PointerType) or \ + not (isinstance(a1, lc.ArrayType) or + (a1 == int32_type) or (a1 == int16_type)): + return None + + data_type = a0.pointee + + if arrtyp.is_literal: + c_contig = True + else: + if arrtyp.name.startswith('Array_F'): + c_contig = False + else: + c_contig = True + + + if a1 == int32_type: + num = 2 + strided = STRIDED_ND + strided_soa = STRIDED_SOA_ND + c_contiguous = C_CONTIGUOUS_ND + f_contiguous = F_CONTIGUOUS_ND + elif a1 == int16_type: + if arrtyp.element_count < 3 or arrtyp.elements[2] != int16_type: + return None + num = 3 + strided = STRIDED_DK + strided_soa = STRIDED_SOA_DK + c_contiguous = C_CONTIGUOUS_DK + f_contiguous = F_CONTIGUOUS_DK + else: + num = 1 + strided = STRIDED + strided_soa = STRIDED_SOA + c_contiguous = C_CONTIGUOUS + f_contiguous = F_CONTIGUOUS + + elcount = num + 2 + # otherwise we have lc.ArrType as element [1] + if arrtyp.element_count not in [num+1,num+2]: + return None + s1 = arrtyp.elements[num] nd = s1.count - if arrtyp.element_count == 3: - if not isinstance(arrtyp.elements[2], lc.ArrayType): + if arrtyp.element_count == elcount: + if not isinstance(arrtyp.elements[num+1], lc.ArrayType): return None - s2 = arrtyp.elements[2] + s2 = arrtyp.elements[num+1] if s1.element != intp_type or s2.element != intp_type: return None if s1.count != s2.count: return None - return STRIDED_SOA, nd, data_type + return strided_soa, nd, data_type if s1.element == diminfo_type: - return STRIDED, nd, data_type + return strided, nd, data_type elif s1.element == intp_type: - return CONTIGUOUS, nd, data_type + return c_contiguous if c_contig else f_contiguous, nd, data_type else: return None -def is_cont_array(arrtyp): - if not isinstance(arrtyp, lc.StructType): - return False - if arrtyp.element_count != 2 or \ - not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType): - return False - if arrtyp.elements[1].element != intp_type: - return False - return True - -def is_strided_array(arrtyp, kind=diminfo_type): - if not isinstance(arrtyp, lc.StructType): - return False - if arrtyp.element_count != 2 or \ - not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType): - return False - if arrtyp.elements[1].element != kind: - return False - return True - -def is_strided_soa_array(arrtyp): - if not isinstance(arrtyp, lc.StructType): - return False - if arrtyp.element_count != 3 or \ - not isinstance(arrtyp.elements[0], lc.PointerType) or \ - not isinstance(arrtyp.elements[1], lc.ArrayType) or \ - not isinstance(arrtyp.elements[2], lc.ArrayType): - return False - s1, s2 = arrtyp.elements[1:] - if s1.element != intp_type or s2.element != intp_type: - return False - if s1.count != s2.count: - return False - return True def test(): - arr = cont_array_type(5) - assert check_array(arr) == (CONTIGUOUS, 5, char_type) - arr = strided_array_type(4) + arr = array_type(5, C_CONTIGUOUS) + assert check_array(arr) == (C_CONTIGUOUS, 5, char_type) + arr = array_type(4, STRIDED) assert check_array(arr) == (STRIDED, 4, char_type) - arr = strided_soa_type(3) + arr = array_type(3, STRIDED_SOA) assert check_array(arr) == (STRIDED_SOA, 3, char_type) if __name__ == '__main__': From 6b333e84aa249869401ab5c02dd0cf95b43d6984 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Mon, 27 May 2013 12:22:13 +0100 Subject: [PATCH 020/155] Use error message string from BytesIO --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index fd72902..9c8501e 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -504,7 +504,7 @@ class Module(llvm.Wrapper): mode, errmsg) if failed: - raise llvm.LLVMException(errmsg) + raise llvm.LLVMException(errmsg.getvalue()) def get_type_named(self, name): typ = self._ptr.getTypeByName(name) From 17ec89e457c05b3fdb004fb3636d47ea853484d0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 28 May 2013 19:23:40 -0500 Subject: [PATCH 021/155] Fix win32 build --- llvm-config-win32.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 05fc94f..5f6c401 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -98,6 +98,9 @@ def main(): if option == '--version': print(get_llvm_version()) + elif option == '--targets-built': + print('X86') # just do X86 + elif option == '--libs': libs_options() From 2e8944916c8a95855ec26fcdc07d4094c1681aba Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 29 May 2013 16:16:19 -0500 Subject: [PATCH 022/155] Add DIBuilder binding --- llvmpy/src/DIBuilder.py | 357 +++++++++++++++++++++++ llvmpy/src/DebugInfo.py | 98 +++++++ llvmpy/src/Support/Dwarf.py | 563 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1018 insertions(+) create mode 100644 llvmpy/src/DIBuilder.py create mode 100644 llvmpy/src/DebugInfo.py create mode 100644 llvmpy/src/Support/Dwarf.py diff --git a/llvmpy/src/DIBuilder.py b/llvmpy/src/DIBuilder.py new file mode 100644 index 0000000..9671963 --- /dev/null +++ b/llvmpy/src/DIBuilder.py @@ -0,0 +1,357 @@ +from binding import * +from .namespace import llvm + +DIBuilder = llvm.Class() + +from .Module import Module +from .Value import Value, MDNode, Function, BasicBlock +from .Instruction import Instruction +from .DebugInfo import DIFile, DIEnumerator, DIType, DIBasicType, DIDerivedType +from .DebugInfo import DIDescriptor, DIArray, DISubrange, DIGlobalVariable +from .DebugInfo import DIVariable, DISubprogram, DINameSpace, DILexicalBlockFile +from .DebugInfo import DILexicalBlock +from .ADT.SmallVector import SmallVector_Value +from .ADT.StringRef import StringRef + +unsigned_arg = cast(int, Unsigned) +stringref_arg = cast(str, StringRef) +bool_arg = cast(bool, Bool) +uint64_arg = cast(int, Uint64) +int64_arg = cast(int, Int64) + +@DIBuilder +class DIBuilder: + _include_ = 'llvm/DIBuilder.h' + new = Constructor(ref(Module)) + delete = Destructor() + + getCU = Method(const(ptr(MDNode))) + finalize = Method() + + createCompileUnit = Method(Void, + unsigned_arg, # Lang + stringref_arg, # File + stringref_arg, # Dir + stringref_arg, # Producer + bool_arg, # isOptimized + stringref_arg, # Flags, + unsigned_arg, # RV + # stringref_arg, # SplitName LLVM3.3 + ) #.require_only(7) + + createFile = Method(DIFile, + stringref_arg, # Filename + stringref_arg, # Directory + ) + + createEnumerator = Method(DIEnumerator, + stringref_arg, # Name + uint64_arg, # Val + ) + + createNullPtrType = Method(DIType, + stringref_arg, # Name + ) + + createBasicType = Method(DIType, + stringref_arg, # Name + uint64_arg, # SizeIntBits, + uint64_arg, # AlignInBits, + unsigned_arg, # Encoding + ) + + createQualifiedType = Method(DIType, + unsigned_arg, # Tag + ref(DIType), # FromTy + ) + + createPointerType = Method(DIType, + ref(DIType), # PointeeTy + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + stringref_arg, # Name + ).require_only(2) + + createReferenceType = Method(DIType, + unsigned_arg, # Tag + ref(DIType), # RTy + ) + + createTypedef = Method(DIType, + ref(DIType), # Ty + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIDescriptor), # Context + ) + + createFriend = Method(DIType, + ref(DIType), # Ty + ref(DIType), # FriendTy + ) + + createInheritance = Method(DIType, + ref(DIType), # Ty + ref(DIType), # BaseTy + uint64_arg, # BaseOffset + unsigned_arg, # Flags + ) + + createMemberType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNo + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + uint64_arg, # OffsetInBits + unsigned_arg, # Flags + ref(DIType), # Ty + ) + + createClassType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNum + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + uint64_arg, # OffsetInBits, + unsigned_arg, # Flags + ref(DIType), # DerivedFrom + ref(DIArray), # Elements + ptr(MDNode), # VTableHolder = 0 + ptr(MDNode), # TemplateParms = 0 + ).require_only(10) + + createStructType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(8) + + createUnionType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNum + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(8) + + createArrayType = Method(DIType, + uint64_arg, # Size + uint64_arg, # AlignInBits + ref(DIType), # Ty + ref(DIArray), # Subscripts + ) + + createVectorType = Method(DIType, + uint64_arg, # Size + uint64_arg, # AlignInBits + ref(DIType), # Ty + ref(DIArray), # Subscripts + ) + + createEnumerationType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + ref(DIArray), # Elements + ref(DIType), # ClassType + ) + + createSubroutineType = Method(DIType, + ref(DIFile), # File + ref(DIArray), # ParameterTypes + ) + + createArtificialType = Method(DIType, + ref(DIType), # Ty + ) + + createObjectPointerType = Method(DIType, + ref(DIType), # Ty + ) + + createTemporaryType = Method(DIType, ref(DIFile)).require_only(0) + + createForwardDecl = Method(DIType, + unsigned_arg, # Tag + stringref_arg, # Name + ref(DIDescriptor), # scope + ref(DIFile), # F + unsigned_arg, # Line + unsigned_arg, # RuntimeLang=0 + uint64_arg, # SizeInBits=0 + uint64_arg, # AlignInBits=0 + ).require_only(5) + + retainType = Method(Void, ref(DIType)) + + createUnspecifiedParameter = Method(DIDescriptor) + + getOrCreateArray = Method(DIArray, + ref(SmallVector_Value), # Elements + ) + + getOrCreateSubrange = Method(DISubrange, + int64_arg, # Lo + int64_arg, # Hi + ) + + createGlobalVariable = Method(DIGlobalVariable, + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + ptr(Value), # Val + ) + + createStaticVariable = Method(DIGlobalVariable, + ref(DIDescriptor), # Context + stringref_arg, # Name + stringref_arg, # LinkageName + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + ptr(Value), # Val + ) + + createLocalVariable = Method(DIVariable, + unsigned_arg, # Tag, + ref(DIDescriptor), # Scope, + stringref_arg, # Name, + ref(DIFile), # File, + unsigned_arg, # LineNo, + ref(DIType), # Ty, + bool_arg, # AlwaysPreserve=false, + unsigned_arg, # Flags=0, + unsigned_arg, # ArgNo=0 + ).require_only(6) + + createComplexVariable = Method(DIVariable, + unsigned_arg, # Tag, + ref(DIDescriptor), # Scope, + stringref_arg, # Name, + ref(DIFile), # F, + unsigned_arg, # LineNo, + ref(DIType), # Ty, + ref(SmallVector_Value), # Addr, + unsigned_arg, # ArgNo=0, + ).require_only(7) + + createFunction = Method(DISubprogram, + ref(DIDescriptor), # Scope + stringref_arg, # Name + stringref_arg, # LinkageName + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + bool_arg, # isDefinition + unsigned_arg, # ScopeLine + unsigned_arg, # Flags=0 + bool_arg, # isOptimized=false + ptr(Function), # *Fn=0 + ptr(MDNode), # *TParam=0, + ptr(MDNode), # *Decl=0 + ).require_only(9) + + + createMethod = Method(DISubprogram, + ref(DIDescriptor), # Scope + stringref_arg, # Name + stringref_arg, # LinkageName + ref(DIFile), # File + unsigned_arg, # LineNo + ref(DIType), # Ty + bool_arg, # isLocalToUnit + bool_arg, # isDefinition + unsigned_arg, # Virtuality=0 + unsigned_arg, # VTableIndex=0 + ptr(MDNode), # *VTableHolder=0 + unsigned_arg, # Flags=0 + bool_arg, # isOptimized=false + ptr(Function), # *Fn=0 + ptr(MDNode), # *TParam=0 + ).require_only(8) + + + createNameSpace = Method(DINameSpace, + ref(DIDescriptor), # Scope, + stringref_arg, # Name, + ref(DIFile), # File, + unsigned_arg, # LineNo + ) + + createLexicalBlockFile = Method(DILexicalBlockFile, + ref(DIDescriptor), # Scope, + ref(DIFile), # File + ) + + createLexicalBlock = Method(DILexicalBlock, + ref(DIDescriptor), # Scope, + ref(DIFile), # File, + unsigned_arg, # Line, + unsigned_arg, # Col + ) + + _insertDeclare_1 = Method(ptr(Instruction), + ptr(Value), # Storage, + ref(DIVariable), # VarInfo + ptr(BasicBlock), # *InsertAtEnd + ) + _insertDeclare_1.realname = 'insertDeclare' + + _insertDeclare_2 = Method(ptr(Instruction), + ptr(Value), # Storage, + ref(DIVariable), # VarInfo + ptr(Instruction), # *InsertBefore + ) + _insertDeclare_2.realname = 'insertDeclare' + + @CustomPythonMethod + def insertDeclare(self, storage, varinfo, insertpt): + if isinstance(insertbefore, _api.llvm.Instruction): + return self._insertDeclare_2(storage, varinfo, insertpt) + else: + return self._insertDeclare_1(storage, varinfo, insertpt) + + _insertDbgValueIntrinsic_1 = Method(ptr(Instruction), + ptr(Value), # *Val + uint64_arg, # Offset + ref(DIVariable), # VarInfo + ptr(BasicBlock), # *InsertAtEnd + ) + _insertDbgValueIntrinsic_1.realname = 'insertDbgValueIntrinsic' + + _insertDbgValueIntrinsic_2 = Method(ptr(Instruction), + ptr(Value), # *Val + uint64_arg, # Offset + ref(DIVariable), # VarInfo + ptr(Instruction), # *InsertAtEnd + ) + _insertDbgValueIntrinsic_2.realname = 'insertDbgValueIntrinsic' + + + @CustomPythonMethod + def insertDbgValueIntrinsic(self, storage, varinfo, insertpt): + if isinstance(insertbefore, _api.llvm.Instruction): + return self._insertDbgValueIntrinsic_2(storage, varinfo, insertpt) + else: + return self._insertDbgValueIntrinsic_1(storage, varinfo, insertpt) diff --git a/llvmpy/src/DebugInfo.py b/llvmpy/src/DebugInfo.py new file mode 100644 index 0000000..81fe168 --- /dev/null +++ b/llvmpy/src/DebugInfo.py @@ -0,0 +1,98 @@ +from binding import * +from .namespace import llvm + +from .ADT.StringRef import StringRef +from .Value import MDNode + +DIDescriptor = llvm.Class(MDNode) +DIEnumerator = llvm.Class(DIDescriptor) +DIScope = llvm.Class(DIDescriptor) +DIType = llvm.Class(DIScope) +DIBasicType = llvm.Class(DIType) +DIDerivedType = llvm.Class(DIType) +DICompositeType = llvm.Class(DIDerivedType) +DIFile = llvm.Class(DIScope) +DIArray = llvm.Class(DIDescriptor) +DISubrange = llvm.Class(DIDescriptor) +DIGlobalVariable = llvm.Class(DIDescriptor) +DIVariable = llvm.Class(DIDescriptor) +DISubprogram = llvm.Class(DIScope) +DINameSpace = llvm.Class(DIScope) +DILexicalBlockFile = llvm.Class(DIScope) +DILexicalBlock = llvm.Class(DIScope) + +llvm.includes.add('llvm/DebugInfo.h') + +return_bool = cast(Bool, bool) +return_stringref = cast(StringRef, str) +return_unsigned = cast(Unsigned, int) + +@DIDescriptor +class DIDescriptor: + pass + +@DIScope +class DIScope: + pass + +@DIFile +class DIFile: + # getFileNode = Method(ptr(MDNode)) # not in LLVM 3.2? + Verify = Method(return_bool) + +@DIEnumerator +class DIEnumerator: + getName = Method(return_stringref) + getEnumValue = Method(cast(Uint64, int)) + Verify = Method(return_bool) + +@DIType +class DIType: + getName = Method(return_stringref) + getLineNumber = Method(return_unsigned) + Verify = Method(return_bool) + +@DIBasicType +class DIBasicType: + pass + +@DIDerivedType +class DIDerivedType: + pass + +@DICompositeType +class DICompositeType: + pass + +@DIArray +class DIArray: + Verify = Method(return_bool) + +@DISubrange +class DISubrange: + Verify = Method(return_bool) + +@DIGlobalVariable +class DIGlobalVariable: + Verify = Method(return_bool) + +@DIVariable +class DIVariable: + Verify = Method(return_bool) + +@DISubprogram +class DISubprogram: + Verify = Method(return_bool) + +@DINameSpace +class DINameSpace: + Verify = Method(return_bool) + +@DILexicalBlockFile +class DILexicalBlockFile: + Verify = Method(return_bool) + +@DILexicalBlock +class DILexicalBlock: + Verify = Method(return_bool) + diff --git a/llvmpy/src/Support/Dwarf.py b/llvmpy/src/Support/Dwarf.py new file mode 100644 index 0000000..caecc24 --- /dev/null +++ b/llvmpy/src/Support/Dwarf.py @@ -0,0 +1,563 @@ +from binding import * +from ..namespace import llvm + +dwarf = llvm.Namespace('dwarf') + +dwarf.includes.add('llvm/Support/Dwarf.h') + +dwarf_constants = dwarf.Enum('dwarf_constants', +''' +DWARF_VERSION +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_entry_point +DW_TAG_enumeration_type +DW_TAG_formal_parameter +DW_TAG_imported_declaration +DW_TAG_label +DW_TAG_lexical_block +DW_TAG_member +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_compile_unit +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_unspecified_parameters +DW_TAG_variant +DW_TAG_common_block +DW_TAG_common_inclusion +DW_TAG_inheritance +DW_TAG_inlined_subroutine +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_with_stmt +DW_TAG_access_declaration +DW_TAG_base_type +DW_TAG_catch_block +DW_TAG_const_type +DW_TAG_constant +DW_TAG_enumerator +DW_TAG_file_type +DW_TAG_friend +DW_TAG_namelist +DW_TAG_namelist_item +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_template_type_parameter +DW_TAG_template_value_parameter +DW_TAG_thrown_type +DW_TAG_try_block +DW_TAG_variant_part +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_dwarf_procedure +DW_TAG_restrict_type +DW_TAG_interface_type +DW_TAG_namespace +DW_TAG_imported_module +DW_TAG_unspecified_type +DW_TAG_partial_unit +DW_TAG_imported_unit +DW_TAG_condition +DW_TAG_shared_type +DW_TAG_type_unit +DW_TAG_rvalue_reference_type +DW_TAG_template_alias +DW_TAG_MIPS_loop +DW_TAG_format_label +DW_TAG_function_template +DW_TAG_class_template +DW_TAG_GNU_template_template_param +DW_TAG_GNU_template_parameter_pack +DW_TAG_GNU_formal_parameter_pack +DW_TAG_lo_user +DW_TAG_APPLE_property +DW_TAG_hi_user +DW_CHILDREN_no +DW_CHILDREN_yes +DW_AT_sibling +DW_AT_location +DW_AT_name +DW_AT_ordering +DW_AT_byte_size +DW_AT_bit_offset +DW_AT_bit_size +DW_AT_stmt_list +DW_AT_low_pc +DW_AT_high_pc +DW_AT_language +DW_AT_discr +DW_AT_discr_value +DW_AT_visibility +DW_AT_import +DW_AT_string_length +DW_AT_common_reference +DW_AT_comp_dir +DW_AT_const_value +DW_AT_containing_type +DW_AT_default_value +DW_AT_inline +DW_AT_is_optional +DW_AT_lower_bound +DW_AT_producer +DW_AT_prototyped +DW_AT_return_addr +DW_AT_start_scope +DW_AT_bit_stride +DW_AT_upper_bound +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_address_class +DW_AT_artificial +DW_AT_base_types +DW_AT_calling_convention +DW_AT_count +DW_AT_data_member_location +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_declaration +DW_AT_discr_list +DW_AT_encoding +DW_AT_external +DW_AT_frame_base +DW_AT_friend +DW_AT_identifier_case +DW_AT_macro_info +DW_AT_namelist_item +DW_AT_priority +DW_AT_segment +DW_AT_specification +DW_AT_static_link +DW_AT_type +DW_AT_use_location +DW_AT_variable_parameter +DW_AT_virtuality +DW_AT_vtable_elem_location +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_byte_stride +DW_AT_entry_pc +DW_AT_use_UTF8 +DW_AT_extension +DW_AT_ranges +DW_AT_trampoline +DW_AT_call_column +DW_AT_call_file +DW_AT_call_line +DW_AT_description +DW_AT_binary_scale +DW_AT_decimal_scale +DW_AT_small +DW_AT_decimal_sign +DW_AT_digit_count +DW_AT_picture_string +DW_AT_mutable +DW_AT_threads_scaled +DW_AT_explicit +DW_AT_object_pointer +DW_AT_endianity +DW_AT_elemental +DW_AT_pure +DW_AT_recursive +DW_AT_signature +DW_AT_main_subprogram +DW_AT_data_bit_offset +DW_AT_const_expr +DW_AT_enum_class +DW_AT_linkage_name +DW_AT_lo_user +DW_AT_hi_user +DW_AT_MIPS_loop_begin +DW_AT_MIPS_tail_loop_begin +DW_AT_MIPS_epilog_begin +DW_AT_MIPS_loop_unroll_factor +DW_AT_MIPS_software_pipeline_depth +DW_AT_MIPS_linkage_name +DW_AT_MIPS_stride +DW_AT_MIPS_abstract_name +DW_AT_MIPS_clone_origin +DW_AT_MIPS_has_inlines +DW_AT_MIPS_stride_byte +DW_AT_MIPS_stride_elem +DW_AT_MIPS_ptr_dopetype +DW_AT_MIPS_allocatable_dopetype +DW_AT_MIPS_assumed_shape_dopetype +DW_AT_MIPS_assumed_size +DW_AT_sf_names +DW_AT_src_info +DW_AT_mac_info +DW_AT_src_coords +DW_AT_body_begin +DW_AT_body_end +DW_AT_APPLE_optimized +DW_AT_APPLE_flags +DW_AT_APPLE_isa +DW_AT_APPLE_block +DW_AT_APPLE_major_runtime_vers +DW_AT_APPLE_runtime_class +DW_AT_APPLE_omit_frame_ptr +DW_AT_APPLE_property_name +DW_AT_APPLE_property_getter +DW_AT_APPLE_property_setter +DW_AT_APPLE_property_attribute +DW_AT_APPLE_objc_complete_type +DW_AT_APPLE_property +DW_FORM_addr +DW_FORM_block2 +DW_FORM_block4 +DW_FORM_data2 +DW_FORM_data4 +DW_FORM_data8 +DW_FORM_string +DW_FORM_block +DW_FORM_block1 +DW_FORM_data1 +DW_FORM_flag +DW_FORM_sdata +DW_FORM_strp +DW_FORM_udata +DW_FORM_ref_addr +DW_FORM_ref1 +DW_FORM_ref2 +DW_FORM_ref4 +DW_FORM_ref8 +DW_FORM_ref_udata +DW_FORM_indirect +DW_FORM_sec_offset +DW_FORM_exprloc +DW_FORM_flag_present +DW_FORM_ref_sig8 +DW_OP_addr +DW_OP_deref +DW_OP_const1u +DW_OP_const1s +DW_OP_const2u +DW_OP_const2s +DW_OP_const4u +DW_OP_const4s +DW_OP_const8u +DW_OP_const8s +DW_OP_constu +DW_OP_consts +DW_OP_dup +DW_OP_drop +DW_OP_over +DW_OP_pick +DW_OP_swap +DW_OP_rot +DW_OP_xderef +DW_OP_abs +DW_OP_and +DW_OP_div +DW_OP_minus +DW_OP_mod +DW_OP_mul +DW_OP_neg +DW_OP_not +DW_OP_or +DW_OP_plus +DW_OP_plus_uconst +DW_OP_shl +DW_OP_shr +DW_OP_shra +DW_OP_xor +DW_OP_skip +DW_OP_bra +DW_OP_eq +DW_OP_ge +DW_OP_gt +DW_OP_le +DW_OP_lt +DW_OP_ne +DW_OP_lit0 +DW_OP_lit1 +DW_OP_lit2 +DW_OP_lit3 +DW_OP_lit4 +DW_OP_lit5 +DW_OP_lit6 +DW_OP_lit7 +DW_OP_lit8 +DW_OP_lit9 +DW_OP_lit10 +DW_OP_lit11 +DW_OP_lit12 +DW_OP_lit13 +DW_OP_lit14 +DW_OP_lit15 +DW_OP_lit16 +DW_OP_lit17 +DW_OP_lit18 +DW_OP_lit19 +DW_OP_lit20 +DW_OP_lit21 +DW_OP_lit22 +DW_OP_lit23 +DW_OP_lit24 +DW_OP_lit25 +DW_OP_lit26 +DW_OP_lit27 +DW_OP_lit28 +DW_OP_lit29 +DW_OP_lit30 +DW_OP_lit31 +DW_OP_reg0 +DW_OP_reg1 +DW_OP_reg2 +DW_OP_reg3 +DW_OP_reg4 +DW_OP_reg5 +DW_OP_reg6 +DW_OP_reg7 +DW_OP_reg8 +DW_OP_reg9 +DW_OP_reg10 +DW_OP_reg11 +DW_OP_reg12 +DW_OP_reg13 +DW_OP_reg14 +DW_OP_reg15 +DW_OP_reg16 +DW_OP_reg17 +DW_OP_reg18 +DW_OP_reg19 +DW_OP_reg20 +DW_OP_reg21 +DW_OP_reg22 +DW_OP_reg23 +DW_OP_reg24 +DW_OP_reg25 +DW_OP_reg26 +DW_OP_reg27 +DW_OP_reg28 +DW_OP_reg29 +DW_OP_reg30 +DW_OP_reg31 +DW_OP_breg0 +DW_OP_breg1 +DW_OP_breg2 +DW_OP_breg3 +DW_OP_breg4 +DW_OP_breg5 +DW_OP_breg6 +DW_OP_breg7 +DW_OP_breg8 +DW_OP_breg9 +DW_OP_breg10 +DW_OP_breg11 +DW_OP_breg12 +DW_OP_breg13 +DW_OP_breg14 +DW_OP_breg15 +DW_OP_breg16 +DW_OP_breg17 +DW_OP_breg18 +DW_OP_breg19 +DW_OP_breg20 +DW_OP_breg21 +DW_OP_breg22 +DW_OP_breg23 +DW_OP_breg24 +DW_OP_breg25 +DW_OP_breg26 +DW_OP_breg27 +DW_OP_breg28 +DW_OP_breg29 +DW_OP_breg30 +DW_OP_breg31 +DW_OP_regx +DW_OP_fbreg +DW_OP_bregx +DW_OP_piece +DW_OP_deref_size +DW_OP_xderef_size +DW_OP_nop +DW_OP_push_object_address +DW_OP_call2 +DW_OP_call4 +DW_OP_call_ref +DW_OP_form_tls_address +DW_OP_call_frame_cfa +DW_OP_bit_piece +DW_OP_implicit_value +DW_OP_stack_value +DW_OP_lo_user +DW_OP_hi_user +DW_ATE_address +DW_ATE_boolean +DW_ATE_complex_float +DW_ATE_float +DW_ATE_signed +DW_ATE_signed_char +DW_ATE_unsigned +DW_ATE_unsigned_char +DW_ATE_imaginary_float +DW_ATE_packed_decimal +DW_ATE_numeric_string +DW_ATE_edited +DW_ATE_signed_fixed +DW_ATE_unsigned_fixed +DW_ATE_decimal_float +DW_ATE_UTF +DW_ATE_lo_user +DW_ATE_hi_user +DW_DS_unsigned +DW_DS_leading_overpunch +DW_DS_trailing_overpunch +DW_DS_leading_separate +DW_DS_trailing_separate +DW_END_default +DW_END_big +DW_END_little +DW_END_lo_user +DW_END_hi_user +DW_ACCESS_public +DW_ACCESS_protected +DW_ACCESS_private +DW_VIS_local +DW_VIS_exported +DW_VIS_qualified +DW_VIRTUALITY_none +DW_VIRTUALITY_virtual +DW_VIRTUALITY_pure_virtual +DW_LANG_C89 +DW_LANG_C +DW_LANG_Ada83 +DW_LANG_C_plus_plus +DW_LANG_Cobol74 +DW_LANG_Cobol85 +DW_LANG_Fortran77 +DW_LANG_Fortran90 +DW_LANG_Pascal83 +DW_LANG_Modula2 +DW_LANG_Java +DW_LANG_C99 +DW_LANG_Ada95 +DW_LANG_Fortran95 +DW_LANG_PLI +DW_LANG_ObjC +DW_LANG_ObjC_plus_plus +DW_LANG_UPC +DW_LANG_D +DW_LANG_Python +DW_LANG_lo_user +DW_LANG_Mips_Assembler +DW_LANG_hi_user +DW_ID_case_sensitive +DW_ID_up_case +DW_ID_down_case +DW_ID_case_insensitive +DW_CC_normal +DW_CC_program +DW_CC_nocall +DW_CC_lo_user +DW_CC_hi_user +DW_INL_not_inlined +DW_INL_inlined +DW_INL_declared_not_inlined +DW_INL_declared_inlined +DW_ORD_row_major +DW_ORD_col_major +DW_DSC_label +DW_DSC_range +DW_LNS_extended_op +DW_LNS_copy +DW_LNS_advance_pc +DW_LNS_advance_line +DW_LNS_set_file +DW_LNS_set_column +DW_LNS_negate_stmt +DW_LNS_set_basic_block +DW_LNS_const_add_pc +DW_LNS_fixed_advance_pc +DW_LNS_set_prologue_end +DW_LNS_set_epilogue_begin +DW_LNS_set_isa +DW_LNE_end_sequence +DW_LNE_set_address +DW_LNE_define_file +DW_LNE_set_discriminator +DW_LNE_lo_user +DW_LNE_hi_user +DW_MACINFO_define +DW_MACINFO_undef +DW_MACINFO_start_file +DW_MACINFO_end_file +DW_MACINFO_vendor_ext +DW_CFA_extended +DW_CFA_nop +DW_CFA_advance_loc +DW_CFA_offset +DW_CFA_restore +DW_CFA_set_loc +DW_CFA_advance_loc1 +DW_CFA_advance_loc2 +DW_CFA_advance_loc4 +DW_CFA_offset_extended +DW_CFA_restore_extended +DW_CFA_undefined +DW_CFA_same_value +DW_CFA_register +DW_CFA_remember_state +DW_CFA_restore_state +DW_CFA_def_cfa +DW_CFA_def_cfa_register +DW_CFA_def_cfa_offset +DW_CFA_def_cfa_expression +DW_CFA_expression +DW_CFA_offset_extended_sf +DW_CFA_def_cfa_sf +DW_CFA_def_cfa_offset_sf +DW_CFA_val_offset +DW_CFA_val_offset_sf +DW_CFA_val_expression +DW_CFA_MIPS_advance_loc8 +DW_CFA_GNU_window_save +DW_CFA_GNU_args_size +DW_CFA_lo_user +DW_CFA_hi_user +DW_EH_PE_absptr +DW_EH_PE_omit +DW_EH_PE_uleb128 +DW_EH_PE_udata2 +DW_EH_PE_udata4 +DW_EH_PE_udata8 +DW_EH_PE_sleb128 +DW_EH_PE_sdata2 +DW_EH_PE_sdata4 +DW_EH_PE_sdata8 +DW_EH_PE_signed +DW_EH_PE_pcrel +DW_EH_PE_textrel +DW_EH_PE_datarel +DW_EH_PE_funcrel +DW_EH_PE_aligned +DW_EH_PE_indirect +DW_APPLE_PROPERTY_readonly +DW_APPLE_PROPERTY_readwrite +DW_APPLE_PROPERTY_assign +DW_APPLE_PROPERTY_retain +DW_APPLE_PROPERTY_copy +DW_APPLE_PROPERTY_nonatomic +''') + +### The following enums are not available in LLVM 3.2 +# DW_AT_GNU_dwo_name +# DW_AT_GNU_vector +# DW_AT_GNU_template_name +# DW_AT_GNU_dwo_id +# DW_AT_GNU_ranges_base +# DW_AT_GNU_addr_base +# DW_AT_GNU_pubnames +# DW_AT_GNU_pubtypes +# DW_FORM_GNU_addr_index +# DW_FORM_GNU_str_index +# DW_OP_GNU_addr_index +# DW_OP_GNU_const_index From 84f1b433def8c4ef9a829c21a14cc26e523117df Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 30 May 2013 14:04:08 -0500 Subject: [PATCH 023/155] Use if-else instead of try-except for perf reason --- llvmpy/capsule.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index f66836f..1b3813b 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -141,9 +141,10 @@ def wrap(cap, owned=False): cls = cap.get_class() addr = cap.pointer name = cap.name - try: # lookup cached object - return _cache[cls][addr] - except KeyError: + # lookup cached object + if cls in _cache and addr in _cache[cls]: + obj = _cache[cls][addr] + else: if not owned and cls._has_dtor(): _addr2dtor[(name, addr)] = cls._delete_ obj = cap.instantiate() @@ -207,11 +208,10 @@ def downcast(obj, cls): logger.debug("Downcast %s to %s" , fromty, toty) fname = 'downcast_%s_to_%s' % (fromty, toty) fname = fname.replace('::', '_') - try: - caster = getattr(_api.downcast, fname) - except AttributeError: + if not hasattr(_api.downcast, fname): fmt = "Downcast from %s to %s is not supported" raise TypeError(fmt % (fromty, toty)) + caster = getattr(_api.downcast, fname) old = unwrap(obj) new = caster(old) used_to_own = has_ownership(old) From 69c75355f4a919fa04ab49a5f933aaa99ec95bfb Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 31 May 2013 11:47:51 -0500 Subject: [PATCH 024/155] fix future import --- llvm_array/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_array/__init__.py b/llvm_array/__init__.py index 5e807c2..08dd11b 100644 --- a/llvm_array/__init__.py +++ b/llvm_array/__init__.py @@ -1,2 +1,2 @@ -from __future__ import absolute_imports +from __future__ import absolute_import from .array import * From ad287faeb1f4473e112ef428e05610020c5357a1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 31 May 2013 14:01:57 -0500 Subject: [PATCH 025/155] Fixes a werid case of refct problem --- llvmpy/capsule.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 1b3813b..5efed13 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -56,15 +56,15 @@ class Capsule(object): @property def classname(self): - return Capsule.getClassName(self.capsule) + return self.getClassName(self.capsule) @property def name(self): - return Capsule.getName(self.capsule) + return self.getName(self.capsule) @property def pointer(self): - return Capsule.getPointer(self.capsule) + return self.getPointer(self.capsule) @staticmethod def valid(capsule): From 2415042a2a07e99b24ab6859edb4d5d341ad5ea6 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 31 May 2013 15:01:02 -0500 Subject: [PATCH 026/155] DIDescriptor does not inherit MDNode --- llvmpy/src/DebugInfo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvmpy/src/DebugInfo.py b/llvmpy/src/DebugInfo.py index 81fe168..8ddb1ee 100644 --- a/llvmpy/src/DebugInfo.py +++ b/llvmpy/src/DebugInfo.py @@ -4,7 +4,7 @@ from .namespace import llvm from .ADT.StringRef import StringRef from .Value import MDNode -DIDescriptor = llvm.Class(MDNode) +DIDescriptor = llvm.Class() DIEnumerator = llvm.Class(DIDescriptor) DIScope = llvm.Class(DIDescriptor) DIType = llvm.Class(DIScope) @@ -29,7 +29,8 @@ return_unsigned = cast(Unsigned, int) @DIDescriptor class DIDescriptor: - pass + new = Constructor(ptr(MDNode)) + delete = Destructor() @DIScope class DIScope: From 2338eae5f6a91651125b8180abafa8c9afaa90d8 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 13 Jun 2013 17:17:43 -0500 Subject: [PATCH 027/155] Fix py3 str has no buffer interface --- llvmpy/include/llvm_binding/extra.h | 67 ++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 6626ede..456f75e 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -270,7 +270,12 @@ llvm::ExecutionEngine* ExecutionEngine_create( ExecutionEngine *ee = ExecutionEngine::create(M, ForceInterpreter, &ErrorStr, OptLevel, GVsWithCode); - PyFile_WriteString(ErrorStr.c_str(), errout); + auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); + if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + return NULL; + } + +// PyFile_WriteString(ErrorStr.c_str(), errout); return ee; } @@ -292,7 +297,11 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT( std::string ErrorStr; ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL, GCsWithCode, RM, CMM); - PyFile_WriteString(ErrorStr.c_str(), errout); + auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); + if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + return NULL; + } +// PyFile_WriteString(ErrorStr.c_str(), errout); return ee; } @@ -512,9 +521,13 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, if (FObj) { std::string ErrStr; Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr); - if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); + if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { +// return NULL; +// } } else { Triple = getBitcodeTargetTriple(MB, Ctx); } @@ -585,9 +598,15 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker, if (! failed) { Py_RETURN_FALSE; } else { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } + +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } Py_RETURN_TRUE; } } @@ -603,9 +622,13 @@ PyObject* Linker_LinkModules(llvm::Module* Dest, if (! failed) { Py_RETURN_FALSE; } else { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } Py_RETURN_TRUE; } } @@ -665,9 +688,14 @@ PyObject* llvm_verifyModule(const llvm::Module& Fn, bool failed = llvm::verifyModule(Fn, Action, &errmsg); if (failed) { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } + +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } Py_RETURN_TRUE; } else { Py_RETURN_FALSE; @@ -790,9 +818,13 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, std::string errmsg; failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg); if (failed) { - if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { +// return NULL; +// } } } else { failed = DynamicLibrary::LoadLibraryPermanently(Filename); @@ -835,7 +867,12 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Triple, std::string error; const Target* target = TargetRegistry::lookupTarget(Triple, error); if (!target) { - PyFile_WriteString(error.c_str(), Error); +// PyFile_WriteString(error.c_str(), Error); + auto_pyobject buf = PyBytes_FromString(error.c_str()); + if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + return NULL; + } + Py_RETURN_NONE; } else { return pycapsule_new(const_cast(target), "llvm::Target"); @@ -852,7 +889,12 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch, std::string error; const Target* target = TargetRegistry::lookupTarget(Arch, Triple, error); if (!target) { - PyFile_WriteString(error.c_str(), Error); +// PyFile_WriteString(error.c_str(), Error); + auto_pyobject buf = PyBytes_FromString(error.c_str()); + if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + return NULL; + } + Py_RETURN_NONE; } else { return pycapsule_new(const_cast(target), "llvm::Target"); @@ -867,7 +909,12 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) std::string error; const Target* target = TargetRegistry::getClosestTargetForJIT(error); if (!target) { - PyFile_WriteString(error.c_str(), Error); + auto_pyobject buf = PyBytes_FromString(error.c_str()); + if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + return NULL; + } + +// PyFile_WriteString(error.c_str(), Error); Py_RETURN_NONE; } else { return pycapsule_new(const_cast(target), "llvm::Target"); From 4c1b9016fb513a96463b68472ec6a5e6c1416912 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 15:12:23 -0500 Subject: [PATCH 028/155] binding compiles with llvm 3.3 --- llvmpy/gen/binding.py | 3 +- llvmpy/include/llvm_binding/extra.h | 83 +++++++++++----- llvmpy/src/Argument.py | 19 +++- llvmpy/src/Attributes.py | 101 +++++++++++++++----- llvmpy/src/DIBuilder.py | 38 +++++--- llvmpy/src/DataLayout.py | 5 +- llvmpy/src/DerivedTypes.py | 5 +- llvmpy/src/Function.py | 22 ++++- llvmpy/src/GlobalValue.py | 5 +- llvmpy/src/IRBuilder.py | 6 +- llvmpy/src/InlineAsm.py | 5 +- llvmpy/src/Instruction.py | 26 +++-- llvmpy/src/LLVMContext.py | 5 +- llvmpy/src/Linker.py | 35 +++---- llvmpy/src/Module.py | 5 +- llvmpy/src/Support/Host.py | 29 ++++-- llvmpy/src/Target/TargetMachine.py | 12 ++- llvmpy/src/TargetTransformInfo.py | 16 +++- llvmpy/src/Transforms/PassManagerBuilder.py | 6 +- llvmpy/src/Type.py | 5 +- llvmpy/src/ValueSymbolTable.py | 5 +- setup.py | 7 +- 22 files changed, 324 insertions(+), 119 deletions(-) diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 8006fd9..db4fdbf 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -247,7 +247,8 @@ class Class(SubModule, _Type): def __call__(self, defn): assert not self._is_defined # process the definition in "defn" - self.name = defn.__name__ + self.name = getattr(defn, '_name_', defn.__name__) + for k, v in defn.__dict__.items(): if isinstance(v, Method): self.methods.append(v) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 456f75e..cd1f59c 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -1,8 +1,22 @@ #include #include -#include -#include -#include +#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 3 + #include + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include + #include +#endif #include #include #include @@ -12,11 +26,7 @@ #include #include #include -#include #include -#include -#include -#include #include #include @@ -56,6 +66,15 @@ namespace extra{ } +static +PyObject* callwrite(PyObject* self, PyObject* arg) +{ + char meth[] = "method"; + char fmt[] = "O"; + return PyObject_CallMethod(self, meth, fmt, arg); +} + + static PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { @@ -271,7 +290,7 @@ llvm::ExecutionEngine* ExecutionEngine_create( &ErrorStr, OptLevel, GVsWithCode); auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); - if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + if (errout && NULL == callwrite(errout, *buf)){ return NULL; } @@ -298,7 +317,7 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT( ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL, GCsWithCode, RM, CMM); auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str()); - if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){ + if (errout && NULL == callwrite(errout, *buf)){ return NULL; } // PyFile_WriteString(ErrorStr.c_str(), errout); @@ -483,7 +502,7 @@ PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx, std::string ErrStr; M = ParseBitcodeFile(MB, Ctx, &ErrStr); auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); - if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ + if (NULL == callwrite(FObj, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { @@ -507,7 +526,7 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) rso.flush(); StringRef ref = rso.str(); auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); - return PyObject_CallMethod(FObj, "write", "O", *buf); + return callwrite(FObj, *buf); } static @@ -522,7 +541,7 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, std::string ErrStr; Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr); auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); - if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ + if (NULL == callwrite(FObj, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { @@ -594,19 +613,19 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker, PyObject* ErrMsg) { std::string errmsg; +#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3 + bool failed = Linker->linkInModule(Mod, &errmsg); +#else bool failed = Linker->LinkInModule(Mod, &errmsg); +#endif if (! failed) { Py_RETURN_FALSE; } else { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } - -// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { -// return NULL; -// } Py_RETURN_TRUE; } } @@ -623,7 +642,7 @@ PyObject* Linker_LinkModules(llvm::Module* Dest, Py_RETURN_FALSE; } else { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { @@ -689,7 +708,7 @@ PyObject* llvm_verifyModule(const llvm::Module& Fn, if (failed) { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } @@ -819,7 +838,7 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg); if (failed) { auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); - if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){ + if (NULL == callwrite(ErrMsg, *buf)){ return NULL; } // if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { @@ -869,7 +888,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Triple, if (!target) { // PyFile_WriteString(error.c_str(), Error); auto_pyobject buf = PyBytes_FromString(error.c_str()); - if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + if (NULL == callwrite(Error, *buf)){ return NULL; } @@ -891,7 +910,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch, if (!target) { // PyFile_WriteString(error.c_str(), Error); auto_pyobject buf = PyBytes_FromString(error.c_str()); - if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + if (NULL == callwrite(Error, *buf)){ return NULL; } @@ -910,7 +929,7 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) const Target* target = TargetRegistry::getClosestTargetForJIT(error); if (!target) { auto_pyobject buf = PyBytes_FromString(error.c_str()); - if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){ + if (NULL == callwrite(Error, *buf)){ return NULL; } @@ -945,3 +964,21 @@ PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) } } + +static +PyObject* llvm_sys_isLittleEndianHost() +{ + if (llvm::sys::IsLittleEndianHost) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static +PyObject* llvm_sys_isBigEndianHost() +{ + if (llvm::sys::IsBigEndianHost) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} \ No newline at end of file diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index 6262147..a08cca1 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -1,16 +1,27 @@ from binding import * from .namespace import llvm from .Value import Argument, Value -from .Attributes import Attributes +if LLVM_VERSION >= (3, 3): + from .Attributes import AttributeSet, Attribute +else: + from .Attributes import Attributes @Argument class Argument: - _include_ = 'llvm/Argument.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/Argument.h' + else: + _include_ = 'llvm/Argument.h' _downcast_ = Value - addAttr = Method(Void, ref(Attributes)) - removeAttr = Method(Void, ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addAttr = Method(Void, ref(AttributeSet)) + removeAttr = Method(Void, ref(AttributeSet)) + else: + addAttr = Method(Void, ref(Attributes)) + removeAttr = Method(Void, ref(Attributes)) + getParamAlignment = Method(cast(Unsigned, int)) getArgNo = Method(cast(Unsigned, int)) diff --git a/llvmpy/src/Attributes.py b/llvmpy/src/Attributes.py index 4fe7651..303d61d 100644 --- a/llvmpy/src/Attributes.py +++ b/llvmpy/src/Attributes.py @@ -2,38 +2,91 @@ from binding import * from .namespace import llvm from .LLVMContext import LLVMContext -llvm.includes.add('llvm/Attributes.h') +if LLVM_VERSION >= (3, 3): + llvm.includes.add('llvm/IR/Attributes.h') +else: + llvm.includes.add('llvm/Attributes.h') + -Attributes = llvm.Class() AttrBuilder = llvm.Class() - -@Attributes -class Attributes: - AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline, - ByVal, InlineHint, InReg, MinSize, - Naked, Nest, NoAlias, NoCapture, - NoImplicitFloat, NoInline, NonLazyBind, NoRedZone, - NoReturn, NoUnwind, OptimizeForSize, ReadNone, - ReadOnly, ReturnsTwice, SExt, StackAlignment, - StackProtect, StackProtectReq, StructRet, UWTable, ZExt''') - - delete = Destructor() - - get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder)) +if LLVM_VERSION >= (3, 3): + Attribute = llvm.Class() + AttributeSet = llvm.Class() +else: + Attributes = llvm.Class() -@AttrBuilder -class AttrBuilder: +if LLVM_VERSION >= (3, 3): + @Attribute + class Attribute: + AttrKind = Enum('''None, Alignment, AlwaysInline, + ByVal, InlineHint, InReg, + MinSize, Naked, Nest, NoAlias, + NoBuiltin, NoCapture, NoDuplicate, NoImplicitFloat, + NoInline, NonLazyBind, NoRedZone, NoReturn, + NoUnwind, OptimizeForSize, ReadNone, ReadOnly, + Returned, ReturnsTwice, SExt, StackAlignment, + StackProtect, StackProtectReq, StackProtectStrong, StructRet, + SanitizeAddress, SanitizeThread, SanitizeMemory, UWTable, + ZExt, EndAttrKinds''') - new = Constructor() - delete = Destructor() + delete = Destructor() - clear = Method() + get = StaticMethod(Attribute, + ref(LLVMContext), + AttrKind, + cast(int, Uint64)).require_only(2) - addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) - removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + @AttrBuilder + class AttrBuilder: - addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) + new = Constructor() + delete = Destructor() + + clear = Method() + + addAttribute = Method(ref(AttrBuilder), Attribute.AttrKind) + removeAttribute = Method(ref(AttrBuilder), Attribute.AttrKind) + + addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) + + @AttributeSet + class AttributeSet: + delete = Destructor() + + get = StaticMethod(AttributeSet, + ref(LLVMContext), + cast(int, Unsigned), + ref(AttrBuilder)) + +else: + @Attributes + class Attributes: + AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline, + ByVal, InlineHint, InReg, MinSize, + Naked, Nest, NoAlias, NoCapture, + NoImplicitFloat, NoInline, NonLazyBind, NoRedZone, + NoReturn, NoUnwind, OptimizeForSize, ReadNone, + ReadOnly, ReturnsTwice, SExt, StackAlignment, + StackProtect, StackProtectReq, StructRet, UWTable, ZExt''') + + delete = Destructor() + + get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder)) + + + @AttrBuilder + class AttrBuilder: + + new = Constructor() + delete = Destructor() + + clear = Method() + + addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + + addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) diff --git a/llvmpy/src/DIBuilder.py b/llvmpy/src/DIBuilder.py index 9671963..cb934d4 100644 --- a/llvmpy/src/DIBuilder.py +++ b/llvmpy/src/DIBuilder.py @@ -124,17 +124,31 @@ class DIBuilder: ptr(MDNode), # TemplateParms = 0 ).require_only(10) - createStructType = Method(DIType, - ref(DIDescriptor), # Scope - stringref_arg, # Name - ref(DIFile), # File - unsigned_arg, # LineNumber - uint64_arg, # SizeInBits - uint64_arg, # AlignInBits - unsigned_arg, # Flags - ref(DIArray), # Elements - unsigned_arg, # RunTimeLang = 0 - ).require_only(8) + if LLVM_VERSION >= (3, 3): + createStructType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIType), # DerivedFrom + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(9) + else: + createStructType = Method(DIType, + ref(DIDescriptor), # Scope + stringref_arg, # Name + ref(DIFile), # File + unsigned_arg, # LineNumber + uint64_arg, # SizeInBits + uint64_arg, # AlignInBits + unsigned_arg, # Flags + ref(DIArray), # Elements + unsigned_arg, # RunTimeLang = 0 + ).require_only(8) createUnionType = Method(DIType, ref(DIDescriptor), # Scope @@ -186,7 +200,7 @@ class DIBuilder: ref(DIType), # Ty ) - createTemporaryType = Method(DIType, ref(DIFile)).require_only(0) + #createTemporaryType = Method(DIType, ref(DIFile)).require_only(0) createForwardDecl = Method(DIType, unsigned_arg, # Tag diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index 812a83d..6741cda 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -15,7 +15,10 @@ from .GlobalVariable import GlobalVariable @DataLayout class DataLayout: - _include_ = 'llvm/DataLayout.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/DataLayout.h' + else: + _include_ = 'llvm/DataLayout.h' _new_string = Constructor(cast(str, StringRef)) _new_module = Constructor(ptr(Module)) diff --git a/llvmpy/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py index 02eec8c..fde01f3 100644 --- a/llvmpy/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -8,7 +8,10 @@ FunctionType = llvm.Class(Type) @FunctionType class FunctionType: - _include_ = 'llvm/DerivedTypes.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/DerivedTypes.h' + else: + _include_ = 'llvm/DerivedTypes.h' _downcast_ = Type _get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index 04c3e65..9c2c8b7 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -4,7 +4,10 @@ from .Value import GlobalValue, Constant, Function, Argument, Value from .Module import Module from .BasicBlock import BasicBlock from .ValueSymbolTable import ValueSymbolTable -from .Attributes import Attributes +if LLVM_VERSION >= (3, 3): + from .Attributes import Attribute, AttributeSet +else: + from .Attributes import Attributes from .Type import Type from .DerivedTypes import FunctionType from .LLVMContext import LLVMContext @@ -12,7 +15,11 @@ from .CallingConv import CallingConv @Function class Function: - _include_ = 'llvm/Function.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/Function.h' + else: + _include_ = 'llvm/Function.h' + _downcast_ = GlobalValue, Constant, Value getReturnType = Method(ptr(Type)) @@ -48,10 +55,17 @@ class Function: deleteBody = Method() viewCFG = Method() + viewCFGOnly = Method() - addFnAttr = Method(Void, Attributes.AttrVal) - removeFnAttr = Method(Void, ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addFnAttr = Method(Void, Attribute.AttrKind) + addAttributes = Method(Void, cast(int, Unsigned), ref(AttributeSet)) + removeAttributes = Method(Void, cast(int, Unsigned), ref(AttributeSet)) + #removeFnAttr = Method(Void, Attribute.AttrKind) # 3.4? + else: + addFnAttr = Method(Void, Attributes.AttrVal) + removeFnAttr = Method(Void, ref(Attributes)) #hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal) Create = StaticMethod(ptr(Function), diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index d954ed0..49071e3 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -6,7 +6,10 @@ from .ADT.StringRef import StringRef @GlobalValue class GlobalValue: - _include_ = 'llvm/GlobalValue.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/GlobalValue.h' + else: + _include_ = 'llvm/GlobalValue.h' LinkageTypes = Enum(''' ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage, diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index c0766e9..c4d8a86 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -18,7 +18,11 @@ IRBuilder = llvm.Class() @IRBuilder class IRBuilder: - _include_ = 'llvm/IRBuilder.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/IRBuilder.h' + else: + _include_ = 'llvm/IRBuilder.h' + _realname_ = 'IRBuilder<>' new = Constructor(ref(LLVMContext)) diff --git a/llvmpy/src/InlineAsm.py b/llvmpy/src/InlineAsm.py index 8793343..c96cef0 100644 --- a/llvmpy/src/InlineAsm.py +++ b/llvmpy/src/InlineAsm.py @@ -4,7 +4,10 @@ from .Value import Value from .DerivedTypes import FunctionType from .ADT.StringRef import StringRef -llvm.includes.add('llvm/InlineAsm.h') +if LLVM_VERSION >= (3, 3): + llvm.includes.add('llvm/IR/InlineAsm.h') +else: + llvm.includes.add('llvm/InlineAsm.h') InlineAsm = llvm.Class(Value) diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index e17e8a1..2771015 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -65,7 +65,10 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', from .ADT.StringRef import StringRef from .CallingConv import CallingConv -from .Attributes import Attributes +if LLVM_VERSION >= (3, 3): + from .Attributes import AttributeSet, Attribute +else: + from .Attributes import Attributes from .Type import Type @@ -142,8 +145,12 @@ class CallInst: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) - addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) - removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addAttribute = Method(Void, cast(int, Unsigned), Attribute.AttrKind) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attribute)) + else: + addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) getCalledFunction = Method(ptr(Function)) getCalledValue = Method(ptr(Value)) setCalledFunction = Method(Void, ptr(Function)) @@ -264,7 +271,10 @@ class UnaryInstruction: @IntrinsicInst class IntrinsicInst: - _include_ = 'llvm/IntrinsicInst.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/IntrinsicInst.h' + else: + _include_ = 'llvm/IntrinsicInst.h' _downcast_ = Value, User, Instruction #compare @@ -292,8 +302,12 @@ class InvokeInst: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) - addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) - removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + if LLVM_VERSION >= (3, 3): + addAttribute = Method(Void, cast(int, Unsigned), Attribute.AttrKind) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attribute)) + else: + addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) getCalledFunction = Method(ptr(Function)) getCalledValue = Method(ptr(Value)) setCalledFunction = Method(Void, ptr(Function)) diff --git a/llvmpy/src/LLVMContext.py b/llvmpy/src/LLVMContext.py index 4a6b49a..8ec1607 100644 --- a/llvmpy/src/LLVMContext.py +++ b/llvmpy/src/LLVMContext.py @@ -3,6 +3,9 @@ from .namespace import llvm @llvm.Class() class LLVMContext: - _include_ = "llvm/LLVMContext.h" + if LLVM_VERSION >= (3, 3): + _include_ = "llvm/IR/LLVMContext.h" + else: + _include_ = "llvm/LLVMContext.h" llvm.Function('getGlobalContext', ref(LLVMContext)) diff --git a/llvmpy/src/Linker.py b/llvmpy/src/Linker.py index 960bd90..5f1b7af 100644 --- a/llvmpy/src/Linker.py +++ b/llvmpy/src/Linker.py @@ -10,30 +10,33 @@ Linker = llvm.Class() @Linker class Linker: - ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors') + #ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors') LinkerMode = Enum('DestroySource, PreserveSource') - _new_w_empty = Constructor(cast(str, StringRef), - cast(str, StringRef), - ref(LLVMContext), - cast(int, Unsigned)).require_only(3) + if LLVM_VERSION >= (3, 3): + new = Constructor(ptr(Module)) + else: + _new_w_empty = Constructor(cast(str, StringRef), + cast(str, StringRef), + ref(LLVMContext), + cast(int, Unsigned)).require_only(3) - _new_w_existing = Constructor(cast(str, StringRef), - ptr(Module), - cast(int, Unsigned)).require_only(2) + _new_w_existing = Constructor(cast(str, StringRef), + ptr(Module), + cast(int, Unsigned)).require_only(2) - @CustomPythonStaticMethod - def new(progname, module_or_name, *args): - if isinstance(module_or_name, Module): - return _new_w_existing(progname, module_or_name, *args) - else: - return _new_w_empty(progname, module_or_name, *args) + @CustomPythonStaticMethod + def new(progname, module_or_name, *args): + if isinstance(module_or_name, Module): + return _new_w_existing(progname, module_or_name, *args) + else: + return _new_w_empty(progname, module_or_name, *args) delete = Destructor() getModule = Method(ptr(Module)) - releaseModule = Method(ptr(Module)) - getLastError = Method(cast(ConstStdString, str)) + #releaseModule = Method(ptr(Module)) + #getLastError = Method(cast(ConstStdString, str)) LinkInModule = CustomMethod('Linker_LinkInModule', PyObjectPtr, # boolean diff --git a/llvmpy/src/Module.py b/llvmpy/src/Module.py index 46fad5a..9dbe754 100644 --- a/llvmpy/src/Module.py +++ b/llvmpy/src/Module.py @@ -16,7 +16,10 @@ from .Metadata import NamedMDNode @Module class Module: - _include_ = "llvm/Module.h" + if LLVM_VERSION >= (3, 3): + _include_ = "llvm/IR/Module.h" + else: + _include_ = "llvm/Module.h" # Enumerators Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian') PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64') diff --git a/llvmpy/src/Support/Host.py b/llvmpy/src/Support/Host.py index 8163ebe..cd063e8 100644 --- a/llvmpy/src/Support/Host.py +++ b/llvmpy/src/Support/Host.py @@ -1,18 +1,29 @@ from binding import * from src.namespace import sys -isLittleEndianHost = sys.Function('isLittleEndianHost', - cast(Bool, bool)) - -isBigEndianHost = sys.Function('isBigEndianHost', - cast(Bool, bool)) - getDefaultTargetTriple = sys.Function('getDefaultTargetTriple', cast(ConstStdString, str)) -# llvm 3.3 -#getProcessTriple = sys.Function('getProcessTriple', -# cast(ConstStdString, str)) +if LLVM_VERSION >= (3, 3): + getProcessTriple = sys.Function('getProcessTriple', + cast(ConstStdString, str)) + + isLittleEndianHost = sys.CustomFunction('isLittleEndianHost', + 'llvm_sys_isLittleEndianHost', + cast(Bool, bool)) + + isBigEndianHost = sys.CustomFunction('isBigEndianHost', + 'llvm_sys_isBigEndianHost', + cast(Bool, bool)) + +else: + + isLittleEndianHost = sys.Function('isLittleEndianHost', + cast(Bool, bool)) + + isBigEndianHost = sys.Function('isBigEndianHost', + cast(Bool, bool)) + getHostCPUName = sys.Function('getHostCPUName', cast(ConstStdString, str)) diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index 1bd6843..84c0d5d 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -8,8 +8,10 @@ from src.ADT.StringRef import StringRef from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc from src.GlobalValue import GlobalValue from src.DataLayout import DataLayout -from src.TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) + +if LLVM_VERSION < (3, 3): + from src.TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) from src.PassManager import PassManagerBase from src.Support.FormattedStream import formatted_raw_ostream @@ -39,9 +41,11 @@ class TargetMachine: setMCUseDwarfDirectory = Method(Void, cast(bool, Bool)) getDataLayout = Method(const(ownedptr(DataLayout))) - getScalarTargetTransformInfo = Method(const( + + if LLVM_VERSION < (3, 3): + getScalarTargetTransformInfo = Method(const( ownedptr(ScalarTargetTransformInfo))) - getVectorTargetTransformInfo = Method(const( + getVectorTargetTransformInfo = Method(const( ownedptr(VectorTargetTransformInfo))) addPassesToEmitFile = Method(cast(bool, Bool), diff --git a/llvmpy/src/TargetTransformInfo.py b/llvmpy/src/TargetTransformInfo.py index 1208050..d51bc52 100644 --- a/llvmpy/src/TargetTransformInfo.py +++ b/llvmpy/src/TargetTransformInfo.py @@ -2,7 +2,10 @@ from binding import * from src.namespace import llvm from src.Pass import ImmutablePass -llvm.includes.add('llvm/TargetTransformInfo.h') +if LLVM_VERSION >= (3, 3): + llvm.includes.add('llvm/Analysis/TargetTransformInfo.h') +else: + llvm.includes.add('llvm/TargetTransformInfo.h') TargetTransformInfo = llvm.Class(ImmutablePass) ScalarTargetTransformInfo = llvm.Class() @@ -11,14 +14,17 @@ VectorTargetTransformInfo = llvm.Class() @ScalarTargetTransformInfo class ScalarTargetTransformInfo: - delete = Destructor() + if LLVM_VERSION < (3, 3): + delete = Destructor() @VectorTargetTransformInfo class VectorTargetTransformInfo: - delete = Destructor() + if LLVM_VERSION < (3, 3): + delete = Destructor() @TargetTransformInfo class TargetTransformInfo: - new = Constructor(ptr(ScalarTargetTransformInfo), - ptr(VectorTargetTransformInfo)) + if LLVM_VERSION < (3, 3): + new = Constructor(ptr(ScalarTargetTransformInfo), + ptr(VectorTargetTransformInfo)) diff --git a/llvmpy/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py index 86be4fb..146d409 100644 --- a/llvmpy/src/Transforms/PassManagerBuilder.py +++ b/llvmpy/src/Transforms/PassManagerBuilder.py @@ -36,7 +36,11 @@ class PassManagerBuilder: DisableSimplifyLibCalls = _attr_bool() DisableUnitAtATime = _attr_bool() DisableUnrollLoops = _attr_bool() - Vectorize = _attr_bool() + if LLVM_VERSION >= (3, 3): + BBVectorize = _attr_bool() + SLPVectorize = _attr_bool() + else: + Vectorize = _attr_bool() LoopVectorize = _attr_bool() LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo), diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index afc148c..50c4862 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -15,7 +15,10 @@ VectorType = llvm.Class(SequentialType) @Type class Type: - _include_ = 'llvm/Type.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/Type.h' + else: + _include_ = 'llvm/Type.h' TypeID = Enum(''' VoidTyID, HalfTyID, FloatTyID, DoubleTyID, diff --git a/llvmpy/src/ValueSymbolTable.py b/llvmpy/src/ValueSymbolTable.py index 7e8890c..8762156 100644 --- a/llvmpy/src/ValueSymbolTable.py +++ b/llvmpy/src/ValueSymbolTable.py @@ -4,7 +4,10 @@ from .ADT.StringRef import StringRef @ValueSymbolTable class ValueSymbolTable: - _include_ = 'llvm/ValueSymbolTable.h' + if LLVM_VERSION >= (3, 3): + _include_ = 'llvm/IR/ValueSymbolTable.h' + else: + _include_ = 'llvm/ValueSymbolTable.h' new = Constructor() delete = Destructor() lookup = Method(ptr(Value), cast(str, StringRef)) diff --git a/setup.py b/setup.py index 1dc8af8..2c3a38f 100644 --- a/setup.py +++ b/setup.py @@ -61,7 +61,12 @@ def auto_intrinsic_gen(incdir): # let's do auto intrinsic generation print("Generate intrinsic IDs") from tools import intrgen - path = "%s/llvm/Intrinsics.gen" % incdir + + if llvm_version >= (3, 3): + path = "%s/llvm/IR/Intrinsics.gen" % incdir + else: + path = "%s/llvm/Intrinsics.gen" % incdir + with open('llvm/_intrinsic_ids.py', 'w') as fout: intrgen.gen(path, fout) From 6d3253e4ea39a857a0f6119f561b8fd3e3ee50c3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 15:44:01 -0500 Subject: [PATCH 029/155] Add things to make MCJIT working --- llvm-config-win32.py | 2 ++ llvm/ee.py | 2 +- llvmpy/include/llvm_binding/extra.h | 1 + llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 ++ setup.py | 2 +- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 5f6c401..e191290 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -53,6 +53,7 @@ LLVMInterpreter LLVMipa LLVMipo LLVMJIT +LLVMMCJIT LLVMLinker LLVMMC LLVMMCParser @@ -71,6 +72,7 @@ LLVMX86Desc LLVMX86Disassembler LLVMX86Info LLVMX86Utils +LLVMDebugInfo Advapi32 Shell32 """.split(): diff --git a/llvm/ee.py b/llvm/ee.py index 7ea90d0..e87777a 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -232,7 +232,7 @@ def initialize_target(target, noraise=False): It is safe to initialize the same target multiple times. """ prefix = 'LLVMInitialize' - postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter'] + postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser'] try: for postfix in postfixes: getattr(api, '%s%s%s' % (prefix, target, postfix))() diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index cd1f59c..49ac261 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -30,6 +30,7 @@ #include #include +#include // to make MCJIT working #include "auto_pyobject.h" diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 3208269..d6dfe43 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -101,3 +101,5 @@ class ExecutionEngine: unwrapped = list(map(capsule.unwrap, args)) return self._runFunction(fn, tuple(unwrapped)) + finalizeObject = Method(Void) + diff --git a/setup.py b/setup.py index 2c3a38f..546e77e 100644 --- a/setup.py +++ b/setup.py @@ -124,7 +124,7 @@ else: extra_components = list(extra_components & enabled_components) libs_core, objs_core = get_libs_and_objs( - ['core', 'analysis', 'scalaropts', 'executionengine', + ['core', 'analysis', 'scalaropts', 'executionengine', 'mcjit', 'jit', 'native', 'interpreter', 'bitreader', 'bitwriter', 'instrumentation', 'ipa', 'ipo', 'transformutils', 'asmparser', 'linker', 'support', 'vectorize'] From 625858aa6fc48975c5f0bf45ffd3aa44f3d3b067 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 16:05:24 -0500 Subject: [PATCH 030/155] fixes --- llvmpy/include/llvm_binding/extra.h | 7 ++++--- setup.py | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 49ac261..161c52e 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -70,7 +70,7 @@ namespace extra{ static PyObject* callwrite(PyObject* self, PyObject* arg) { - char meth[] = "method"; + char meth[] = "write"; char fmt[] = "O"; return PyObject_CallMethod(self, meth, fmt, arg); } @@ -965,7 +965,7 @@ PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) } } - +#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3 static PyObject* llvm_sys_isLittleEndianHost() { @@ -982,4 +982,5 @@ PyObject* llvm_sys_isBigEndianHost() Py_RETURN_TRUE; else Py_RETURN_FALSE; -} \ No newline at end of file +} +#endif diff --git a/setup.py b/setup.py index 546e77e..e94a258 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ def run_llvm_config(extra_args): return stdout.decode().strip() llvm_version = run_llvm_config(['--version']) + print('LLVM version = %r' % llvm_version) targets_built = run_llvm_config(['--targets-built']) @@ -62,7 +63,7 @@ def auto_intrinsic_gen(incdir): print("Generate intrinsic IDs") from tools import intrgen - if llvm_version >= (3, 3): + if llvm_version.startswith('3.3'): path = "%s/llvm/IR/Intrinsics.gen" % incdir else: path = "%s/llvm/Intrinsics.gen" % incdir From 56a511854a6fd7f6776c58630088498385e5af30 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 16:43:50 -0500 Subject: [PATCH 031/155] update "attribute(s)" ignorance --- llvm/core.py | 78 +++++++++++++++++++++++++++++++++++--------------- llvm/passes.py | 23 +++++++++++---- 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 9c8501e..d413bef 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -325,11 +325,17 @@ class VisibilityEnum(Enum): VisibilityEnum.declare() -# parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) +# parameter attributes +# LLVM 3.2 llvm::Attributes::AttrVal (see llvm/Attributes.h) +# LLVM 3.3 llvm::Attribute::AttrKind (see llvm/Attributes.h) class AttrEnum(Enum): prefix = 'ATTR_' - AttrVal = api.llvm.Attributes.AttrVal + if llvm.version >= (3, 3): + AttrVal = api.llvm.Attribute.AttrKind + else: + AttrVal = api.llvm.Attributes.AttrVal + ATTR_NONE = AttrVal.None_ ATTR_ZEXT = AttrVal.ZExt ATTR_SEXT = AttrVal.SExt @@ -1436,29 +1442,55 @@ class Argument(Value): _valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS, ATTR_NO_CAPTURE, ATTR_STRUCT_RET]) - def add_attribute(self, attr): - context = api.llvm.getGlobalContext() - attrbldr = api.llvm.AttrBuilder.new() - attrbldr.addAttribute(attr) - attrs = api.llvm.Attributes.get(context, attrbldr) - self._ptr.addAttr(attrs) - if attr not in self: - raise ValueError("Attribute %s is not valid for arg %s" % - (attr, self)) + if llvm.version >= (3, 3): + def add_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.addAttr(attrs) + + if attr not in self: + raise ValueError("Attribute %r is not valid for arg %s" % + (attr, self)) - def remove_attribute(self, attr): - context = api.llvm.getGlobalContext() - attrbldr = api.llvm.AttrBuilder.new() - attrbldr.addAttribute(attr) - attrs = api.llvm.Attributes.get(context, attrbldr) - self._ptr.removeAttr(attrs) + def remove_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.removeAttr(attrs) - def _set_alignment(self, align): - context = api.llvm.getGlobalContext() - attrbldr = api.llvm.AttrBuilder.new() - attrbldr.addAlignmentAttr(align) - attrs = api.llvm.Attributes.get(context, attrbldr) - self._ptr.addAttr(attrs) + def _set_alignment(self, align): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.addAttr(attrs) + else: + def add_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + if attr not in self: + raise ValueError("Attribute %r is not valid for arg %s" % + (attr, self)) + + def remove_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttr(attrs) + + def _set_alignment(self, align): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) def _get_alignment(self): return self._ptr.getParamAlignment() diff --git a/llvm/passes.py b/llvm/passes.py index 068a7a3..b13fa84 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -70,13 +70,24 @@ class PassManagerBuilder(llvm.Wrapper): def size_level(self, sizelevel): self._ptr.SizeLevel = sizelevel - @property - def vectorize(self): - return self._ptr.Vectorize + if llvm.version >= (3, 3): + @property + def bbvectorize(self): + return self._ptr.BBVectorize - @vectorize.setter - def vectorize(self, enable): - self._ptr.Vectorize = enable + @bbvectorize.setter + def bbvectorize(self, enable): + self._ptr.BBVectorize = enable + + vectorize = bbvectorize + else: + @property + def vectorize(self): + return self._ptr.Vectorize + + @vectorize.setter + def vectorize(self, enable): + self._ptr.Vectorize = enable @property From 319984f0e0a69672dc6dd315062c88bdd67987cc Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 16:57:29 -0500 Subject: [PATCH 032/155] add MCJIT test --- llvm/core.py | 6 +++++- llvm/ee.py | 7 ++++++- llvm/test_llvmpy.py | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index d413bef..99657d7 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2454,4 +2454,8 @@ if api.llvm.InitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") - +if api.llvm.InitializeNativeTargetAsmParser(): + # required by MCJIT? + # should this be an optional feature? + # should user trigger the initialization? + raise llvm.LLVMException("No native asm parser!?") diff --git a/llvm/ee.py b/llvm/ee.py index e87777a..583201b 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -152,7 +152,9 @@ class EngineBuilder(llvm.Wrapper): engine = self._ptr.create(tm._ptr) else: engine = self._ptr.create() - return ExecutionEngine(engine) + ee = ExecutionEngine(engine) + ee.finalize_object() # no effect for legacy JIT + return ee def select_target(self, *args): '''get the corresponding target machine @@ -218,6 +220,9 @@ class ExecutionEngine(llvm.Wrapper): 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() diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index e21a825..8d38ed0 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1353,6 +1353,31 @@ class TestCmp(TestCase): tests.append(TestCmp) +# --------------------------------------------------------------------------- + +class TestMCJIT(TestCase): + def test_mcjit(self): + m = Module.new('oidfjs') + fnty = Type.function(Type.int(), [Type.int(), Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bldr = Builder.new(bb) + bldr.ret(bldr.add(*func.args)) + + func.verify() + + engine = EngineBuilder.new(m).mcjit(True).create() + ptr = engine.get_pointer_to_function(func) + + from ctypes import c_int, CFUNCTYPE + callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) + self.assertEqual(321 + 123, callee(321, 123)) + +if llvm.version >= (3, 3): + # MCJIT broken in 3.2 + # The test will segfault in OSX? + tests.append(TestMCJIT) + # --------------------------------------------------------------------------- def run(verbosity=1): From c0e9dedc9048e7849b767c193542ef507d21f8c0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 31 Jul 2013 17:50:30 -0500 Subject: [PATCH 033/155] add binding to dynamiclibrary namespace for multimodule linking --- llvm/ee.py | 14 ++++++++++++++ llvm/test_llvmpy.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/llvm/ee.py b/llvm/ee.py index 583201b..fe21ea2 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -195,6 +195,9 @@ class ExecutionEngine(llvm.Wrapper): 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) @@ -371,3 +374,14 @@ class TargetMachine(llvm.Wrapper): def feature_string(self): return self._ptr.getTargetFeatureString() + + +#===----------------------------------------------------------------------=== +# 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) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 8d38ed0..19c402c 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1373,6 +1373,43 @@ class TestMCJIT(TestCase): callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) self.assertEqual(321 + 123, callee(321, 123)) + def test_multi_module_linking(self): + # generate external library module + m = Module.new('external-library-module') + fnty = Type.function(Type.int(), [Type.int(), Type.int()]) + libfname = 'myadd' + func = m.add_function(fnty, libfname) + bb = func.append_basic_block('') + bldr = Builder.new(bb) + bldr.ret(bldr.add(*func.args)) + func.verify() + + # JIT the lib module and bind dynamic symbol + libengine = EngineBuilder.new(m).mcjit(True).create() + myadd_ptr = libengine.get_pointer_to_function(func) + le.dylib_add_symbol(libfname, myadd_ptr) + + # reference external library + m = Module.new('user') + fnty = Type.function(Type.int(), [Type.int(), Type.int()]) + func = m.add_function(fnty, 'foo') + bb = func.append_basic_block('') + bldr = Builder.new(bb) + extadd = m.get_or_insert_function(fnty, name=libfname) + bldr.ret(bldr.call(extadd, func.args)) + func.verify() + + # JIT the user module + engine = EngineBuilder.new(m).mcjit(True).create() + ptr = engine.get_pointer_to_function(func) + self.assertEqual(myadd_ptr, + engine.get_pointer_to_named_function(libfname)) + + from ctypes import c_int, CFUNCTYPE + callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) + self.assertEqual(321 + 123, callee(321, 123)) + + if llvm.version >= (3, 3): # MCJIT broken in 3.2 # The test will segfault in OSX? From c4db61c7f53b513645761dadfdc19a105aa410e0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 1 Aug 2013 13:02:45 -0500 Subject: [PATCH 034/155] add test for basic arith operators and problems for div and mod on 32bit platforms --- llvm/test_llvmpy.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 19c402c..e51c406 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1415,6 +1415,68 @@ if llvm.version >= (3, 3): # The test will segfault in OSX? tests.append(TestMCJIT) + +class TestArith(TestCase): + ''' + Test basic arithmetic support with LLVM old-JIT + ''' + def func_template(self, ty, op): + m = Module.new('dofjaa') + fnty = Type.function(ty, [ty, ty]) + fn = m.add_function(fnty, 'foo') + bldr = Builder.new(fn.append_basic_block('')) + bldr.ret(getattr(bldr, op)(*fn.args)) + + engine = EngineBuilder.new(m).mcjit(True).create() + ptr = engine.get_pointer_to_function(fn) + + from ctypes import c_uint32, c_uint64, c_float, c_double, CFUNCTYPE + + maptypes = { + Type.int(32): c_uint32, + Type.int(64): c_uint64, + Type.float(): c_float, + Type.double(): c_double, + } + cty = maptypes[ty] + prototype = CFUNCTYPE(*[cty] * 3) + callee = prototype(ptr) + callee(12, 23) + + def template(self, iop, fop): + inttys = [Type.int(32), Type.int(64)] + flttys = [Type.float(), Type.double()] + + for ty in inttys: + self.func_template(ty, iop) + for ty in flttys: + self.func_template(ty, fop) + + def test_add(self): + self.template('add', 'fadd') + + def test_sub(self): + self.template('sub', 'fsub') + + def test_mul(self): + self.template('mul', 'fmul') + + def test_div(self): + if BITS == 32: + print('skipped test for div') + print('known failure due to unresolved external symbol __udivdi3') + return + self.template('udiv', 'fdiv') + + def test_rem(self): + if BITS == 32: + print('skipped test for rem') + print('known failure due to unresolved external symbol __umoddi3') + return + self.template('urem', 'frem') + +tests.append(TestArith) + # --------------------------------------------------------------------------- def run(verbosity=1): From 2a25b1c2b3819bb11fe330dfd64674c06d5db00d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 1 Aug 2013 11:50:36 -0500 Subject: [PATCH 035/155] fix avx detection for py3 --- llvm/workaround/avx_support.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/workaround/avx_support.py b/llvm/workaround/avx_support.py index 81cb936..0b1c2da 100644 --- a/llvm/workaround/avx_support.py +++ b/llvm/workaround/avx_support.py @@ -50,8 +50,7 @@ def detect_osx_like(): stdout=subprocess.PIPE) except OSError: return False - - features = info.stdout.read() + features = info.stdout.read().decode('UTF8') features = features.split() return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features From 0421ad8456fe86facbd6d975cf47ea05845f2671 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 2 Aug 2013 12:12:35 -0500 Subject: [PATCH 036/155] add dev docs --- llvmpy/README | 5 -- llvmpy/README.md | 151 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 5 deletions(-) delete mode 100644 llvmpy/README create mode 100644 llvmpy/README.md diff --git a/llvmpy/README b/llvmpy/README deleted file mode 100644 index 2bfabcd..0000000 --- a/llvmpy/README +++ /dev/null @@ -1,5 +0,0 @@ -# README - -This is a reimplementation of the LLVM binding, aiming to provide a more familiar interface to the C++ API whenever possible. - -The implementation uses a custom DSL in python to describe the interface (under binding directory). The DSL serves as input to *gen.py* for generation of the .cpp and .py files for the actual binding. diff --git a/llvmpy/README.md b/llvmpy/README.md new file mode 100644 index 0000000..4e444f8 --- /dev/null +++ b/llvmpy/README.md @@ -0,0 +1,151 @@ +# README + +This is a reimplementation of the LLVM binding, aiming to provide a more +familiar interface to the C++ API whenever possible. + +The implementation uses a custom DSL in python to describe the interface. +The DSL serves as input to *gen/gen.py* for generation of the .cpp and .py files +for the actual binding. + +# How to Add New Class + +Let's use the `llvm::Module` as an example because it should be one of the most +familiar class in LLVM. + +Reference code in https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Module.py +and see LLVM documentation at http://llvm.org/docs/doxygen/html/classllvm_1_1Module.html + +1) Import binding helpers + +```python +from binding import * +# Yes, it is bad practice to import star. +# I will fix it one day. +``` + +2) Import LLVM namespace + +```python +from .namespace import llvm +``` + +3) Declare the class + +```python +Module = llvm.Class() +``` + +4) Import all the dependencies for the definition + +5) Define the class + +```python +@Module +class Module: + ... +``` + +## Inside the definition... + +5.1) Use the ``_include_`` attribute to add include files. + +5.2) Use ``Enum`` to create an enumerator type. + +5.3) Make constructor + +Not every class needs to have a binding for the constructor. +Only add things that will be used. + +```python +new = Constructor(cast(str, StringRef), ref(LLVMContext)) +``` + +The constructor must be named as "new". + +The args to ``Constructor`` are parameters of the signature. +The first parameter means cast Python string to a StringRef. +The second parameter means pass LLVMContext object as a value reference. + +5.4) Make destructor + +Not every class needs to have a binding for the destructor. +Only add things that will be used. +If it is always owned by another object, it usually does not need to have one. + +```python +delete = Destructor() +``` + +The destructor must be named as "delete". + +5.5) Add Simple Methods + +```python +getFunction = Method(ptr(Function), cast(str, StringRef)) +``` + +The first arg is the return type: a ponter to Function. +The rest of the args are for the parameters. + +Note: ``cast(fromtype, totype)`` can be used as return-type as well. +In that case, the ``fromtype`` will usually refer to a LLVM object +and the ``totype`` will refer to the Python object. + +5.6) Add custom methods defined in C++ + +The ``list_functions`` is created as a ``CustomMethod``. + +```python +list_functions = CustomMethod('Module_list_functions', PyObjectPtr) +``` + +The first arg is the name that appears in C++. +The second argument is the return-type. +The rest of the arguments are parameters. + +The definition of ``Module_list_functions`` is located in +"include/llvm_binding/extra.h". + +5.7) Add custom python method + +One can also add custom methods in Python, e.g. ``__str__``. + +```python +@CustomPythonMethod +def __str__(self): + from llvmpy import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() +``` + +The body of ``__str__`` is directly copied to the Python output file. +Thus, it can't reference to anything in current file scope. + +# Static Methods + +``StaticMethod`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/PassRegistry.py + +``CustomStaticMethod`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Support/TargetRegistry.py + + +# Namespace + +``Namespace`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Support/CodeGen.py + +# Functions + +``Function`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Assembly/Parser.py + +``CustomFunction`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Bitcode/ReaderWriter.py + + + + + +# Other Things from the binding.py + +https://github.com/llvmpy/llvmpy/blob/master/llvmpy/gen/binding.py + +The list of C++ types: https://github.com/llvmpy/llvmpy/blob/master/llvmpy/gen/binding.py#L218 + From 84a95945ea7ec06ff361fc3aa62ca623bb00f516 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 6 Aug 2013 14:17:14 -0500 Subject: [PATCH 037/155] update marker header file --- llvm-config-win32.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index e191290..8c268cb 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -108,7 +108,7 @@ def main(): elif option == '--includedir': incdir = join(find_llvm_prefix(), 'include') - ensure_file(join(incdir, 'llvm' , 'BasicBlock.h')) + ensure_file(join(incdir, 'llvm' , 'Linker.h')) print(incdir) elif option == '--libdir': From c20c4d776f9b44475cae61b7da8922895dd09817 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 14:42:49 -0500 Subject: [PATCH 038/155] fix exception handling for TargetMachine --- llvm/ee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/ee.py b/llvm/ee.py index fe21ea2..832f422 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -282,7 +282,7 @@ class TargetMachine(llvm.Wrapper): with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(triple, error) if not target: - raise llvm.LLVMException(error) + raise llvm.LLVMException(error.getvalue()) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") target_options = api.llvm.TargetOptions.new() From b4d943a6717ff2431c4df6578d6afccbed3f9f62 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 14:43:23 -0500 Subject: [PATCH 039/155] add autoselect ELF generation for MCJIT --- llvm/ee.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/ee.py b/llvm/ee.py index 832f422..4090a0f 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -30,6 +30,7 @@ "Execution Engine and related classes." +import sys from io import BytesIO import contextlib @@ -150,6 +151,12 @@ class EngineBuilder(llvm.Wrapper): ''' if tm is not None: engine = self._ptr.create(tm._ptr) + elif (sys.prefix.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) else: engine = self._ptr.create() ee = ExecutionEngine(engine) @@ -173,6 +180,7 @@ class EngineBuilder(llvm.Wrapper): '''Enable/disable MCJIT ''' self._ptr.setUseMCJIT(enable) + self._use_mcjit = True return self #===----------------------------------------------------------------------=== From eb4fc653f2ca3e8d9c4f31817b791070a75886d3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 14:52:16 -0500 Subject: [PATCH 040/155] ensure MCJIT ELF autoselect works --- llvm/ee.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/ee.py b/llvm/ee.py index 4090a0f..b91c4cb 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -151,12 +151,12 @@ class EngineBuilder(llvm.Wrapper): ''' if tm is not None: engine = self._ptr.create(tm._ptr) - elif (sys.prefix.startswith('win32') and + 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) + engine = self._ptr.create(tm._ptr) else: engine = self._ptr.create() ee = ExecutionEngine(engine) From 1e9d37a64e489efdd9c06a2b365e7b6063336652 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 15:59:17 -0500 Subject: [PATCH 041/155] add no-signed-wrap and no-unsigned-wrap flags to IRBuilder --- llvm/core.py | 20 ++++++++++++-------- llvm/test_llvmpy.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 99657d7..0fbd5ab 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2124,20 +2124,23 @@ class Builder(llvm.Wrapper): # arithmethic, bitwise and logical - def add(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) + def add(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fadd(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) - def sub(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) + def sub(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fsub(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) - def mul(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) + def mul(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fmul(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) @@ -2160,8 +2163,9 @@ class Builder(llvm.Wrapper): def frem(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) - def shl(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) + def shl(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def lshr(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index e51c406..9c3e695 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1477,6 +1477,40 @@ class TestArith(TestCase): tests.append(TestArith) +class TestNUWNSW(TestCase): + def make_module(self): + mod = Module.new('asdfa') + fnty = Type.function(Type.void(), [Type.int()] * 2) + func = mod.add_function(fnty, 'foo') + bldr = Builder.new(func.append_basic_block('')) + return mod, func, bldr + + def has_nsw(self, inst, op): + self.assertTrue(('%s nsw' % op) in str(inst), "NSW flag does not work") + + def has_nuw(self, inst, op): + self.assertTrue(('%s nuw' % op) in str(inst), "NUW flag does not work") + + def _test_template(self, opf, opname): + mod, func, bldr = self.make_module() + a, b = func.args + self.has_nsw(opf(bldr, a, b, nsw=True), opname) + self.has_nuw(opf(bldr, a, b, nuw=True), opname) + + def test_add_nuw_nsw(self): + self._test_template(Builder.add, 'add') + + def test_sub_nuw_nsw(self): + self._test_template(Builder.sub, 'sub') + + def test_mul_nuw_nsw(self): + self._test_template(Builder.mul, 'mul') + + def test_shl_nuw_nsw(self): + self._test_template(Builder.shl, 'shl') + +tests.append(TestNUWNSW) + # --------------------------------------------------------------------------- def run(verbosity=1): From cfe5e9ea92f617b5a3e02b70aff5f26963f03393 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 16:11:24 -0500 Subject: [PATCH 042/155] add exact flag to IRBuilder --- llvm/core.py | 20 ++++++++++++-------- llvm/test_llvmpy.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 0fbd5ab..7535b0f 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2145,11 +2145,13 @@ class Builder(llvm.Wrapper): def fmul(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) - def udiv(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) + def udiv(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name, + exact)) - def sdiv(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) + def sdiv(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name, + exact)) def fdiv(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) @@ -2167,11 +2169,13 @@ class Builder(llvm.Wrapper): return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name, nuw, nsw)) - def lshr(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) + def lshr(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name, + exact)) - def ashr(self, lhs, rhs, name=""): - return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) + def ashr(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name, + exact)) def and_(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 9c3e695..250e404 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1511,6 +1511,37 @@ class TestNUWNSW(TestCase): tests.append(TestNUWNSW) + +class TestExact(TestCase): + def make_module(self): + mod = Module.new('asdfa') + fnty = Type.function(Type.void(), [Type.int()] * 2) + func = mod.add_function(fnty, 'foo') + bldr = Builder.new(func.append_basic_block('')) + return mod, func, bldr + + def has_exact(self, inst, op): + self.assertTrue(('%s exact' % op) in str(inst), "exact flag does not work") + + def _test_template(self, opf, opname): + mod, func, bldr = self.make_module() + a, b = func.args + self.has_exact(opf(bldr, a, b, exact=True), opname) + + def test_udiv_exact(self): + self._test_template(Builder.udiv, 'udiv') + + def test_sdiv_exact(self): + self._test_template(Builder.sdiv, 'sdiv') + + def test_lshr_exact(self): + self._test_template(Builder.lshr, 'lshr') + + def test_ashr_exact(self): + self._test_template(Builder.ashr, 'ashr') + +tests.append(TestExact) + # --------------------------------------------------------------------------- def run(verbosity=1): From 1ed3c773103a09d126a645c6af9f4bb5809a4d99 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 12 Aug 2013 16:16:38 -0500 Subject: [PATCH 043/155] add neg nuw nsw --- llvm/core.py | 4 ++-- llvm/test_llvmpy.py | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 7535b0f..945dd86 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2186,8 +2186,8 @@ class Builder(llvm.Wrapper): def xor(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) - def neg(self, val, name=""): - return _make_value(self._ptr.CreateNeg(val._ptr, name)) + def neg(self, val, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateNeg(val._ptr, name, nuw, nsw)) def not_(self, val, name=""): return _make_value(self._ptr.CreateNot(val._ptr, name)) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 250e404..2a5c1f5 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1509,6 +1509,13 @@ class TestNUWNSW(TestCase): def test_shl_nuw_nsw(self): self._test_template(Builder.shl, 'shl') + def test_neg_nuw_nsw(self): + mod, func, bldr = self.make_module() + a, b = func.args + self.has_nsw(bldr.neg(a, nsw=True), 'sub') + self.has_nuw(bldr.neg(a, nuw=True), 'sub') + + tests.append(TestNUWNSW) From d060c10096ea97d091a8cced5610a5bc887971a9 Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:42:54 -0500 Subject: [PATCH 044/155] add conda build script --- buildscripts/condarecipe/bld.bat | 6 ++++++ buildscripts/condarecipe/build.sh | 13 +++++++++++++ buildscripts/condarecipe/meta.yaml | 27 +++++++++++++++++++++++++++ buildscripts/condarecipe/run_test.py | 19 +++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 buildscripts/condarecipe/bld.bat create mode 100644 buildscripts/condarecipe/build.sh create mode 100644 buildscripts/condarecipe/meta.yaml create mode 100644 buildscripts/condarecipe/run_test.py diff --git a/buildscripts/condarecipe/bld.bat b/buildscripts/condarecipe/bld.bat new file mode 100644 index 0000000..45ef910 --- /dev/null +++ b/buildscripts/condarecipe/bld.bat @@ -0,0 +1,6 @@ +set LLVMPY_DYNLINK=0 +set INCLUDE=%LIBRARY_INC% +set LIBPATH=%LIBRARY_LIB% +set LIB=%LIBRARY_LIB% +python setup.py install +if errorlevel 1 exit 1 diff --git a/buildscripts/condarecipe/build.sh b/buildscripts/condarecipe/build.sh new file mode 100644 index 0000000..5c98fde --- /dev/null +++ b/buildscripts/condarecipe/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [[ (`uname` == Linux) && (`uname -m` != armv6l) ]] +then + export CC=gcc + #gcc44 + export CXX=g++ + #g++44 +fi + +export LLVMPY_DYNLINK=$DISTRO_BUILD + +$PYTHON setup.py install diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml new file mode 100644 index 0000000..05007f3 --- /dev/null +++ b/buildscripts/condarecipe/meta.yaml @@ -0,0 +1,27 @@ +package: + name: llvmpy + version: master + +source: + git_url: git@github.com:llvmpy/llvmpy.git +# git_tag: 0.12.0 + +requirements: + build: + - llvm + - python + run: + - llvm [unix] + - python + +test: + imports: + - llvm + - llvmpy + - llvmpy._api + - llvmpy._capsule + - llpython + - llvm_array + - llvm_cbuilder + + diff --git a/buildscripts/condarecipe/run_test.py b/buildscripts/condarecipe/run_test.py new file mode 100644 index 0000000..281a599 --- /dev/null +++ b/buildscripts/condarecipe/run_test.py @@ -0,0 +1,19 @@ +import sys +import platform +import llvm + +from llvm.core import Module +from llvm.ee import EngineBuilder +m = Module.new('fjoidajfa') +eb = EngineBuilder.new(m) +target = eb.select_target() + +print('target.triple=%r' % target.triple) +if sys.platform == 'darwin': + s = {'64bit': 'x86_64', '32bit': 'x86'}[platform.architecture()[0]] + assert target.triple.startswith(s + '-apple-darwin') + +assert llvm.test(verbosity=2) == 0 + +print('llvm.__version__: %s' % llvm.__version__) +#assert llvm.__version__ == '0.12.0' From bf0253c9f9d96bb922f4c88ecffc85d01f0ecbb1 Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:55:13 -0500 Subject: [PATCH 045/155] add chrpath --- buildscripts/condarecipe/meta.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml index 05007f3..15d9f8a 100644 --- a/buildscripts/condarecipe/meta.yaml +++ b/buildscripts/condarecipe/meta.yaml @@ -10,6 +10,7 @@ requirements: build: - llvm - python + - chrpath run: - llvm [unix] - python From 3a289ccace2efe5d3f898f59441768c5865445ff Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:55:42 -0500 Subject: [PATCH 046/155] add percent python --- buildscripts/condarecipe/bld.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/condarecipe/bld.bat b/buildscripts/condarecipe/bld.bat index 45ef910..e9177c5 100644 --- a/buildscripts/condarecipe/bld.bat +++ b/buildscripts/condarecipe/bld.bat @@ -2,5 +2,5 @@ set LLVMPY_DYNLINK=0 set INCLUDE=%LIBRARY_INC% set LIBPATH=%LIBRARY_LIB% set LIB=%LIBRARY_LIB% -python setup.py install +%PYTHON% setup.py install if errorlevel 1 exit 1 From 1be8b07cedfff7a73aaad59e4b076a75dde8f03d Mon Sep 17 00:00:00 2001 From: majidaldo Date: Tue, 13 Aug 2013 14:59:33 -0500 Subject: [PATCH 047/155] charpath just for linux --- buildscripts/condarecipe/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml index 15d9f8a..b079986 100644 --- a/buildscripts/condarecipe/meta.yaml +++ b/buildscripts/condarecipe/meta.yaml @@ -10,7 +10,7 @@ requirements: build: - llvm - python - - chrpath + - chrpath [linux] run: - llvm [unix] - python From d10b182479b58a25bb45a6bd5c8d1a6aa8ee468c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 13 Aug 2013 15:27:49 -0500 Subject: [PATCH 048/155] dislabe MCJIT tests for LLVM3.2 --- llvm/test_llvmpy.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 2a5c1f5..f8d6adb 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1418,7 +1418,7 @@ if llvm.version >= (3, 3): class TestArith(TestCase): ''' - Test basic arithmetic support with LLVM old-JIT + Test basic arithmetic support with LLVM MCJIT ''' def func_template(self, ty, op): m = Module.new('dofjaa') @@ -1475,7 +1475,9 @@ class TestArith(TestCase): return self.template('urem', 'frem') -tests.append(TestArith) +if llvm.version >= (3, 3): + # MCJIT is broken in 3.2 + tests.append(TestArith) class TestNUWNSW(TestCase): def make_module(self): From 07c64779d8e3a86d0ac64139bf0bafd26b629e1e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 13 Aug 2013 18:38:41 -0500 Subject: [PATCH 049/155] begin low-level runtime implementation --- llrtc/Makefile | 21 ++++++++++ llrtc/README.md | 25 +++++++++++ llrtc/common.mk | 26 ++++++++++++ llrtc/lib/Makefile | 44 +++++++++++++++++++ llrtc/lib/test_udivmod64.c | 22 ++++++++++ llrtc/lib/test_udivmod64.py | 53 +++++++++++++++++++++++ llrtc/lib/udivmod64.c | 84 +++++++++++++++++++++++++++++++++++++ llrtc/lib/udivmod64.h | 11 +++++ llrtc/tools/striptriple.py | 15 +++++++ 9 files changed, 301 insertions(+) create mode 100644 llrtc/Makefile create mode 100644 llrtc/README.md create mode 100644 llrtc/common.mk create mode 100644 llrtc/lib/Makefile create mode 100644 llrtc/lib/test_udivmod64.c create mode 100644 llrtc/lib/test_udivmod64.py create mode 100644 llrtc/lib/udivmod64.c create mode 100644 llrtc/lib/udivmod64.h create mode 100644 llrtc/tools/striptriple.py diff --git a/llrtc/Makefile b/llrtc/Makefile new file mode 100644 index 0000000..c271d0e --- /dev/null +++ b/llrtc/Makefile @@ -0,0 +1,21 @@ +DIRECTORIES = divmod + +all: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir; \ + done + +test: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir test; \ + done + +clean-test: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir clean-test; \ + done + +clean: + for mydir in $(DIRECTORIES); do \ + make -C $$mydir clean; \ + done \ No newline at end of file diff --git a/llrtc/README.md b/llrtc/README.md new file mode 100644 index 0000000..539d9c3 --- /dev/null +++ b/llrtc/README.md @@ -0,0 +1,25 @@ +# LLRT: Low Level Runtime + +## Why? + +The same reason for LLVM compiler-rt. LLVM generates libgcc symbols, such as +__divdi3 for 64-bit division on 32-bit platform. They are not also available. +We need to ship compiler-rt but it is not Windows ready. +This subproject aims to provide a small portable subset of compiler-rt. +Start small and add only the things we really needed. +Performance is not crucial but should not be terrible. +Functionality and usefullness should be more important than performance. + +## Developer Instructions + +LLRT implements some functionalities in compiler-rt in ANSI C. +The C files are compiled using clang to produce LLVM IR which are shipped. +The IR files are committed in the repository. +So, remember to build the IR files commit them after modifying the C files. + +## Build Requirement + +- Make +- Clang +- Python + diff --git a/llrtc/common.mk b/llrtc/common.mk new file mode 100644 index 0000000..3de9c12 --- /dev/null +++ b/llrtc/common.mk @@ -0,0 +1,26 @@ +CLANG = clang +CF = -Wall -ansi +OUTDIR = .. + +all: ir + +$(OUTPUT).c: $(OUTPUT).h + +$(OUTPUT): test.c $(OUTPUT).c + $(CLANG) $(CF) -ftrapv -o $@ $+ + +test: $(OUTPUT) + python test.py + +ir: + CLANG -m32 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86/$(OUTPUT).ll + CLANG -m64 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86_64/$(OUTPUT).ll + python ../tools/striptriple.py $(OUTDIR)/x86/$(OUTPUT).ll + python ../tools/striptriple.py $(OUTDIR)/x86_64/$(OUTPUT).ll + +clean-test: + rm -f $(OUTPUT) + +clean: clean-test + rm -f $(OUTDIR)/x86/$(OUTPUT).ll + rm -f $(OUTDIR)/x86_64/$(OUTPUT).ll diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile new file mode 100644 index 0000000..1bb325f --- /dev/null +++ b/llrtc/lib/Makefile @@ -0,0 +1,44 @@ +OUTPUT = llrt +SOURCES = udivmod64.c + +CLANG = clang +CF = -Wall -ansi +CF_TEST = $(CF) -ftrapv +CF_BUILD = $(CF) -O0 -emit-llvm +OUTDIR = .. + +all: ir + +ir: $(SOURCES) + $(CLANG) -m32 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86.ll -c $(SOURCES) + python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86.ll + $(CLANG) -m64 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86_64.ll -c $(SOURCES) + python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86_64.ll + +lib$(OUTPUT).a: $(SOURCES) + $(CLANG) $(CF) -o $@ -c $+ + +build-test: lib$(OUTPUT).a + for src in $(SOURCES); do \ + $(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \ + done; + +test: build-test + for src in $(SOURCES); do \ + echo "testing $${src%.*}"; \ + python test_$${src%.*}.py > test_$${src%.*}.out; \ + done; + +clean-test: + rm -f *.out + rm -f *.a + for src in $(SOURCES); do \ + rm -f test_$${src%.*} ;\ + done; + +clean-dist: + rm $(OUTDIR)/*.ll + +clean: clean-test clean-dist + +udivmod64.c: udivmod64.h diff --git a/llrtc/lib/test_udivmod64.c b/llrtc/lib/test_udivmod64.c new file mode 100644 index 0000000..e2935c5 --- /dev/null +++ b/llrtc/lib/test_udivmod64.c @@ -0,0 +1,22 @@ +#include +#include + +extern uint64_t +udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); + +int main(int argc, char * argv[]){ + uint64_t n, d, q, r; + if (argc != 3) { + printf("invalid argument: %s dividend divisor", argv[0]); + return 1; + } + sscanf(argv[1], "%llu", &n); + sscanf(argv[2], "%llu", &d); + + q = udivmod64(n, d, &r); + + printf("%llu\n", q); + printf("%llu\n", r); + + return 0; +} \ No newline at end of file diff --git a/llrtc/lib/test_udivmod64.py b/llrtc/lib/test_udivmod64.py new file mode 100644 index 0000000..487a458 --- /dev/null +++ b/llrtc/lib/test_udivmod64.py @@ -0,0 +1,53 @@ +import math +import os +import subprocess +udt = os.path.join('.', 'test_udivmod64') + +def testcase(dividend, divisor): + print 'divmod64(%d, %d)' % (dividend, divisor) + + procargs = ('%s %s %s' % (udt, dividend, divisor)).split() + result = subprocess.check_output(procargs) + gotQ, gotR = map(int, result.splitlines()) + + expectQ = dividend // divisor + expectR = dividend % divisor + + print 'Q = %d, R = %d' % (gotQ, gotR) + + if expectQ != gotQ: + raise ValueError("invalid quotient: got=%d but expect=%d" % + (gotQ, expectQ)) + if expectR != gotR: + raise ValueError("invalid remainder: got=%d but expect=%d" % + (gotR, expectR)) + print 'OK' + +def testsequence(): + subjects = [ + (0, 1), + (0, 0xffffffffffffffff), + (1, 2), + (1, 983219), + (2, 2), + (3, 2), + (1024, 2), + (2048, 512), + (21321, 512), + (9329189, 1031), + (0xffffffff, 2), + (0xffffffff, 0xffff), + (0x1ffffffff, 2), + (0x1ffffffff, 0xffff), + (0xffff, 0xffffffff), + (0xffffffffffffffff, 0xffff), + (0xffffffffffffffff, 0x7fffffffffffffff), + (0xffffffffffffffff, 0xfffffffffffffff0), + (0xffffffffffffffff, 87655678587161901), + ] + + for dvd, dvr in subjects: + testcase(dvd, dvr) + +if __name__ == '__main__': + testsequence() diff --git a/llrtc/lib/udivmod64.c b/llrtc/lib/udivmod64.c new file mode 100644 index 0000000..a028aea --- /dev/null +++ b/llrtc/lib/udivmod64.c @@ -0,0 +1,84 @@ +/* +Implements unsigned divmod using for platform missing 64-bit division and/or +modulo functions. +*/ +#include "udivmod64.h" + +/* +count left zero for 64-bit words + +*/ +static +int clz64(uint64_t x) +{ + const int total_bits = sizeof(x) * BITS_PER_BYTE; + int zc = 0; + + while (zc < total_bits && ((x >> (total_bits - zc - 1)) & 1) == 0) { + ++zc; + } + return zc; +} + +typedef struct div_state_ +{ + uint64_t tmp, dvd; +} div_state; + +/* +Left shift div_state by 1 bit +*/ +static +void div_state_lshift(div_state *state) +{ + state->tmp = (state->tmp << 1) | (state->dvd >> 63); + state->dvd = state->dvd << 1; +} + +/* +Division of unsigned 64-bit word using 64-bit addition and subtration following +the shift-restore division algorithm. +For those interested in 32-bit implementation, +mapping of 64-bit addition and subtraction to 32-bit should be trivial. + +Reference: + - IBM. The PowerPC Compiler Writer's Guide + - LLVM compiler-rt + +Assumptions: + - all operands and results are positive + - unsigned wrapped around +*/ +uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder) +{ + div_state state = {0, dividend}; + uint64_t quotient = 0; + int i; + int skipahead; + + if (divisor == 0) { + return 1 / 0; /* intentionally div by zero */ + } + + /* + skipahead to reduce iteration + */ + skipahead = clz64(dividend); + + for (i = 0; i < skipahead; ++i) { + div_state_lshift(&state); + } + + /* + division loop + */ + for (i = skipahead; i < 64; ++i) { + div_state_lshift(&state); + if (state.tmp >= divisor) { + state.tmp = state.tmp - divisor; + quotient |= 1ull << (63 - i); + } + } + *remainder = state.tmp; + return quotient; +} diff --git a/llrtc/lib/udivmod64.h b/llrtc/lib/udivmod64.h new file mode 100644 index 0000000..9cbcd8c --- /dev/null +++ b/llrtc/lib/udivmod64.h @@ -0,0 +1,11 @@ +#ifndef LLRT_UDIVMOD_H_ +#define LLRT_UDIVMOD_H_ + +#include + +#define BITS_PER_BYTE 8 + +uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); + +#endif /* LLRT_UDIVMOD_H_ */ + diff --git a/llrtc/tools/striptriple.py b/llrtc/tools/striptriple.py new file mode 100644 index 0000000..a20ba34 --- /dev/null +++ b/llrtc/tools/striptriple.py @@ -0,0 +1,15 @@ +import sys +import re + +buf = [] +with open(sys.argv[1], 'r') as fin: + tripleline = re.compile('^target\s+triple\s+=\s+') + for line in fin.readlines(): + if not tripleline.match(line): + buf.append(line) + +with open(sys.argv[1], 'w') as fout: + for line in buf: + fout.write(line) + + From 7d1c4c18a0539f61d1aba1e55fdea537a8300ec5 Mon Sep 17 00:00:00 2001 From: majidaldo Date: Wed, 14 Aug 2013 14:39:10 -0500 Subject: [PATCH 050/155] high version number --- buildscripts/condarecipe/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml index b079986..2b05015 100644 --- a/buildscripts/condarecipe/meta.yaml +++ b/buildscripts/condarecipe/meta.yaml @@ -1,6 +1,6 @@ package: name: llvmpy - version: master + version: 99.9.9 source: git_url: git@github.com:llvmpy/llvmpy.git From 8480d55faf0e671326b37576a05d0e1fbd7cb79b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 15:29:13 -0500 Subject: [PATCH 051/155] add sdivmod; improve build system; --- llrtc/Makefile | 29 ++++++------- llrtc/common.mk | 26 ------------ llrtc/lib/.gitignore | 4 ++ llrtc/lib/Makefile | 68 ++++++++++++++++++++----------- llrtc/lib/{udivmod64.h => llrt.h} | 7 ++-- llrtc/lib/sdivmod64.c | 40 ++++++++++++++++++ llrtc/lib/test_sdivmod64.c | 21 ++++++++++ llrtc/lib/test_sdivmod64.py | 56 +++++++++++++++++++++++++ llrtc/lib/test_udivmod64.c | 6 +-- llrtc/lib/test_udivmod64.py | 2 +- llrtc/lib/udivmod64.c | 4 +- 11 files changed, 190 insertions(+), 73 deletions(-) delete mode 100644 llrtc/common.mk create mode 100644 llrtc/lib/.gitignore rename llrtc/lib/{udivmod64.h => llrt.h} (50%) create mode 100644 llrtc/lib/sdivmod64.c create mode 100644 llrtc/lib/test_sdivmod64.c create mode 100644 llrtc/lib/test_sdivmod64.py diff --git a/llrtc/Makefile b/llrtc/Makefile index c271d0e..bde100e 100644 --- a/llrtc/Makefile +++ b/llrtc/Makefile @@ -1,21 +1,22 @@ -DIRECTORIES = divmod - all: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir; \ - done + make -C lib + +ir: + make -C lib ir test: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir test; \ - done + make -C lib test clean-test: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir clean-test; \ - done + make -C lib clean-test + +clean-temp: + make -C lib clean-temp clean: - for mydir in $(DIRECTORIES); do \ - make -C $$mydir clean; \ - done \ No newline at end of file + make -C lib clean + +install: ir + make -C lib clean-test + make -C lib clean-temp + \ No newline at end of file diff --git a/llrtc/common.mk b/llrtc/common.mk deleted file mode 100644 index 3de9c12..0000000 --- a/llrtc/common.mk +++ /dev/null @@ -1,26 +0,0 @@ -CLANG = clang -CF = -Wall -ansi -OUTDIR = .. - -all: ir - -$(OUTPUT).c: $(OUTPUT).h - -$(OUTPUT): test.c $(OUTPUT).c - $(CLANG) $(CF) -ftrapv -o $@ $+ - -test: $(OUTPUT) - python test.py - -ir: - CLANG -m32 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86/$(OUTPUT).ll - CLANG -m64 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86_64/$(OUTPUT).ll - python ../tools/striptriple.py $(OUTDIR)/x86/$(OUTPUT).ll - python ../tools/striptriple.py $(OUTDIR)/x86_64/$(OUTPUT).ll - -clean-test: - rm -f $(OUTPUT) - -clean: clean-test - rm -f $(OUTDIR)/x86/$(OUTPUT).ll - rm -f $(OUTDIR)/x86_64/$(OUTPUT).ll diff --git a/llrtc/lib/.gitignore b/llrtc/lib/.gitignore new file mode 100644 index 0000000..fbcf76a --- /dev/null +++ b/llrtc/lib/.gitignore @@ -0,0 +1,4 @@ +*.o +*.run +*.out +*.ll diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile index 1bb325f..8c9361d 100644 --- a/llrtc/lib/Makefile +++ b/llrtc/lib/Makefile @@ -1,44 +1,66 @@ OUTPUT = llrt -SOURCES = udivmod64.c +SOURCES = udivmod64.c sdivmod64.c +TESTS = test_udivmod64.c test_sdivmod64.c CLANG = clang +LLVM_LINK = llvm-link CF = -Wall -ansi CF_TEST = $(CF) -ftrapv CF_BUILD = $(CF) -O0 -emit-llvm OUTDIR = .. +STRIPPER = ../tools/striptriple.py all: ir -ir: $(SOURCES) - $(CLANG) -m32 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86.ll -c $(SOURCES) - python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86.ll - $(CLANG) -m64 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86_64.ll -c $(SOURCES) - python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86_64.ll +ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll -lib$(OUTPUT).a: $(SOURCES) - $(CLANG) $(CF) -o $@ -c $+ +$(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc) + $(LLVM_LINK) -S $+ -o $@ + python $(STRIPPER) $@ -build-test: lib$(OUTPUT).a - for src in $(SOURCES); do \ - $(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \ - done; +$(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc) + $(LLVM_LINK) -S $+ -o $@ + python $(STRIPPER) $@ -test: build-test - for src in $(SOURCES); do \ - echo "testing $${src%.*}"; \ - python test_$${src%.*}.py > test_$${src%.*}.out; \ +build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run) + +lib$(OUTPUT).a: $(SOURCES:.c=.o) + $(CLANG) -static $+ -o $@ + +test: $(TESTS:.c=.run) + for src in $+; do \ + echo "testing $${src}"; \ + python $${src%.*}.py > $${src%.*}.out; \ done; clean-test: rm -f *.out - rm -f *.a - for src in $(SOURCES); do \ - rm -f test_$${src%.*} ;\ - done; + rm -f *.o + rm -f *.run -clean-dist: - rm $(OUTDIR)/*.ll +clean-dist: clean-temp + rm -f *.ll + +clean-temp: + rm -f *.bc + rm -f *.o + rm -f *.out clean: clean-test clean-dist -udivmod64.c: udivmod64.h +%.c: llrt.h + +%_x86.bc: %.c + $(CLANG) -m32 $(CF_BUILD) -c $< -o $@ + +%_x86_64.bc: %.c + $(CLANG) -m64 $(CF_BUILD) -c $< -o $@ + +%.o: %.c + $(CLANG) $(CF_TEST) -c $< + +%.run: %.c + $(CLANG) $(CF_TEST) -o $@ $+ + +test_udivmod64.run: udivmod64.o +test_sdivmod64.run: udivmod64.o sdivmod64.o diff --git a/llrtc/lib/udivmod64.h b/llrtc/lib/llrt.h similarity index 50% rename from llrtc/lib/udivmod64.h rename to llrtc/lib/llrt.h index 9cbcd8c..0d26309 100644 --- a/llrtc/lib/udivmod64.h +++ b/llrtc/lib/llrt.h @@ -1,11 +1,12 @@ -#ifndef LLRT_UDIVMOD_H_ -#define LLRT_UDIVMOD_H_ +#ifndef LLRT_H_ +#define LLRT_H_ #include #define BITS_PER_BYTE 8 uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); +int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder); -#endif /* LLRT_UDIVMOD_H_ */ +#endif /* LLRT_H_ */ diff --git a/llrtc/lib/sdivmod64.c b/llrtc/lib/sdivmod64.c new file mode 100644 index 0000000..df294b3 --- /dev/null +++ b/llrtc/lib/sdivmod64.c @@ -0,0 +1,40 @@ +#include "llrt.h" +#include + +/* +Calls to udivmod64 internally. +Note: remainder uses sign of divisor. +*/ +int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder) +{ + int signbitidx = BITS_PER_BYTE * sizeof(dividend) - 1; + int signed_dividend = dividend < 0; + int signed_divisor = divisor < 0; + int signed_result = signed_divisor ^ signed_dividend; + + int64_t quotient; + uint64_t udvd, udvr, uquotient, uremainder; + + udvd = signed_dividend ? -dividend : dividend; + udvr = signed_divisor ? -divisor : divisor; + uquotient = udivmod64(udvd, udvr, &uremainder); + + if (signed_result){ + if (uremainder) { + quotient = -(int64_t)uquotient - 1; + } else { + quotient = -(int64_t)uquotient; + } + if (remainder) { + /* if signed, there could be unsigned overflow + causing undefined behavior */ + *remainder = (uint64_t)dividend - (uint64_t)quotient * (uint64_t)divisor; + } + } else { + quotient = (int64_t)uquotient; + if (remainder) { + *remainder = signed_divisor ? -uremainder : uremainder; + } + } + return quotient; +} diff --git a/llrtc/lib/test_sdivmod64.c b/llrtc/lib/test_sdivmod64.c new file mode 100644 index 0000000..1e804d6 --- /dev/null +++ b/llrtc/lib/test_sdivmod64.c @@ -0,0 +1,21 @@ +#include +#include +#include "llrt.h" + +int main(int argc, char * argv[]){ + int64_t n, d, q, r; + + if (argc != 3) { + printf("invalid argument: %s dividend divisor", argv[0]); + return 1; + } + sscanf(argv[1], "%lld", &n); + sscanf(argv[2], "%lld", &d); + + q = sdivmod64(n, d, &r); + + printf("%lld\n", q); + printf("%lld\n", r); + + return 0; +} diff --git a/llrtc/lib/test_sdivmod64.py b/llrtc/lib/test_sdivmod64.py new file mode 100644 index 0000000..4aa49a9 --- /dev/null +++ b/llrtc/lib/test_sdivmod64.py @@ -0,0 +1,56 @@ +import math +import os +import subprocess +udt = os.path.join('.', 'test_sdivmod64.run') + +def testcase(dividend, divisor): + print 'divmod64(%d, %d)' % (dividend, divisor) + + procargs = ('%s %s %s' % (udt, dividend, divisor)).split() + result = subprocess.check_output(procargs) + gotQ, gotR = map(int, result.splitlines()) + + expectQ = dividend // divisor + expectR = dividend % divisor + + print 'Q = %d, R = %d' % (gotQ, gotR) + + if expectQ != gotQ: + raise ValueError("invalid quotient: got=%d but expect=%d" % + (gotQ, expectQ)) + if expectR != gotR: + raise ValueError("invalid remainder: got=%d but expect=%d" % + (gotR, expectR)) + print 'OK' + +def testsequence(): + subjects = [ + (0, 1), + (0, 0xffffffff), + (1, 2), + (1, 983219), + (2, 2), + (3, 2), + (1024, 2), + (2048, 512), + (21321, 512), + (9329189, 1031), + (0xffffffff, 2), + (0xffffffff, 0xffff), + (0x1ffffffff, 2), + (0x1ffffffff, 0xffff), + (0xffff, 0xffffffff), + (0x0fffffffffffffff, 0xffff), + (0x7fffffffffffffff, 0x7fffffffffffffff), + (0x7fffffffffffffff, 0x7ffffffffffffff0), + (0x7fffffffffffffff, 87655678587161901), + ] + + for dvd, dvr in subjects: + testcase(dvd, dvr) + testcase(dvd, -dvr) + testcase(-dvd, dvr) + testcase(-dvd, -dvr) + +if __name__ == '__main__': + testsequence() diff --git a/llrtc/lib/test_udivmod64.c b/llrtc/lib/test_udivmod64.c index e2935c5..70b44aa 100644 --- a/llrtc/lib/test_udivmod64.c +++ b/llrtc/lib/test_udivmod64.c @@ -1,8 +1,6 @@ #include #include - -extern uint64_t -udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); +#include "llrt.h" int main(int argc, char * argv[]){ uint64_t n, d, q, r; @@ -19,4 +17,4 @@ int main(int argc, char * argv[]){ printf("%llu\n", r); return 0; -} \ No newline at end of file +} diff --git a/llrtc/lib/test_udivmod64.py b/llrtc/lib/test_udivmod64.py index 487a458..da07ccb 100644 --- a/llrtc/lib/test_udivmod64.py +++ b/llrtc/lib/test_udivmod64.py @@ -1,7 +1,7 @@ import math import os import subprocess -udt = os.path.join('.', 'test_udivmod64') +udt = os.path.join('.', 'test_udivmod64.run') def testcase(dividend, divisor): print 'divmod64(%d, %d)' % (dividend, divisor) diff --git a/llrtc/lib/udivmod64.c b/llrtc/lib/udivmod64.c index a028aea..5936f98 100644 --- a/llrtc/lib/udivmod64.c +++ b/llrtc/lib/udivmod64.c @@ -2,7 +2,7 @@ Implements unsigned divmod using for platform missing 64-bit division and/or modulo functions. */ -#include "udivmod64.h" +#include "llrt.h" /* count left zero for 64-bit words @@ -79,6 +79,6 @@ uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder) quotient |= 1ull << (63 - i); } } - *remainder = state.tmp; + if (remainder) *remainder = state.tmp; return quotient; } From e69048ad3dd6bdf541796e4f64e699962fe5006b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 17:24:34 -0500 Subject: [PATCH 052/155] add div64 and mod64 --- llrtc/Makefile | 2 +- llrtc/lib/Makefile | 2 +- llrtc/lib/div64.c | 11 +++++++++++ llrtc/lib/llrt.h | 7 +++++++ llrtc/lib/mod64.c | 15 +++++++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 llrtc/lib/div64.c create mode 100644 llrtc/lib/mod64.c diff --git a/llrtc/Makefile b/llrtc/Makefile index bde100e..b15eac5 100644 --- a/llrtc/Makefile +++ b/llrtc/Makefile @@ -17,6 +17,6 @@ clean: make -C lib clean install: ir - make -C lib clean-test + cp llrt_*.ll ../llvm/llrt make -C lib clean-temp \ No newline at end of file diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile index 8c9361d..9dbfb27 100644 --- a/llrtc/lib/Makefile +++ b/llrtc/lib/Makefile @@ -1,5 +1,5 @@ OUTPUT = llrt -SOURCES = udivmod64.c sdivmod64.c +SOURCES = udivmod64.c sdivmod64.c div64.c mod64.c TESTS = test_udivmod64.c test_sdivmod64.c CLANG = clang diff --git a/llrtc/lib/div64.c b/llrtc/lib/div64.c new file mode 100644 index 0000000..8466965 --- /dev/null +++ b/llrtc/lib/div64.c @@ -0,0 +1,11 @@ +#include "llrt.h" + +uint64_t udiv64(uint64_t dividend, uint64_t divisor) +{ + return udivmod64(dividend, divisor, NULL); +} + +int64_t sdiv64(int64_t dividend, int64_t divisor) +{ + return sdivmod64(dividend, divisor, NULL); +} diff --git a/llrtc/lib/llrt.h b/llrtc/lib/llrt.h index 0d26309..4e9e348 100644 --- a/llrtc/lib/llrt.h +++ b/llrtc/lib/llrt.h @@ -3,10 +3,17 @@ #include +#define NULL 0 #define BITS_PER_BYTE 8 uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder); +uint64_t udiv64(uint64_t dividend, uint64_t divisor); +int64_t sdiv64(int64_t dividend, int64_t divisor); + +uint64_t umod64(uint64_t dividend, uint64_t divisor); +int64_t smod64(int64_t dividend, int64_t divisor); + #endif /* LLRT_H_ */ diff --git a/llrtc/lib/mod64.c b/llrtc/lib/mod64.c new file mode 100644 index 0000000..875f6b9 --- /dev/null +++ b/llrtc/lib/mod64.c @@ -0,0 +1,15 @@ +#include "llrt.h" + +uint64_t umod64(uint64_t dividend, uint64_t divisor) +{ + uint64_t rem; + udivmod64(dividend, divisor, &rem); + return rem; +} + +int64_t smod64(int64_t dividend, int64_t divisor) +{ + int64_t rem; + sdivmod64(dividend, divisor, &rem); + return rem; +} From bf8693bb806be4192810b740c08300876d76cb34 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 17:45:38 -0500 Subject: [PATCH 053/155] disable float div/mod test temporarily --- llvm/core.py | 3 + llvm/llrt.py | 77 ++++++++ llvm/llrt/llrt_x86.ll | 371 +++++++++++++++++++++++++++++++++++++++ llvm/llrt/llrt_x86_64.ll | 371 +++++++++++++++++++++++++++++++++++++++ llvm/test_llvmpy.py | 42 ++++- 5 files changed, 858 insertions(+), 6 deletions(-) create mode 100644 llvm/llrt.py create mode 100644 llvm/llrt/llrt_x86.ll create mode 100644 llvm/llrt/llrt_x86_64.ll diff --git a/llvm/core.py b/llvm/core.py index 945dd86..c4fe560 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1848,6 +1848,9 @@ class Instruction(User): def erase_from_parent(self): return self._ptr.eraseFromParent() + def replace_all_uses_with(self, inst): + self._ptr.replaceAllUsesWith(inst) + class CallOrInvokeInstruction(Instruction): _type_ = api.llvm.CallInst, api.llvm.InvokeInst diff --git a/llvm/llrt.py b/llvm/llrt.py new file mode 100644 index 0000000..b80914e --- /dev/null +++ b/llvm/llrt.py @@ -0,0 +1,77 @@ +import os +import llvm.core as lc +import llvm.passes as lp +import llvm.ee as le + +def replace_divmod64(lfunc): + '''Replaces all 64-bit integer division (sdiv, udiv) and modulo (srem, urem) + ''' + int64 = lc.Type.int(64) + int64ptr = lc.Type.pointer(lc.Type.int(64)) + + functy = lc.Type.function(int64, [int64, int64]) + udiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_udiv64') + sdiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_sdiv64') + umod64 = lfunc.module.get_or_insert_function(functy, '__llrt_umod64') + smod64 = lfunc.module.get_or_insert_function(functy, '__llrt_smod64') + + builder = lc.Builder.new(lfunc.entry_basic_block) + for bb in lfunc.basic_blocks: + for inst in bb.instructions: + if inst.opcode_name == 'sdiv' and inst.type == int64: + _replace_with(builder, inst, sdiv64) + elif inst.opcode_name == 'udiv' and inst.type == int64: + _replace_with(builder, inst, udiv64) + elif inst.opcode_name == 'srem' and inst.type == int64: + _replace_with(builder, inst, smod64) + elif inst.opcode_name == 'urem' and inst.type == int64: + _replace_with(builder, inst, umod64) + +def _replace_with(builder, inst, func): + '''Replace instruction with a call to the function with the same operands + as arguments. + ''' + builder.position_before(inst) + replacement = builder.call(func, inst.operands) + inst.replace_all_uses_with(replacement._ptr) + inst.erase_from_parent() + +def load(arch): + '''Load the LLRT module corresponding to the given architecture + Creates a new module and optimizes it using the information from + the host machine. + ''' + path = os.path.join(os.path.dirname(__file__), 'llrt', 'llrt_%s.ll' % arch) + with open(path) as fin: + lib = lc.Module.from_assembly(fin) + + # run passes to optimize + tm = le.TargetMachine.new() + pms = lp.build_pass_managers(tm, opt=3, fpm=False) + pms.pm.run(lib) + return lib + +class LLRT(object): + def __init__(self): + arch = le.get_default_triple().split('-', 1)[0] + self.module = load(arch) + self.engine = le.EngineBuilder.new(self.module).opt(3).create() + self.installed_symbols = set() + + def install_symbols(self): + '''Bind all the external symbols to the global symbol map. + Any future reference to these symbols will be automatically resolved + by LLVM. + ''' + for lfunc in self.module.functions: + if lfunc.linkage == lc.LINKAGE_EXTERNAL: + mangled = '__llrt_' + lfunc.name + self.installed_symbols.add(mangled) + ptr = self.engine.get_pointer_to_function(lfunc) + le.dylib_add_symbol(mangled, ptr) + + def uninstall_symbols(self): + for sym in self.installed_symbols: + le.dylib_add_symbol(sym, 0) + + diff --git a/llvm/llrt/llrt_x86.ll b/llvm/llrt/llrt_x86.ll new file mode 100644 index 0000000..5096214 --- /dev/null +++ b/llvm/llrt/llrt_x86.ll @@ -0,0 +1,371 @@ +; ModuleID = 'udivmod64_x86.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128" + +%struct.div_state_ = type { i64, i64 } + +define i64 @udivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind ssp { + %1 = alloca i64, align 4 + %2 = alloca i64, align 8 + %3 = alloca i64, align 8 + %4 = alloca i64*, align 4 + %state = alloca %struct.div_state_, align 4 + %quotient = alloca i64, align 8 + %i = alloca i32, align 4 + %skipahead = alloca i32, align 4 + store i64 %dividend, i64* %2, align 8 + store i64 %divisor, i64* %3, align 8 + store i64* %remainder, i64** %4, align 4 + %5 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0 + store i64 0, i64* %5, align 4 + %6 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 1 + %7 = load i64* %2, align 8 + store i64 %7, i64* %6, align 4 + store i64 0, i64* %quotient, align 8 + %8 = load i64* %3, align 8 + %9 = icmp eq i64 %8, 0 + br i1 %9, label %10, label %11 + +;