From 203858f417e84e51c37f1aa368c5b71db5b65ca7 Mon Sep 17 00:00:00 2001 From: Christoph Gohlke Date: Fri, 18 Jan 2013 13:40:48 -0800 Subject: [PATCH 001/338] Fix ImportError on Python 3 --- llvm/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/__init__.py b/llvm/__init__.py index b89e5a9..79399ff 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -6,7 +6,7 @@ __version__ = '0.10.0' from weakref import WeakValueDictionary -import _core +from . import _core #===----------------------------------------------------------------------=== # LLVM Version From 5209cdb03233ee1073eb0fabd5fd7748feb65502 Mon Sep 17 00:00:00 2001 From: Christoph Gohlke Date: Fri, 18 Jan 2013 13:49:15 -0800 Subject: [PATCH 002/338] Detect and use NVPTX libraries on Windows --- llvm-config-win32.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index d8fa5c1..2b6e8f5 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -58,6 +58,11 @@ Shell32 print('-lLLVMPTXCodeGen') print('-lLLVMPTXDesc') print('-lLLVMPTXInfo') + elif os.path.exists(os.path.join(llvmbin, '../lib/LLVMNVPTXCodeGen.lib')): + print('-lLLVMNVPTXAsmPrinter') + print('-lLLVMNVPTXCodeGen') + print('-lLLVMNVPTXDesc') + print('-lLLVMNVPTXInfo') elif sys.argv[1] == '--includedir': llvmbin = find_path_of('llvm-tblgen.exe') if llvmbin is None: From 2bef762ba2a90f2f52881e47cb5a06aaa0a09116 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Wed, 23 Jan 2013 19:49:38 -0600 Subject: [PATCH 003/338] Add testcase with debuginfo and trap for gdb --- test/test_debuginfo.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index 68ab29c..8ecaa3a 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -1,6 +1,7 @@ import os import unittest +import llvm.ee from llvm.core import * from llvm import _dwarf, debuginfo @@ -76,11 +77,17 @@ class TestDebugInfo(unittest.TestCase): # Build some instructions value = square.args[0] - result = bldr.fmul(value, value) + # result = bldr.fmul(value, value) + + # Generate an instruction that will result in a signal + result = bldr.fdiv(value, llvm.core.Constant.real(value.type, 0)) + ltrap = llvm.core.Function.intrinsic(mod, INTR_TRAP, []) + lcall = bldr.call(ltrap, []) ret = bldr.ret(result) # Annotate instructions with source position result.set_metadata("dbg", posinfo1.get_metadata(mod)) + lcall.set_metadata("dbg", posinfo1.get_metadata(mod)) ret.set_metadata("dbg", posinfo2.get_metadata(mod)) # ... Aaaand, test... @@ -98,7 +105,28 @@ class TestDebugInfo(unittest.TestCase): self.assertIn("some_function", modstr) self.assertIn("float (float)* @square", modstr) + return square + + +def debug_in_gdb(lfunc): + # Create an execution engine object. This will create a JIT compiler + # on platforms that support it, or an interpreter otherwise. + module = lfunc.module + ee = llvm.ee.ExecutionEngine.new(module) + float_type = lfunc.args[0].type + + # The arguments needs to be passed as "GenericValue" objects. + arg1_value = 5.0 + arg1 = llvm.ee.GenericValue.real(float_type, arg1_value) + + # Now let's compile and run! + retval = ee.run_function(lfunc, [arg1]) + print retval.as_real(float_type) + + if __name__ == '__main__': # TestDebugInfo("test_dwarf_constants").debug() # TestDebugInfo("test_debug_info_compile_unit").debug() +# tester = TestDebugInfo("test_debug_info_compile_unit") +# debug_in_gdb(tester.test_debug_info_compile_unit()) unittest.main() \ No newline at end of file From 3b1ae9889dc8744ca7ab28d05bb09e34efba23c6 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 24 Jan 2013 11:44:25 -0600 Subject: [PATCH 004/338] Ensure python2.6 support --- llvm/test_llvmpy.py | 76 ++++++++++++++++++++++++++++++------------ test/inlineasm.py | 3 +- test/loopvectorize.py | 3 +- test/metadata.py | 4 +-- test/tbaa.py | 3 +- test/test.py | 10 +++--- test/test_debuginfo.py | 3 +- 7 files changed, 70 insertions(+), 32 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 84a2a0a..a5fe957 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -8,6 +8,7 @@ import shutil import unittest import subprocess import tempfile +import contextlib is_py3k = bool(sys.version_info[0] == 3) BITS = tuple.__itemsize__ * 8 @@ -29,9 +30,40 @@ import llvm.ee as le tests = [] + # --------------------------------------------------------------------------- -class TestAsm(unittest.TestCase): +if sys.version_info[:2] <= (2, 6): + # create custom TestCase + class TestCase(unittest.TestCase): + def assertIn(self, item, container): + self.assertTrue(item in container) + + def assertNotIn(self, item, container): + self.assertFalse(item in container) + + def assertLess(self, a, b): + self.assertTrue(a < b) + + def assertIs(self, a, b): + self.assertTrue(a is b) + + @contextlib.contextmanager + def assertRaises(self, exc): + try: + yield + except exc: + pass + else: + raise self.failureException("Did not raise %s" % exc) + +else: + TestCase = unittest.TestCase + + +# --------------------------------------------------------------------------- + +class TestAsm(TestCase): def setUp(self): self.tmpdir = tempfile.mkdtemp() @@ -82,7 +114,7 @@ tests.append(TestAsm) # --------------------------------------------------------------------------- -class TestAttr(unittest.TestCase): +class TestAttr(TestCase): def make_module(self): test_module = """ define i32 @sum(i32, i32) { @@ -104,7 +136,7 @@ tests.append(TestAttr) # --------------------------------------------------------------------------- -class TestAtomic(unittest.TestCase): +class TestAtomic(TestCase): orderings = ['unordered', 'monotonic', 'acquire', 'release', 'acq_rel', 'seq_cst'] @@ -187,7 +219,7 @@ tests.append(TestAtomic) # --------------------------------------------------------------------------- -class TestConstExpr(unittest.TestCase): +class TestConstExpr(TestCase): def test_constexpr_opcode(self): mod = Module.new('test_constexpr_opcode') @@ -203,7 +235,7 @@ tests.append(TestConstExpr) # --------------------------------------------------------------------------- -class TestOperands(unittest.TestCase): +class TestOperands(TestCase): # implement a test function test_module = """ define i32 @prod(i32, i32) { @@ -259,7 +291,7 @@ tests.append(TestOperands) # --------------------------------------------------------------------------- -class TestPasses(unittest.TestCase): +class TestPasses(TestCase): # Create a module. asm = """ @@ -385,7 +417,7 @@ tests.append(TestPasses) # --------------------------------------------------------------------------- -class TestEngineBuilder(unittest.TestCase): +class TestEngineBuilder(TestCase): def make_test_module(self): module = Module.new("testmodule") @@ -452,7 +484,7 @@ tests.append(TestEngineBuilder) # --------------------------------------------------------------------------- -class TestExecutionEngine(unittest.TestCase): +class TestExecutionEngine(TestCase): def test_get_pointer_to_global(self): module = lc.Module.new(str(self)) gvar = module.add_global_variable(Type.int(), 'hello') @@ -492,7 +524,7 @@ class TestExecutionEngine(unittest.TestCase): tests.append(TestExecutionEngine) # --------------------------------------------------------------------------- -class TestObjCache(unittest.TestCase): +class TestObjCache(TestCase): def test_objcache(self): # Testing module aliasing @@ -593,7 +625,7 @@ tests.append(TestObjCache) # --------------------------------------------------------------------------- -class TestTargetMachines(unittest.TestCase): +class TestTargetMachines(TestCase): '''Exercise target machines Require PTX backend @@ -646,7 +678,7 @@ tests.append(TestTargetMachines) # --------------------------------------------------------------------------- -class TestNative(unittest.TestCase): +class TestNative(TestCase): def setUp(self): self.tmpdir = tempfile.mkdtemp() @@ -708,7 +740,7 @@ if sys.platform != 'win32': # --------------------------------------------------------------------------- -class TestNativeAsm(unittest.TestCase): +class TestNativeAsm(TestCase): def test_asm(self): m = Module.new('module1') @@ -731,7 +763,7 @@ tests.append(TestNativeAsm) # --------------------------------------------------------------------------- -class TestUses(unittest.TestCase): +class TestUses(TestCase): def test_uses(self): m = Module.new('a') @@ -768,7 +800,7 @@ tests.append(TestUses) # --------------------------------------------------------------------------- -class TestMetaData(unittest.TestCase): +class TestMetaData(TestCase): # test module metadata def test_metadata(self): m = Module.new('a') @@ -788,7 +820,7 @@ tests.append(TestMetaData) # --------------------------------------------------------------------------- -class TestInlining(unittest.TestCase): +class TestInlining(TestCase): def test_inline_call(self): mod = Module.new(__name__) callee = mod.add_function(Type.function(Type.int(), [Type.int()]), @@ -817,7 +849,7 @@ tests.append(TestInlining) # --------------------------------------------------------------------------- -class TestIssue10(unittest.TestCase): +class TestIssue10(TestCase): def test_issue10(self): m = Module.new('a') ti = Type.int() @@ -838,7 +870,7 @@ tests.append(TestIssue10) # --------------------------------------------------------------------------- -class TestOpaque(unittest.TestCase): +class TestOpaque(TestCase): def test_opaque(self): # Create an opaque type @@ -869,7 +901,7 @@ class TestOpaque(unittest.TestCase): tests.append(TestOpaque) # --------------------------------------------------------------------------- -class TestCPUSupport(unittest.TestCase): +class TestCPUSupport(TestCase): def _build_test_module(self): mod = Module.new('test') @@ -945,7 +977,7 @@ class TestCPUSupport(unittest.TestCase): tests.append(TestCPUSupport) # --------------------------------------------------------------------------- -class TestIntrinsicBasic(unittest.TestCase): +class TestIntrinsicBasic(TestCase): def _build_module(self, float): mod = Module.new('test') @@ -1032,7 +1064,7 @@ tests.append(TestIntrinsicBasic) # --------------------------------------------------------------------------- -class TestIntrinsic(unittest.TestCase): +class TestIntrinsic(TestCase): def test_bswap(self): # setup a function and a builder mod = Module.new('test') @@ -1130,7 +1162,7 @@ tests.append(TestIntrinsic) # --------------------------------------------------------------------------- -class TestVolatile(unittest.TestCase): +class TestVolatile(TestCase): def test_volatile(self): mod = Module.new('mod') @@ -1184,7 +1216,7 @@ tests.append(TestVolatile) # --------------------------------------------------------------------------- -class TestNamedMetaData(unittest.TestCase): +class TestNamedMetaData(TestCase): def test_named_md(self): m = Module.new('test_named_md') nmd = m.get_or_insert_named_metadata('something') diff --git a/test/inlineasm.py b/test/inlineasm.py index 635e6bf..df91d71 100644 --- a/test/inlineasm.py +++ b/test/inlineasm.py @@ -3,12 +3,13 @@ # Import the llvm-py modules. from llvm import * from llvm.core import * +from llvm.test_llvmpy import TestCase import logging import unittest -class TestInlineAsm(unittest.TestCase): +class TestInlineAsm(TestCase): def test_inline_asm(self): mod = Module.new(__name__) fnty = Type.function(Type.int(), [Type.int()]) diff --git a/test/loopvectorize.py b/test/loopvectorize.py index ff7cb10..9cf1654 100644 --- a/test/loopvectorize.py +++ b/test/loopvectorize.py @@ -2,13 +2,14 @@ from llvm.core import * from llvm.passes import * from llvm.ee import * import llvm +from llvm.test_llvmpy import TestCase from os.path import dirname, join as join_path import unittest import re -class TestLoopVectorizer(unittest.TestCase): +class TestLoopVectorizer(TestCase): def test_loop_vectorizer(self): if llvm.version <= (3, 1): return # SKIP diff --git a/test/metadata.py b/test/metadata.py index 90b6ae8..3228159 100644 --- a/test/metadata.py +++ b/test/metadata.py @@ -1,10 +1,10 @@ from __future__ import print_function import unittest - +from llvm.test_llvmpy import TestCase from llvm.core import * -class TestMetaData(unittest.TestCase): +class TestMetaData(TestCase): def test_metadata_get(self): module = Module.new('test_metadata') md = MetaData.get(module, [Constant.int(Type.int(), 1234)]) diff --git a/test/tbaa.py b/test/tbaa.py index d775a53..242ed19 100644 --- a/test/tbaa.py +++ b/test/tbaa.py @@ -1,8 +1,9 @@ from llvm.core import * from llvm.tbaa import * +from llvm.test_llvmpy import TestCase import unittest -class TestTBAABuilder(unittest.TestCase): +class TestTBAABuilder(TestCase): def test_tbaa_builder(self): mod = Module.new('test_tbaa_builder') fty = Type.function(Type.void(), [Type.pointer(Type.float())]) diff --git a/test/test.py b/test/test.py index bbc43f4..3b46281 100644 --- a/test/test.py +++ b/test/test.py @@ -7,9 +7,9 @@ import unittest, sys, logging from llvm import * from llvm.core import * +from llvm.test_llvmpy import TestCase - -class TestModule(unittest.TestCase): +class TestModule(TestCase): def setUp(self): pass @@ -100,8 +100,10 @@ def main(): gc.set_debug(gc.DEBUG_LEAK) # run tests - unittest.main(exit=False) # set exit to False so that it will return. - + if sys.version_info[:2] > (2, 6): + unittest.main(exit=False) # set exit to False so that it will return. + else: + unittest.main() # done for it in gc.garbage: logging.debug('garbage = %s', it) diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index 8ecaa3a..0340c1b 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -4,8 +4,9 @@ import unittest import llvm.ee from llvm.core import * from llvm import _dwarf, debuginfo +from llvm.test_llvmpy import TestCase -class TestDebugInfo(unittest.TestCase): +class TestDebugInfo(TestCase): def test_dwarf_constants(self): dwarf_constants = vars(_dwarf) From 60795adb5ecb6d57265e94b179669df21de48eb8 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Thu, 24 Jan 2013 20:10:34 -0600 Subject: [PATCH 005/338] Implement JUMP_IF_FALSE bytecode instruction in llpython --- llpython/byte_translator.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/llpython/byte_translator.py b/llpython/byte_translator.py index 08b4560..93ccb6f 100644 --- a/llpython/byte_translator.py +++ b/llpython/byte_translator.py @@ -449,7 +449,11 @@ class LLVMTranslator (BytecodeFlowVisitor): return [self.builder.branch(self.llvm_blocks[i + arg + 3])] def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws): - raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE") + cond = args[0] + block_false = self.llvm_blocks[op] + block_true = self.llvm_blocks[i + 3] + return [self.builder.cbranch(cond, block_true, block_false)] + # raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE") def op_JUMP_IF_FALSE_OR_POP (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP") From c0ff3615eeadf966e26b8b9bce3e76f5e5947404 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 25 Jan 2013 13:48:52 -0600 Subject: [PATCH 006/338] update changelog --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 815ecf7..5c8960c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +0.10.1, 25-Jan-2013: + * fix support for Python 2.6 + 0.10, 18-Jan-2013: * Add LLVM 3.2 support. From d355facf25bfd4316c5fa58b88beddf5fae1d099 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 25 Jan 2013 13:55:19 -0600 Subject: [PATCH 007/338] DOC: formatting --- CHANGELOG | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5c8960c..f93e98e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,10 @@ -0.10.1, 25-Jan-2013: +2013-01-25 0.10.1: +-------------------- * fix support for Python 2.6 -0.10, 18-Jan-2013: +2013-01-18 0.10.0: +-------------------- * Add LLVM 3.2 support. * New TargetData class. * Fixed windows issue (Issue #42). @@ -11,16 +13,16 @@ * Added llvm.passes.build_pass_managers as a simpler way to build PassManagers. -0.7, in progress: - +in progress, 0.7: +----------------- * Add llvm.core.Argument.alignment property. * Migrate to LLVM 2.8. * Fix ffi link issue on darwin (Albert Mietus) (Issue #29). * LLVM tutorial ported (Max Shawabkeh) (Issue #33). -0.6, 31-Aug-2010: - +2010-08-31 0.6: +----------------- * Add and remove function attributes (Krzysztof Goj) (Issue #21). * Wrap fadd,fsub,fmul (Aaron S Lav) (Issue #31). * Migrate to LLVM 2.7. @@ -39,16 +41,16 @@ * Migrate to LLVM 2.5. -0.5, 22-Nov-2008: - +2008-11-22 0.5: +----------------- * Added vicmp, vfcmp instructions and constant expressions. * Builds on FreeBSD. * Updated documentation. * Migrate to LLVM 2.4. -0.4, 21-Nov-2008: - +2008-11-21 0.4: +----------------- * Code cleanup, added license headers. * Added llvm.core.load_library_permanently() (Issue #12). * Fix comparison using != (Issue #11). @@ -57,8 +59,8 @@ * Added viewCFG methods to Function (Paulo Silva). -0.3, 8-Sep-2008: - +2008-09-08 0.3: +----------------- * Passes added. * Assembly support: create modules from .ll files. * Various bug fixes. @@ -70,13 +72,13 @@ * Updated documentation. -0.2.1, 18-Jun-2008: - +2008-06-28 0.2.1: +------------------- * Build cleanly with LLVM 2.3 and 2.3svn. -0.2, 15-Jun-2008: - +2008-06-15 0.2: +----------------- * Independent package, need not be unpacked into llvm/bindings. * Fixed ownership issues with Module/ModuleProvider. * Modules, values and types can be stringified, to get their LLVM @@ -91,7 +93,6 @@ * Lots of cleanup. -0.1, 10-May-2008: - - * Initial release. - +2008-05-10 0.1: +----------------- + * Initial release From 4ab6791e786d1951a8e4537ae162efb861e46a6d Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 25 Jan 2013 13:57:43 -0600 Subject: [PATCH 008/338] fix version string --- llvm/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/__init__.py b/llvm/__init__.py index 79399ff..defc483 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -2,7 +2,7 @@ Common classes related to LLVM. """ -__version__ = '0.10.0' +__version__ = '0.10.1' from weakref import WeakValueDictionary From 3772b8ba6e3794b64cfbd5a9580a51618f489e81 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 25 Jan 2013 14:05:40 -0600 Subject: [PATCH 009/338] REL: master now 0.10.2 --- CHANGELOG | 5 +++++ llvm/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f93e98e..0efe307 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +2013-??-?? 0.10.2: +-------------------- + + + 2013-01-25 0.10.1: -------------------- * fix support for Python 2.6 diff --git a/llvm/__init__.py b/llvm/__init__.py index defc483..1935514 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -2,7 +2,7 @@ Common classes related to LLVM. """ -__version__ = '0.10.1' +__version__ = '0.10.2' from weakref import WeakValueDictionary From 8b918f37d6d2a34e0a8d7b980946a72b76eed74d Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 25 Jan 2013 17:01:54 -0600 Subject: [PATCH 010/338] change default --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 25b69ee..ce51a7c 100644 --- a/setup.py +++ b/setup.py @@ -11,8 +11,8 @@ else: default_llvm_config = 'llvm-config' llvm_config = os.environ.get('LLVM_CONFIG_PATH', default_llvm_config) -# set LLVMPY_DYNLINK=1, if you want to link _core.so dynamically to libLLVM.so -dynlink = int(os.environ.get('LLVMPY_DYNLINK', 0)) +# set LLVMPY_DYNLINK=0, if you want to link _core.so statically +dynlink = int(os.environ.get('LLVMPY_DYNLINK', 1)) def run_llvm_config(args): cmd = llvm_config + ' ' + ' '.join(args) From 3d66981cc1dc8a1700ffcc7f33e91b3c8072aebe Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 25 Jan 2013 17:06:42 -0600 Subject: [PATCH 011/338] update changelog --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 0efe307..cc465d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ 2013-??-?? 0.10.2: -------------------- - + * change default to link dynamically to LLVM (use LLVMPY_DYNLINK=0 to link + statically) 2013-01-25 0.10.1: From 7e7b362e478088142a33bc8a9217fa47219ebd18 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sat, 26 Jan 2013 11:20:53 -0600 Subject: [PATCH 012/338] Get llvm version as a string. It may contain 'svn' postfix. --- setup.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index ce51a7c..0807ead 100644 --- a/setup.py +++ b/setup.py @@ -38,12 +38,7 @@ def get_enabled_components(): return run_llvm_config(['--components']).split() def get_llvm_version(): - # get version number; treat it as fixed point - pat = re.compile(r'(\d+)\.(\d+)') - m = pat.search(run_llvm_config([' --version'])) - if m is None: - sys.exit('could not determine llvm version') - return tuple(map(int, m.groups())) + return run_llvm_config([' --version']) def auto_intrinsic_gen(incdir): @@ -60,14 +55,14 @@ libdir = run_llvm_config(['--libdir']) ldflags = run_llvm_config(['--ldflags']) llvm_version = get_llvm_version() -print('LLVM version = %d.%d' % llvm_version) +print('LLVM version = %s' % llvm_version) auto_intrinsic_gen(incdir) macros = [('__STDC_CONSTANT_MACROS', None), ('__STDC_LIMIT_MACROS', None)] if dynlink: - libs_core = ['LLVM-%d.%d' % llvm_version] + libs_core = ['LLVM-%s' % llvm_version] objs_core = [] else: enabled_components = set(get_enabled_components()) From ffc067f8526773f7478d74f85c1b6c979f6f2e7f Mon Sep 17 00:00:00 2001 From: Jon Riehl Date: Mon, 28 Jan 2013 20:08:09 -0600 Subject: [PATCH 013/338] Attempt at a fix for issue #48. --- llpython/byte_control.py | 52 +++++++++++++++++---------- llpython/byte_flow.py | 69 ++++++++++++++++++++++++++---------- llpython/byte_translator.py | 7 ++-- llpython/bytecode_visitor.py | 26 ++++++++++++++ llpython/opcode_util.py | 19 +++++++--- llpython/phi_injector.py | 3 +- 6 files changed, 132 insertions(+), 44 deletions(-) diff --git a/llpython/byte_control.py b/llpython/byte_control.py index 34ebae4..9df6d5c 100644 --- a/llpython/byte_control.py +++ b/llpython/byte_control.py @@ -5,13 +5,13 @@ import opcode import opcode_util import pprint -from bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin +from bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin from control_flow import ControlFlowGraph # ______________________________________________________________________ -class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): - '''Visitor responsible for traversing a bytecode flow object and +class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor): + '''Visitor responsible for traversing a bytecode basic block map and building a control flow graph (CFG). The primary purpose of this transformation is to create a CFG, @@ -27,21 +27,26 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): del self.nargs return ret_val - def enter_flow_object (self, flow): - super(ControlFlowBuilder, self).enter_flow_object(flow) - self.flow = flow + def enter_blocks (self, blocks): + super(ControlFlowBuilder, self).enter_blocks(blocks) + self.blocks = blocks + self.block_list = list(blocks.keys()) + self.block_list.sort() self.cfg = ControlFlowGraph() - for block in flow.keys(): - self.cfg.add_block(block, flow[block]) + self.loop_stack = [] + for block in self.block_list: + self.cfg.add_block(block, blocks[block]) - def exit_flow_object (self, flow): - super(ControlFlowBuilder, self).exit_flow_object(flow) - assert self.flow == flow + def exit_blocks (self, blocks): + super(ControlFlowBuilder, self).exit_blocks(blocks) + assert self.blocks == blocks self.cfg.compute_dataflow() self.cfg.update_for_ssa() ret_val = self.cfg + del self.loop_stack del self.cfg - del self.flow + del self.block_list + del self.blocks return ret_val def enter_block (self, block): @@ -58,13 +63,15 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): def exit_block (self, block): assert block == self.block del self.block - i, op, opname, arg, args = self.flow[block][-1] + i, op, arg = self.blocks[block][-1] + opname = opcode.opname[op] if op in opcode.hasjabs: self.cfg.add_edge(block, arg) elif op in opcode.hasjrel: self.cfg.add_edge(block, i + arg + 3) elif opname == 'BREAK_LOOP': - self.cfg.add_edge(block, arg) + loop_i, _, loop_arg = self.loop_stack[-1] + self.cfg.add_edge(block, loop_i + loop_arg + 3) elif opname != 'RETURN_VALUE': self.cfg.add_edge(block, self._get_next_block(block)) if op in opcode_util.hascbranch: @@ -80,15 +87,24 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args, **kws) + def op_SETUP_LOOP (self, i, op, arg, *args, **kws): + self.loop_stack.append((i, op, arg)) + return super(ControlFlowBuilder, self).op_SETUP_LOOP(i, op, arg, *args, + **kws) + + def op_POP_BLOCK (self, i, op, arg, *args, **kws): + self.loop_stack.pop() + return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args, + **kws) + # ______________________________________________________________________ def build_cfg (func): '''Given a Python function, create a bytecode flow, visit the flow object, and return a control flow graph.''' - import byte_flow - return ControlFlowBuilder().visit( - byte_flow.build_flow(func), - opcode_util.get_code_object(func).co_argcount) + co_obj = opcode_util.get_code_object(func) + return ControlFlowBuilder().visit(opcode_util.build_basic_blocks(co_obj), + co_obj.co_argcount) # ______________________________________________________________________ # Main (self-test) routine diff --git a/llpython/byte_flow.py b/llpython/byte_flow.py index 822e564..4a878b2 100644 --- a/llpython/byte_flow.py +++ b/llpython/byte_flow.py @@ -4,13 +4,13 @@ import dis import opcode -from bytecode_visitor import BytecodeIterVisitor +from bytecode_visitor import BasicBlockVisitor import opcode_util # ______________________________________________________________________ -class BytecodeFlowBuilder (BytecodeIterVisitor): - '''Transforms a bytecode vector into a bytecode "flow tree". +class BytecodeFlowBuilder (BasicBlockVisitor): + '''Transforms a CFG into a bytecode "flow tree". The flow tree is a Python dictionary, described loosely by the following set of productions: @@ -36,6 +36,8 @@ class BytecodeFlowBuilder (BytecodeIterVisitor): if pops: if pops < 0: pops = arg - pops - 1 + assert pops <= len(self.stack), ("Stack underflow at instruction " + "%d (%s)!" % (i, opname)) stk_args = self.stack[-pops:] del self.stack[-pops:] else: @@ -51,27 +53,50 @@ class BytecodeFlowBuilder (BytecodeIterVisitor): opname, pops, pushes, appends = self.opmap[op] return self._visit_op(i, op, arg, opname, pops, pushes, appends) - def enter_code_object (self, co_obj): - labels = dis.findlabels(co_obj.co_code) - labels = opcode_util.extendlabels(co_obj.co_code, labels) + def visit_cfg (self, cfg): + self.cfg = cfg + ret_val = self.visit(cfg.blocks) + del self.cfg + return ret_val + + def enter_blocks (self, blocks): + labels = list(blocks.keys()) + labels.sort() self.blocks = dict((index, []) for index in labels) - self.stack = [] self.loop_stack = [] - self.blocks[0] = self.block = [] + self.stacks = {} - def exit_code_object (self, co_obj): + def exit_blocks (self, blocks): ret_val = self.blocks - del self.stack + del self.stacks del self.loop_stack - del self.block del self.blocks return ret_val - def visit_op (self, i, op, arg): - if i in self.blocks: - self.block = self.blocks[i] - return super(BytecodeFlowBuilder, self).visit_op(i, op, arg) + def enter_block (self, block): + self.block_no = block + self.block = self.blocks[block] + in_blocks = self.cfg.blocks_in[block] + if len(in_blocks) == 0: + self.stack = [] + else: + pred_stack = None + for pred in in_blocks: + if pred in self.stacks: + pred_stack = self.stacks[pred] + break + if pred_stack is not None: + self.stack = pred_stack[:] + else: + raise NotImplementedError() + + def exit_block (self, block): + assert self.block_no == block + self.stacks[block] = self.stack + del self.stack + del self.block + del self.block_no op_BINARY_ADD = _op op_BINARY_AND = _op @@ -140,8 +165,14 @@ class BytecodeFlowBuilder (BytecodeIterVisitor): op_INPLACE_XOR = _op op_JUMP_ABSOLUTE = _op op_JUMP_FORWARD = _op - op_JUMP_IF_FALSE = _op - op_JUMP_IF_TRUE = _op + + def op_JUMP_IF_FALSE (self, i, op, arg): + opname, _, _, _ = self.opmap[op] + ret_val = (i, op, opname, arg, [self.stack[-1]]) + self.block.append(ret_val) + return ret_val + + op_JUMP_IF_TRUE = op_JUMP_IF_FALSE op_LIST_APPEND = _op op_LOAD_ATTR = _op op_LOAD_CLOSURE = _op @@ -211,7 +242,9 @@ class BytecodeFlowBuilder (BytecodeIterVisitor): def build_flow (func): '''Given a Python function, return a bytecode flow tree for that function.''' - return BytecodeFlowBuilder().visit(opcode_util.get_code_object(func)) + import byte_control + cfg = byte_control.build_cfg(func) + return BytecodeFlowBuilder().visit_cfg(cfg) # ______________________________________________________________________ # Main (self-test) routine diff --git a/llpython/byte_translator.py b/llpython/byte_translator.py index 93ccb6f..de36640 100644 --- a/llpython/byte_translator.py +++ b/llpython/byte_translator.py @@ -153,7 +153,7 @@ class LLVMTranslator (BytecodeFlowVisitor): environment.''' if llvm_type is None: if llvm_function is None: - llvm_type = lc.Type.function(lvoid, ()) + llvm_type = lc.Type.function(bytetype.lvoid, ()) else: llvm_type = llvm_function.type.pointee if env is None: @@ -178,7 +178,8 @@ class LLVMTranslator (BytecodeFlowVisitor): self.globals = func_globals nargs = self.code_obj.co_argcount self.cfg = self.control_flow_builder.visit( - self.bytecode_flow_builder.visit(self.code_obj), nargs) + opcode_util.build_basic_blocks(self.code_obj), nargs) + self.cfg.blocks = self.bytecode_flow_builder.visit_cfg(self.cfg) self.llvm_function = llvm_function flow = self.phi_injector.visit_cfg(self.cfg, nargs) ret_val = self.visit(flow) @@ -450,7 +451,7 @@ class LLVMTranslator (BytecodeFlowVisitor): def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws): cond = args[0] - block_false = self.llvm_blocks[op] + block_false = self.llvm_blocks[i + 3 + arg] block_true = self.llvm_blocks[i + 3] return [self.builder.cbranch(cond, block_true, block_false)] # raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE") diff --git a/llpython/bytecode_visitor.py b/llpython/bytecode_visitor.py index 091e138..dcc3a0c 100644 --- a/llpython/bytecode_visitor.py +++ b/llpython/bytecode_visitor.py @@ -164,6 +164,32 @@ class BytecodeIterVisitor (BytecodeVisitor): # ______________________________________________________________________ +class BasicBlockVisitor (BytecodeVisitor): + def visit (self, blocks): + self.enter_blocks(blocks) + block_indices = list(blocks.keys()) + block_indices.sort() + for block_index in block_indices: + self.enter_block(block_index) + for i, op, arg in blocks[block_index]: + self.visit_op(i, op, arg) + self.exit_block(block_index) + return self.exit_blocks(blocks) + + def enter_blocks (self, blocks): + pass + + def exit_blocks (self, blocks): + pass + + def enter_block (self, block_index): + pass + + def exit_block (self, block_index): + pass + +# ______________________________________________________________________ + class BytecodeFlowVisitor (BytecodeVisitor): def visit (self, flow): self.block_list = list(flow.keys()) diff --git a/llpython/opcode_util.py b/llpython/opcode_util.py index 5c0cff9..efd0c5c 100644 --- a/llpython/opcode_util.py +++ b/llpython/opcode_util.py @@ -79,9 +79,9 @@ OPCODE_MAP = { 'INPLACE_XOR': (2, 1, None), 'JUMP_ABSOLUTE': (0, None, 1), 'JUMP_FORWARD': (0, None, 1), - 'JUMP_IF_FALSE': (1, None, 1), + 'JUMP_IF_FALSE': (1, 1, 1), 'JUMP_IF_FALSE_OR_POP': (None, None, None), - 'JUMP_IF_TRUE': (1, None, 1), + 'JUMP_IF_TRUE': (1, 1, 1), 'JUMP_IF_TRUE_OR_POP': (None, None, None), 'LIST_APPEND': (2, 0, 1), 'LOAD_ATTR': (1, 1, None), @@ -148,7 +148,7 @@ OPCODE_MAP = { # ______________________________________________________________________ # Module functions -def itercode(code): +def itercode(code, start = 0): """Return a generator of byte-offset, opcode, and argument from a byte-code-string """ @@ -159,7 +159,7 @@ def itercode(code): n = len(code) while i < n: op = code[i] - num = i + num = i + start i = i + 1 oparg = None if op >= opcode.HAVE_ARGUMENT: @@ -211,5 +211,16 @@ def extendlabels(code, labels = None): def get_code_object (func): return getattr(func, '__code__', getattr(func, 'func_code', None)) +# ______________________________________________________________________ + +def build_basic_blocks (co_obj): + co_code = co_obj.co_code + labels = extendlabels(co_code, dis.findlabels(co_code)) + labels.sort() + blocks = dict((index, list(itercode(co_code[index:next_index], index))) + for index, next_index in zip([0] + labels, + labels + [len(co_code)])) + return blocks + # ______________________________________________________________________ # End of opcode_util.py diff --git a/llpython/phi_injector.py b/llpython/phi_injector.py index 2618e97..6cccb66 100644 --- a/llpython/phi_injector.py +++ b/llpython/phi_injector.py @@ -127,9 +127,10 @@ class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): def inject_phis (func): '''Given a Python function, return a bytecode flow object that has been transformed by a fresh PhiInjector instance.''' - import byte_control + import byte_control, byte_flow argcount = byte_control.opcode_util.get_code_object(func).co_argcount cfg = byte_control.build_cfg(func) + cfg.blocks = byte_flow.BytecodeFlowBuilder().visit_cfg(cfg) return PhiInjector().visit_cfg(cfg, argcount) # ______________________________________________________________________ From b895f1fc99e4dd76444e1ba011a31a515c03eb8e Mon Sep 17 00:00:00 2001 From: Jon Riehl Date: Tue, 29 Jan 2013 16:44:03 -0600 Subject: [PATCH 014/338] Added explicit branch to otherwise unterminated basic blocks in llpython.byte_translator. --- llpython/byte_translator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llpython/byte_translator.py b/llpython/byte_translator.py index de36640..3922099 100644 --- a/llpython/byte_translator.py +++ b/llpython/byte_translator.py @@ -225,6 +225,12 @@ class LLVMTranslator (BytecodeFlowVisitor): return ret_val def exit_block (self, block): + bb_instrs = self.llvm_block.instructions + if ((len(bb_instrs) == 0) or + (not bb_instrs[-1].is_terminator)): + out_blocks = list(self.cfg.blocks_out[block]) + assert len(out_blocks) == 1 + self.builder.branch(self.llvm_blocks[out_blocks[0]]) del self.llvm_block del self.builder From 5d54bbb1cdc3c14f885135fdf365246e25b180ed Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 31 Jan 2013 16:00:39 -0600 Subject: [PATCH 015/338] Autodetect libLLVM*.so and use it if it exists; or, user can override if LLVMPY_DYNLINK. --- setup.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 0807ead..4ad1b35 100644 --- a/setup.py +++ b/setup.py @@ -11,8 +11,6 @@ else: default_llvm_config = 'llvm-config' llvm_config = os.environ.get('LLVM_CONFIG_PATH', default_llvm_config) -# set LLVMPY_DYNLINK=0, if you want to link _core.so statically -dynlink = int(os.environ.get('LLVMPY_DYNLINK', 1)) def run_llvm_config(args): cmd = llvm_config + ' ' + ' '.join(args) @@ -20,8 +18,7 @@ def run_llvm_config(args): if run_llvm_config(['--version']) == '': sys.exit("Cannot invoke llvm-config.\n" - "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config") - + "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config") def get_libs_and_objs(components): parts = run_llvm_config(['--libs'] + components).split() @@ -61,7 +58,37 @@ auto_intrinsic_gen(incdir) macros = [('__STDC_CONSTANT_MACROS', None), ('__STDC_LIMIT_MACROS', None)] + +def determine_to_use_dynlink(libdir, llvm_version): + user_envvar = os.environ.get('LLVMPY_DYNLINK', None) + if user_envvar is not None: + # if users sets LLVMPY_DYNLINK=[0|1] + # respect the user setting + print('User sets LLVMPY_DYNLINK to %s' % user_envvar) + return bool(int(user_envvar)) + else: + # otherwise, determine by scanning the libdir + libfile = 'libLLVM-%s' % llvm_version + print('Searching shared library %s in %s' % (libfile, libdir)) + so = '%s.so' % libfile + dylib = '%s.dylib' % libfile + dll = '%s.dll' % libfile + libdir_content = os.listdir(libdir) + if sys.platform.startswith('linux'): + return so in libdir_content + elif sys.platform.startswith('darwin'): + return dylib in libdir_content or so in libdir_content + elif sys.platform.startswith('win32'): + return dll in libdir_content + else: # other platforms + return any((x in libdir_content) for x in [so, dyld, dll]) + + +dynlink = determine_to_use_dynlink(libdir, llvm_version) + + if dynlink: + print('Using dynamic linking') libs_core = ['LLVM-%s' % llvm_version] objs_core = [] else: From 1d4c431b23283a844ea9c58f8d53f027b5601f3b Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Thu, 31 Jan 2013 17:53:01 -0600 Subject: [PATCH 016/338] minor simplification --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 4ad1b35..839d816 100644 --- a/setup.py +++ b/setup.py @@ -60,8 +60,8 @@ macros = [('__STDC_CONSTANT_MACROS', None), ('__STDC_LIMIT_MACROS', None)] def determine_to_use_dynlink(libdir, llvm_version): - user_envvar = os.environ.get('LLVMPY_DYNLINK', None) - if user_envvar is not None: + user_envvar = os.getenv('LLVMPY_DYNLINK') + if user_envvar: # if users sets LLVMPY_DYNLINK=[0|1] # respect the user setting print('User sets LLVMPY_DYNLINK to %s' % user_envvar) From 5dd0948c6505591f25531e3be88424ca5eef56c8 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Thu, 31 Jan 2013 17:54:20 -0600 Subject: [PATCH 017/338] cleanup --- docs/gh-pages.py | 2 +- llpython/nobitey.py | 2 +- llvm-config-win32.py | 4 ++-- llvm/passes.py | 4 ++-- llvm/tbaa.py | 8 ++++---- llvm/test_llvmpy.py | 4 ++-- setup.py | 2 +- test/loopvectorize.c | 2 +- test/loopvectorize.py | 2 +- test/test_debuginfo.py | 2 +- www/makeweb.py | 2 +- www/src/license.txt | 4 ++-- www/src/userguide.txt | 10 +++++----- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/gh-pages.py b/docs/gh-pages.py index d9c8614..dd30e28 100755 --- a/docs/gh-pages.py +++ b/docs/gh-pages.py @@ -86,7 +86,7 @@ if __name__ == '__main__': tag = sh2('git describe --exact-match') except CalledProcessError: tag = "dev" # Fallback - + startdir = os.getcwdu() if not os.path.exists(pages_dir): # init the repo diff --git a/llpython/nobitey.py b/llpython/nobitey.py index b756fc8..014216b 100644 --- a/llpython/nobitey.py +++ b/llpython/nobitey.py @@ -16,7 +16,7 @@ from pyaddfunc import pyaddfunc LLVM_TO_INT_PARSE_STR_MAP = { 8 : 'b', - 16 : 'h', + 16 : 'h', 32 : 'i', # Note that on 32-bit systems sizeof(int) == sizeof(long) 64 : 'L', # Seeing sizeof(long long) == 8 on both 32 and 64-bit platforms } diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 2b6e8f5..595452c 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -63,7 +63,7 @@ Shell32 print('-lLLVMNVPTXCodeGen') print('-lLLVMNVPTXDesc') print('-lLLVMNVPTXInfo') -elif sys.argv[1] == '--includedir': +elif sys.argv[1] == '--includedir': llvmbin = find_path_of('llvm-tblgen.exe') if llvmbin is None: raise RuntimeError('Could not find LLVM') @@ -71,7 +71,7 @@ elif sys.argv[1] == '--includedir': if not os.path.exists(os.path.join(incdir, 'llvm/BasicBlock.h')): raise RuntimeError('Could not find LLVM include dir') print incdir -elif sys.argv[1] == '--libdir': +elif sys.argv[1] == '--libdir': llvmbin = find_path_of('llvm-tblgen.exe') if llvmbin is None: raise RuntimeError('Could not find LLVM') diff --git a/llvm/passes.py b/llvm/passes.py index b1f236c..4d7efb4 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -156,7 +156,7 @@ class PassManager(object): def add(self, pass_obj): '''Add a pass to the pass manager. - + pass_obj --- Either a Pass instance, a string name of a pass ''' if isinstance(pass_obj, Pass): @@ -340,7 +340,7 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False, inline_threshold=2000, pm=True, fpm=True, mod=None): ''' tm --- The TargetMachine for which the passes are optimizing for. - The TargetMachine must stay alive until the pass managers + The TargetMachine must stay alive until the pass managers are removed. opt --- [0-3] Optimization level. Default to 2. loop_vectorize --- [boolean] Whether to use loop-vectorizer. diff --git a/llvm/tbaa.py b/llvm/tbaa.py index d8e0074..b510ce2 100644 --- a/llvm/tbaa.py +++ b/llvm/tbaa.py @@ -2,11 +2,11 @@ from llvm.core import * class TBAABuilder(object): '''Simplify creation of TBAA metadata. - - Each TBAABuidler object operates on a module. + + Each TBAABuidler object operates on a module. User can create multiple TBAABuilder on a module ''' - + def __init__(self, module, rootid): ''' module --- the module to use. @@ -23,7 +23,7 @@ class TBAABuilder(object): def get_node(self, name, parent=None, const=False): '''Returns a MetaData object representing a TBAA node. - Use loadstore_instruction.set_metadata('tbaa', node) to + Use loadstore_instruction.set_metadata('tbaa', node) to bind a type to a memory. ''' parent = parent or self.root diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index a5fe957..05b7d72 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -454,7 +454,7 @@ class TestEngineBuilder(TestCase): with self.assertRaises(llvm.LLVMException): # Ensure the targetmachine is owned. llvm._util.check_is_unowned(tm) - + with self.assertRaises(llvm.LLVMException): # Ensure the module is owned. @@ -932,7 +932,7 @@ class TestCPUSupport(TestCase): arg = le.GenericValue.real(Type.double(), 1.234) retval = ee.run_function(func, [arg]) - + golden = math.sin(1.234) answer = retval.as_real(Type.double()) self.assertTrue(abs(answer-golden)/golden < 1e-5) diff --git a/setup.py b/setup.py index 839d816..afbf56e 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ def run_llvm_config(args): if run_llvm_config(['--version']) == '': sys.exit("Cannot invoke llvm-config.\n" - "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config") + "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config") def get_libs_and_objs(components): parts = run_llvm_config(['--libs'] + components).split() diff --git a/test/loopvectorize.c b/test/loopvectorize.c index a46b633..a498898 100644 --- a/test/loopvectorize.c +++ b/test/loopvectorize.c @@ -41,4 +41,4 @@ void ex7(int *A, int *B, int n, int k) { void ex8(int *A, char *B, int n, int k) { for (int i = 0; i < n; ++i) A[i] += 4 * B[i]; -} \ No newline at end of file +} diff --git a/test/loopvectorize.py b/test/loopvectorize.py index 9cf1654..2c12d5b 100644 --- a/test/loopvectorize.py +++ b/test/loopvectorize.py @@ -40,4 +40,4 @@ class TestLoopVectorizer(TestCase): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index 0340c1b..33dbbdb 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -130,4 +130,4 @@ if __name__ == '__main__': # TestDebugInfo("test_debug_info_compile_unit").debug() # tester = TestDebugInfo("test_debug_info_compile_unit") # debug_in_gdb(tester.test_debug_info_compile_unit()) - unittest.main() \ No newline at end of file + unittest.main() diff --git a/www/makeweb.py b/www/makeweb.py index 936b69e..81c9283 100755 --- a/www/makeweb.py +++ b/www/makeweb.py @@ -139,7 +139,7 @@ def get_opts(): usage = "usage: %prog [options] srcdir destdir" p = OptionParser(usage=usage) - p.add_option("-f", "--force", action="store_true", dest="force", default=False, + p.add_option("-f", "--force", action="store_true", dest="force", default=False, help="ignore timestamps and force build of all files") p.add_option("-v", "--verbose", action="count", dest="verbose", default=0, help="be chatty (use more v's to be more friendly)") diff --git a/www/src/license.txt b/www/src/license.txt index e40da20..9465a49 100644 --- a/www/src/license.txt +++ b/www/src/license.txt @@ -1,12 +1,12 @@ License ======= -llvm-py is distributed under the +llvm-py is distributed under the http://www.opensource.org/licenses/bsd-license.php[new BSD license]. This is similar to LLVM's license. You should be able to use llvm-py where-ever and how-ever you're able to use LLVM itself. -The license text is present in the +The license text is present in the http://code.google.com/p/llvm-py/source/browse/trunk/LICENSE[LICENSE] file in the distribution, and is reproduced here: diff --git a/www/src/userguide.txt b/www/src/userguide.txt index cf67e1c..bbd7ad3 100644 --- a/www/src/userguide.txt +++ b/www/src/userguide.txt @@ -35,7 +35,7 @@ information is available link:license.html[here]. .Platforms llvm-py has been built/tested/reported to work on various GNU/Linux flavours, *BSD, Mac OS X; on i386 and amd64 architectures. Windows is not -supported, for a variety of reasons. +supported, for a variety of reasons. .Versions llvm-py 0.6 requires verion 2.7 of LLVM. It will not work with previous @@ -433,7 +433,7 @@ Here is a quick overview of the contents of each package: sizes and alignment of primitive types, endinanness etc) .llvm.passes -- PassManager -- represents an LLVM pass manager +- PassManager -- represents an LLVM pass manager - FunctionPassManager -- represents an LLVM function pass manager - constants +PASS_*+ that represent various passes @@ -1007,7 +1007,7 @@ The `Function` object represents an instance of a function type. Such objects contain `Argument` objects, which represent the actual, local-variable-like arguments of the function (not to be confused with the arguments returned by a function _type_ object -- these represent -the _type_ of the arguments). +the _type_ of the arguments). The various `Instruction`-s are created by the `Builder` class. Most instructions are represented by `Instruction` itself, but there are @@ -1260,7 +1260,7 @@ Global Value (llvm.core) The class `llvm.core.GlobalValue` represents module-scope aliases, variables and functions. Global variables are represented by the sub-class -`llvm.core.GlobalVariable` and functions by `llvm.core.Function`. +`llvm.core.GlobalVariable` and functions by `llvm.core.Function`. Global values have the read-write properties `linkage`, `section`, `visibility` and `alignment`. Use one of the following constants (from @@ -1841,7 +1841,7 @@ The `llvm.core.PHINode` is a subclass of created (using `Builder.phi`) the phi node contains no incoming blocks (nor their corresponding values). To add an incoming arc to the phi node, use the `add_incoming` method, which takes a source -block (`llvm.core.BasicBlock` object) and a value (object of +block (`llvm.core.BasicBlock` object) and a value (object of `llvm.core.Value` or of a class derived from it) that the phi node will take on if control branches in from that block. From fe37d8bae0b095f7a23cc3b325fbc27124399ba2 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Thu, 31 Jan 2013 20:21:15 -0600 Subject: [PATCH 018/338] DOC: explain link detection in changelog --- CHANGELOG | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cc465d6..14e4503 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,10 @@ 2013-??-?? 0.10.2: -------------------- - * change default to link dynamically to LLVM (use LLVMPY_DYNLINK=0 to link - statically) + * change default to link dynamically to LLVM use: + $ export LLVMPY_DYNLINK=0 # link statically + $ export LLVMPY_DYNLINK=1 # link dynamically + $ unset LLVMPY_DYNLINK # tries to link dynamically if LLVM shared + # objects are found and statically otherwise 2013-01-25 0.10.1: From 7bd02ef91a3969a872721cd4c7fe61ba21b0e8e1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 12:06:17 -0600 Subject: [PATCH 019/338] Update changelog about recent llpython fixes. --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 14e4503..fb9e40e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,7 +5,7 @@ $ export LLVMPY_DYNLINK=1 # link dynamically $ unset LLVMPY_DYNLINK # tries to link dynamically if LLVM shared # objects are found and statically otherwise - + * fix llpython for Python 2.6 support. 2013-01-25 0.10.1: -------------------- From 4fb754924386d931c2a2d2305bb1ae9779b32d4a Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 1 Feb 2013 14:16:38 -0600 Subject: [PATCH 020/338] add release date --- CHANGELOG | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fb9e40e..3d19ab8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,12 @@ -2013-??-?? 0.10.2: +2013-02-01 0.10.2: -------------------- * change default to link dynamically to LLVM use: $ export LLVMPY_DYNLINK=0 # link statically $ export LLVMPY_DYNLINK=1 # link dynamically $ unset LLVMPY_DYNLINK # tries to link dynamically if LLVM shared # objects are found and statically otherwise - * fix llpython for Python 2.6 support. + * fix llpython for Python 2.6 support + 2013-01-25 0.10.1: -------------------- From 3f789913f533ce85f3f6e80116e4993cb4cb5654 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 1 Feb 2013 15:55:12 -0600 Subject: [PATCH 021/338] add versioneer --- setup.py | 46 ++-- versioneer.py | 642 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 669 insertions(+), 19 deletions(-) create mode 100644 versioneer.py diff --git a/setup.py b/setup.py index afbf56e..6816f81 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,15 @@ import sys import os -import re from distutils.core import setup, Extension +import versioneer + + +versioneer.versionfile_source = 'llvm/_version.py' +versioneer.versionfile_build = 'llvm/_version.py' +versioneer.tag_prefix = '' +versioneer.parentdir_prefix = 'llvmpy-' + # On win32, there is a fake llvm-config since llvm doesn't supply one if sys.platform == 'win32': @@ -130,20 +137,24 @@ else: macros.append(('_GNU_SOURCE', None)) extra_link_args = ldflags.split() -kwds = dict(ext_modules = [Extension( - name='llvm._core', - sources=['llvm/_core.cpp', 'llvm/wrap.cpp', 'llvm/extra.cpp'], - define_macros = macros, - include_dirs = ['/usr/include', incdir], - library_dirs = [libdir], - libraries = libs_core, - extra_objects = objs_core, - extra_link_args = extra_link_args), +kwds = dict( + ext_modules = [ + Extension( + name='llvm._core', + sources=['llvm/_core.cpp', 'llvm/wrap.cpp', 'llvm/extra.cpp'], + define_macros = macros, + include_dirs = ['/usr/include', incdir], + library_dirs = [libdir], + libraries = libs_core, + extra_objects = objs_core, + extra_link_args = extra_link_args), - Extension(name='llvm._dwarf', - sources=['llvm/_dwarf.cpp'], - include_dirs=[incdir]) -]) + Extension(name='llvm._dwarf', + sources=['llvm/_dwarf.cpp'], + include_dirs=[incdir]) + ], + cmdclass = versioneer.get_cmdclass(), +) def run_2to3(): import lib2to3.refactor @@ -155,19 +166,16 @@ def run_2to3(): # if fix.split('fix_')[-1] not in ('next',) #] - kwds["cmdclass"] = {"build_py": build_py} + kwds["cmdclass"].update(dict(build_py=build_py)) if sys.version_info[0] >= 3: run_2to3() -# Read version from llvm/__init__.py -pat = re.compile(r'__version__\s*=\s*(\S+)', re.M) -data = open('llvm/__init__.py').read() -kwds['version'] = eval(pat.search(data).group(1)) kwds['long_description'] = open('README.rst').read() setup( name = 'llvmpy', + version=versioneer.get_version(), description = 'Python bindings for LLVM', author = 'R Mahadevan', maintainer = 'Continuum Analytics, Inc.', diff --git a/versioneer.py b/versioneer.py new file mode 100644 index 0000000..02bc76a --- /dev/null +++ b/versioneer.py @@ -0,0 +1,642 @@ +#! /usr/bin/python + +"""versioneer.py + +(like a rocketeer, but for versions) + +* https://github.com/warner/python-versioneer +* Brian Warner +* License: Public Domain +* Version: 0.7+ + +This file helps distutils-based projects manage their version number by just +creating version-control tags. + +For developers who work from a VCS-generated tree (e.g. 'git clone' etc), +each 'setup.py version', 'setup.py build', 'setup.py sdist' will compute a +version number by asking your version-control tool about the current +checkout. The version number will be written into a generated _version.py +file of your choosing, where it can be included by your __init__.py + +For users who work from a VCS-generated tarball (e.g. 'git archive'), it will +compute a version number by looking at the name of the directory created when +te tarball is unpacked. This conventionally includes both the name of the +project and a version number. + +For users who work from a tarball built by 'setup.py sdist', it will get a +version number from a previously-generated _version.py file. + +As a result, loading code directly from the source tree will not result in a +real version. If you want real versions from VCS trees (where you frequently +update from the upstream repository, or do new development), you will need to +do a 'setup.py version' after each update, and load code from the build/ +directory. + +You need to provide this code with a few configuration values: + + versionfile_source: + A project-relative pathname into which the generated version strings + should be written. This is usually a _version.py next to your project's + main __init__.py file. If your project uses src/myproject/__init__.py, + this should be 'src/myproject/_version.py'. This file should be checked + in to your VCS as usual: the copy created below by 'setup.py + update_files' will include code that parses expanded VCS keywords in + generated tarballs. The 'build' and 'sdist' commands will replace it with + a copy that has just the calculated version string. + + versionfile_build: + Like versionfile_source, but relative to the build directory instead of + the source directory. These will differ when your setup.py uses + 'package_dir='. If you have package_dir={'myproject': 'src/myproject'}, + then you will probably have versionfile_build='myproject/_version.py' and + versionfile_source='src/myproject/_version.py'. + + tag_prefix: a string, like 'PROJECTNAME-', which appears at the start of all + VCS tags. If your tags look like 'myproject-1.2.0', then you + should use tag_prefix='myproject-'. If you use unprefixed tags + like '1.2.0', this should be an empty string. + + parentdir_prefix: a string, frequently the same as tag_prefix, which + appears at the start of all unpacked tarball filenames. If + your tarball unpacks into 'myproject-1.2.0', this should + be 'myproject-'. + +To use it: + + 1: include this file in the top level of your project + 2: make the following changes to the top of your setup.py: + import versioneer + versioneer.versionfile_source = 'src/myproject/_version.py' + versioneer.versionfile_build = 'myproject/_version.py' + versioneer.tag_prefix = '' # tags are like 1.2.0 + versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0' + 3: add the following arguments to the setup() call in your setup.py: + version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), + 4: run 'setup.py update_files', which will create _version.py, and will + append the following to your __init__.py: + from _version import __version__ + 5: modify your MANIFEST.in to include versioneer.py + 6: add both versioneer.py and the generated _version.py to your VCS +""" + +import os +import sys +import re +import subprocess +from distutils.core import Command +from distutils.command.sdist import sdist as _sdist +from distutils.command.build import build as _build + +versionfile_source = None +versionfile_build = None +tag_prefix = None +parentdir_prefix = None + +VCS = "git" +IN_LONG_VERSION_PY = False +GIT = "git" + + +LONG_VERSION_PY = ''' +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by github's download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7+ (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" +git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" + + +import subprocess +import sys + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %%s" %% args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %%s (error)" %% args[0]) + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%%s', no digits" %% ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %%d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %%s" %% ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %%s" %% r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %%s" %% root) + return {} + + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%%s' doesn't start with prefix '%%s'" %% (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%%s', but '%%s' doesn't start with prefix '%%s'" %% + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "%(TAG_PREFIX)s" +parentdir_prefix = "%(PARENTDIR_PREFIX)s" +versionfile_source = "%(VERSIONFILE_SOURCE)s" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver + +''' + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % args[0]) + return None + return stdout + + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%s', no digits" % ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %s" % ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + + +def do_vcs_install(versionfile_source, ipy): + run_command([GIT, "add", "versioneer.py"]) + run_command([GIT, "add", versionfile_source]) + run_command([GIT, "add", ipy]) + present = False + try: + f = open(".gitattributes", "r") + for line in f.readlines(): + if line.strip().startswith(versionfile_source): + if "export-subst" in line.strip().split()[1:]: + present = True + f.close() + except EnvironmentError: + pass + if not present: + f = open(".gitattributes", "a+") + f.write("%s export-subst\n" % versionfile_source) + f.close() + run_command([GIT, "add", ".gitattributes"]) + + +SHORT_VERSION_PY = """ +# This file was generated by 'versioneer.py' (0.7+) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +version_version = '%(version)s' +version_full = '%(full)s' +def get_versions(default={}, verbose=False): + return {'version': version_version, 'full': version_full} + +""" + +DEFAULT = {"version": "unknown", "full": "unknown"} + +def versions_from_file(filename): + versions = {} + try: + f = open(filename) + except EnvironmentError: + return versions + for line in f.readlines(): + mo = re.match("version_version = '([^']+)'", line) + if mo: + versions["version"] = mo.group(1) + mo = re.match("version_full = '([^']+)'", line) + if mo: + versions["full"] = mo.group(1) + return versions + +def write_to_version_file(filename, versions): + f = open(filename, "w") + f.write(SHORT_VERSION_PY % versions) + f.close() + print("set %s to '%s'" % (filename, versions["version"])) + + +def get_best_versions(versionfile, tag_prefix, parentdir_prefix, + default=DEFAULT, verbose=False): + # returns dict with two keys: 'version' and 'full' + # + # extract version from first of _version.py, 'git describe', parentdir. + # This is meant to work for developers using a source checkout, for users + # of a tarball created by 'setup.py sdist', and for users of a + # tarball/zipball created by 'git archive' or github's download-from-tag + # feature. + + variables = get_expanded_variables(versionfile_source) + if variables: + ver = versions_from_expanded_variables(variables, tag_prefix) + if ver: + if verbose: print("got version from expanded variable %s" % ver) + return ver + + ver = versions_from_file(versionfile) + if ver: + if verbose: print("got version from file %s %s" % (versionfile, ver)) + return ver + + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if ver: + if verbose: print("got version from git %s" % ver) + return ver + + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, verbose) + if ver: + if verbose: print("got version from parentdir %s" % ver) + return ver + + if verbose: print("got version from default %s" % ver) + return default + +def get_versions(default=DEFAULT, verbose=False): + assert versionfile_source is not None, "please set versioneer.versionfile_source" + assert tag_prefix is not None, "please set versioneer.tag_prefix" + assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix" + return get_best_versions(versionfile_source, tag_prefix, parentdir_prefix, + default=default, verbose=verbose) +def get_version(verbose=False): + return get_versions(verbose=verbose)["version"] + +class cmd_version(Command): + description = "report generated version string" + user_options = [] + boolean_options = [] + def initialize_options(self): + pass + def finalize_options(self): + pass + def run(self): + ver = get_version(verbose=True) + print("Version is currently: %s" % ver) + + +class cmd_build(_build): + def run(self): + versions = get_versions(verbose=True) + _build.run(self) + # now locate _version.py in the new build/ directory and replace it + # with an updated value + target_versionfile = os.path.join(self.build_lib, versionfile_build) + print("UPDATING %s" % target_versionfile) + os.unlink(target_versionfile) + f = open(target_versionfile, "w") + f.write(SHORT_VERSION_PY % versions) + f.close() + +class cmd_sdist(_sdist): + def run(self): + versions = get_versions(verbose=True) + self._versioneer_generated_versions = versions + # unless we update this, the command will keep using the old version + self.distribution.metadata.version = versions["version"] + return _sdist.run(self) + + def make_release_tree(self, base_dir, files): + _sdist.make_release_tree(self, base_dir, files) + # now locate _version.py in the new base_dir directory (remembering + # that it may be a hardlink) and replace it with an updated value + target_versionfile = os.path.join(base_dir, versionfile_source) + print("UPDATING %s" % target_versionfile) + os.unlink(target_versionfile) + f = open(target_versionfile, "w") + f.write(SHORT_VERSION_PY % self._versioneer_generated_versions) + f.close() + +INIT_PY_SNIPPET = """ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions +""" + +class cmd_update_files(Command): + description = "modify __init__.py and create _version.py" + user_options = [] + boolean_options = [] + def initialize_options(self): + pass + def finalize_options(self): + pass + def run(self): + ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py") + print(" creating %s" % versionfile_source) + f = open(versionfile_source, "w") + f.write(LONG_VERSION_PY % {"DOLLAR": "$", + "TAG_PREFIX": tag_prefix, + "PARENTDIR_PREFIX": parentdir_prefix, + "VERSIONFILE_SOURCE": versionfile_source, + }) + f.close() + try: + old = open(ipy, "r").read() + except EnvironmentError: + old = "" + if INIT_PY_SNIPPET not in old: + print(" appending to %s" % ipy) + f = open(ipy, "a") + f.write(INIT_PY_SNIPPET) + f.close() + else: + print(" %s unmodified" % ipy) + do_vcs_install(versionfile_source, ipy) + +def get_cmdclass(): + return {'version': cmd_version, + 'update_files': cmd_update_files, + 'build': cmd_build, + 'sdist': cmd_sdist, + } From 0a6a11f35adc1425800abb34d148b5ddd3db550d Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Fri, 1 Feb 2013 16:04:58 -0600 Subject: [PATCH 022/338] add missing llvm/_version.py --- .gitattributes | 1 + llvm/__init__.py | 4 +- llvm/_version.py | 194 +++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 .gitattributes create mode 100644 llvm/_version.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3a05aa8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +llvm/_version.py export-subst diff --git a/llvm/__init__.py b/llvm/__init__.py index 1935514..8f61f35 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -2,7 +2,9 @@ Common classes related to LLVM. """ -__version__ = '0.10.2' +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions from weakref import WeakValueDictionary diff --git a/llvm/_version.py b/llvm/_version.py new file mode 100644 index 0000000..4b60157 --- /dev/null +++ b/llvm/_version.py @@ -0,0 +1,194 @@ + +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by github's download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7+ (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "$Format:%d$" +git_full = "$Format:%H$" + + +import subprocess +import sys + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % args[0]) + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%s', no digits" % ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %s" % ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "" +parentdir_prefix = "llvmpy-" +versionfile_source = "llvm/_version.py" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver + diff --git a/setup.py b/setup.py index 6816f81..78079fd 100644 --- a/setup.py +++ b/setup.py @@ -88,7 +88,7 @@ def determine_to_use_dynlink(libdir, llvm_version): elif sys.platform.startswith('win32'): return dll in libdir_content else: # other platforms - return any((x in libdir_content) for x in [so, dyld, dll]) + return any((x in libdir_content) for x in [so, dylib, dll]) dynlink = determine_to_use_dynlink(libdir, llvm_version) From c822f5f9f7746b930f403cd6258311012272064a Mon Sep 17 00:00:00 2001 From: Phillip Cloud Date: Sat, 2 Feb 2013 20:44:27 -0500 Subject: [PATCH 023/338] add GIT variable to _version.py --- llvm/_version.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/_version.py b/llvm/_version.py index 4b60157..a90c5b8 100644 --- a/llvm/_version.py +++ b/llvm/_version.py @@ -12,7 +12,7 @@ IN_LONG_VERSION_PY = True # these strings will be replaced by git during git-archive git_refnames = "$Format:%d$" git_full = "$Format:%H$" - +GIT = "git" import subprocess import sys @@ -191,4 +191,3 @@ def get_versions(default={"version": "unknown", "full": ""}, verbose=False): if not ver: ver = default return ver - From a12c4da93d1147384c08f8d4ffed16ddcb383e99 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:09:14 -0600 Subject: [PATCH 024/338] Init commit for work on new binding This contains the foundation for the new binding as well as early work on Module and Type. --- newbinding/Makefile | 18 + .../binding/AssemblyAnnotationWriter.py | 6 + newbinding/binding/DerivedTypes.py | 13 + newbinding/binding/LLVMContext.py | 8 + newbinding/binding/Makefile | 0 newbinding/binding/Module.py | 25 + newbinding/binding/StringRef.py | 6 + newbinding/binding/Type.py | 96 ++++ newbinding/binding/_Debug.py | 3 + newbinding/binding/binding.py | 498 ++++++++++++++++++ newbinding/binding/gen.py | 206 ++++++++ newbinding/binding/namespace.py | 4 + newbinding/binding/raw_ostream.py | 17 + newbinding/binding/utils.py | 6 + newbinding/capsule.cpp | 143 +++++ newbinding/capsule.py | 74 +++ newbinding/include/llvm_binding/binding.h | 73 +++ .../include/llvm_binding/capsule_context.h | 48 ++ newbinding/include/llvm_binding/conversion.h | 93 ++++ newbinding/include/llvm_binding/extra.h | 34 ++ newbinding/setup.py | 54 ++ newbinding/test.py | 32 ++ newbinding/test2.py | 20 + 23 files changed, 1477 insertions(+) create mode 100644 newbinding/Makefile create mode 100644 newbinding/binding/AssemblyAnnotationWriter.py create mode 100644 newbinding/binding/DerivedTypes.py create mode 100644 newbinding/binding/LLVMContext.py create mode 100644 newbinding/binding/Makefile create mode 100644 newbinding/binding/Module.py create mode 100644 newbinding/binding/StringRef.py create mode 100644 newbinding/binding/Type.py create mode 100644 newbinding/binding/_Debug.py create mode 100644 newbinding/binding/binding.py create mode 100644 newbinding/binding/gen.py create mode 100644 newbinding/binding/namespace.py create mode 100644 newbinding/binding/raw_ostream.py create mode 100644 newbinding/binding/utils.py create mode 100644 newbinding/capsule.cpp create mode 100644 newbinding/capsule.py create mode 100644 newbinding/include/llvm_binding/binding.h create mode 100644 newbinding/include/llvm_binding/capsule_context.h create mode 100644 newbinding/include/llvm_binding/conversion.h create mode 100644 newbinding/include/llvm_binding/extra.h create mode 100644 newbinding/setup.py create mode 100644 newbinding/test.py create mode 100644 newbinding/test2.py diff --git a/newbinding/Makefile b/newbinding/Makefile new file mode 100644 index 0000000..ba902e3 --- /dev/null +++ b/newbinding/Makefile @@ -0,0 +1,18 @@ +PYMODS = _Debug raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module + +all: _api.so _capsule.so + +_api.so _capsule.so: api.cpp capsule.cpp + python setup.py build_ext --inplace + + +api.cpp api.py: binding/*.py include/llvm_binding/*.h + cd binding; python gen.py api $(PYMODS) + mv binding/api.cpp api.cpp + mv binding/api.py api.py + +clean: + rm -f _api.so _capsule.so + rm -f api.cpp api.py + + diff --git a/newbinding/binding/AssemblyAnnotationWriter.py b/newbinding/binding/AssemblyAnnotationWriter.py new file mode 100644 index 0000000..5641232 --- /dev/null +++ b/newbinding/binding/AssemblyAnnotationWriter.py @@ -0,0 +1,6 @@ +from binding import * +from namespace import llvm + +AssemblyAnnotationWriter = llvm.Class() +AssemblyAnnotationWriter.include.add("llvm/Assembly/AssemblyAnnotationWriter.h") + diff --git a/newbinding/binding/DerivedTypes.py b/newbinding/binding/DerivedTypes.py new file mode 100644 index 0000000..10d5fbf --- /dev/null +++ b/newbinding/binding/DerivedTypes.py @@ -0,0 +1,13 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from Type import Type + +FunctionType = Type.Subclass() +FunctionType.include.add('llvm/DerivedTypes.h') + +get = FunctionType.staticmethod(FunctionType.Pointer, Type.Pointer, Bool.From(bool)) +isVarArg = FunctionType.method(Bool.To(bool)) +getReturnType = FunctionType.method(Type.Pointer) +getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int)) +getNumParams = FunctionType.method(Unsigned.To(int)) diff --git a/newbinding/binding/LLVMContext.py b/newbinding/binding/LLVMContext.py new file mode 100644 index 0000000..0965748 --- /dev/null +++ b/newbinding/binding/LLVMContext.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm + +LLVMContext = llvm.Class() +LLVMContext.include.add("llvm/LLVMContext.h") + +getGlobalContext = llvm.Function(LLVMContext.Ref) + diff --git a/newbinding/binding/Makefile b/newbinding/binding/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/newbinding/binding/Module.py b/newbinding/binding/Module.py new file mode 100644 index 0000000..a458401 --- /dev/null +++ b/newbinding/binding/Module.py @@ -0,0 +1,25 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from StringRef import StringRef +from raw_ostream import raw_svector_ostream_helper +from AssemblyAnnotationWriter import AssemblyAnnotationWriter + +Module = llvm.Class() +Module.include.add("llvm/Module.h") + +new = Module.new(StringRef.From(str), LLVMContext.Ref) +delete = Module.delete() +getModuleIdentifier = Module.method(ConstStdString.To(str)) +setModuleIdentifier = Module.method(Void, StringRef.From(str)) +setDataLayout = Module.method(Void, StringRef.From(str)) +setTargetTriple = Module.method(Void, StringRef.From(str)) +setModuleInlineAsm = Module.method(Void, StringRef.From(str)) +appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) +getContext = Module.method(LLVMContext.Ref) +dump = Module.method(Void) +print_ = Module.method(Void, raw_svector_ostream_helper.Ref, + AssemblyAnnotationWriter.Pointer) +print_.realname = 'print' +#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) + diff --git a/newbinding/binding/StringRef.py b/newbinding/binding/StringRef.py new file mode 100644 index 0000000..554629b --- /dev/null +++ b/newbinding/binding/StringRef.py @@ -0,0 +1,6 @@ +from binding import * +from namespace import llvm + +StringRef = llvm.Class() +StringRef.include.add("llvm/ADT/StringRef.h") + diff --git a/newbinding/binding/Type.py b/newbinding/binding/Type.py new file mode 100644 index 0000000..19f6d61 --- /dev/null +++ b/newbinding/binding/Type.py @@ -0,0 +1,96 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from raw_ostream import raw_svector_ostream_helper + +Type = llvm.Class() +Type.include.add('llvm/Type.h') + +IntegerType = Type.Subclass() +CompositeType = Type.Subclass() +SequentialType = CompositeType.Subclass() +PointerType = SequentialType.Subclass() + +getContext = Type.method(LLVMContext.Ref) +dump = Type.method(Void) +print_ = Type.method(Void, raw_svector_ostream_helper.Ref) +print_.realname = 'print' + +def type_checker(): + return Type.method(Bool.To(bool)) + +isVoidTy = type_checker() +isHalfTy = type_checker() +isFloatTy = type_checker() +isDoubleTy = type_checker() +isX86_FP80Ty = type_checker() +isFP128Ty = type_checker() +isPPC_FP128Ty = type_checker() +isFloatingPointTy = type_checker() +isX86_MMXTy = type_checker() +isFPOrFPVectorTy = type_checker() +isLabelTy = type_checker() +isMetadataTy = type_checker() +isIntOrIntVectorTy = type_checker() +isFunctionTy = type_checker() +isStructTy = type_checker() +isArrayTy = type_checker() +isPointerTy = type_checker() +isPtrOrPtrVectorTy = type_checker() +isVectorTy = type_checker() +isEmptyTy = type_checker() +isPrimitiveType = type_checker() +isDerivedType = type_checker() +isFirstClassType = type_checker() +isSingleValueType = type_checker() +isAggregateType = type_checker() +isSized = type_checker() + +isIntegerTy = Type.multimethod([Bool.To(bool)], + [Bool.To(bool), Unsigned.From(int)]) + + +def type_factory(): + return Type.staticmethod(Type.Pointer, LLVMContext.Ref) + +getVoidTy = type_factory() +getLabelTy = type_factory() +getHalfTy = type_factory() +getFloatTy = type_factory() +getDoubleTy = type_factory() +getMetadataTy = type_factory() +getX86_FP80Ty = type_factory() +getFP128Ty = type_factory() +getPPC_FP128Ty = type_factory() +getX86_MMXTy = type_factory() + +getIntNTy = Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref, Unsigned.From(int)) + +def integer_factory(): + return Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref) + +getInt1Ty = integer_factory() +getInt8Ty = integer_factory() +getInt16Ty = integer_factory() +getInt32Ty = integer_factory() +getInt64Ty = integer_factory() + +def pointer_factory(): + return Type.staticmethod(PointerType.Pointer, LLVMContext.Ref) + +getHalfPtrTy = pointer_factory() +getFloatPtrTy = pointer_factory() +getDoublePtrTy = pointer_factory() +getX86_FP80PtrTy = pointer_factory() +getFP128PtrTy = pointer_factory() +getPPC_FP128PtrTy = pointer_factory() +getX86_MMXPtrTy = pointer_factory() +getInt1PtrTy = pointer_factory() +getInt8PtrTy = pointer_factory() +getInt16PtrTy = pointer_factory() +getInt32PtrTy = pointer_factory() +getInt64PtrTy = pointer_factory() +getIntNPtrTy = Type.staticmethod(PointerType.Pointer, + LLVMContext.Ref, Unsigned.From(int)) + + diff --git a/newbinding/binding/_Debug.py b/newbinding/binding/_Debug.py new file mode 100644 index 0000000..be092f3 --- /dev/null +++ b/newbinding/binding/_Debug.py @@ -0,0 +1,3 @@ +from binding import * + +enable_capsule_dtor_debug = Function('', Void, Bool.From(bool)) diff --git a/newbinding/binding/binding.py b/newbinding/binding/binding.py new file mode 100644 index 0000000..1230813 --- /dev/null +++ b/newbinding/binding/binding.py @@ -0,0 +1,498 @@ +from utils import * + +_py2capi_fmtmap = { + str: 's#', +} + +NULL = 'NULL' + +_symbols = set() + +def new_symbol(name): + if name in _symbols: + ct = 1 + orig = name + while name in _symbols: + name = '%s%d' % (orig, ct) + ct += 1 + _symbols.add(name) + return name + +def parse_arguments(println, var, *args): + typecodes = [] + holders = [] + argvals = [] + for arg in args: + typecodes.append(arg.format) + val = declare(println, 'PyObject*') + argvals.append(val) + holders.append('&' + val) + + items = [var, '"%s"' % (''.join(typecodes))] + holders + println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items)) + + # unwrap + unwrapped = [] + for arg, val in zip(args, argvals): + unwrapped.append(arg.unwrap(println, val)) + + return unwrapped + +def mangle(name): + name = name.replace('_', '__').replace(' ', '_') + return name.replace('::', '_').rstrip('*&') + +def pycapsule_new(println, ptr, name, clsname, dtor='capsule_destructor'): + # build capsule + name_soften = mangle(name) + var = new_symbol('pycap_%s' % name_soften) + fmt = 'PyObject* %(var)s = PyCapsule_New(%(ptr)s, "%(name)s", %(dtor)s);' + println(fmt % locals()) + + # build context + fmt = 'new CapsuleContext("%(clsname)s")' + context = declare(println, 'CapsuleContext*', fmt % locals()) + + fmt = 'PyCapsule_SetContext(%(var)s, (void*)%(context)s)' + err = declare(println, 'int', fmt % locals()) + + println('if (%(err)s) return NULL;' % locals()) + return var + + +def declare(println, typ, init=None): + typ_soften = mangle(typ) + var = new_symbol('var_%s' % typ_soften) + if init is None: + println('%(typ)s %(var)s;' % locals()) + else: + println('%(typ)s %(var)s = %(init)s;' % locals()) + return var + + +def return_value(println, var): + println('return %(var)s;' % locals()) + + +def return_none(println): + println('Py_RETURN_NONE;') + + +def die_if_null(println, var): + println('if (!%(var)s) return NULL;' % locals()) + + +class Binding(object): + __rank_global = 0 + def __init__(self): + self.rank = Binding.__rank_global + Binding.__rank_global += 1 + self.include = set() + + def compile(self, name, println): + raise NotImplementedError(type(self)) + +class Ref(object): + def __init__(self, elem): + self.element = elem + + @property + def fullname(self): + return '%s&' % self.element.fullname + + @property + def capsule_name(self): + return self.element.capsule_name + + @property + def pointer(self): + return self.element.pointer + + def as_pointer(self, println, var): + init = '&%s' % (var) + casted = declare(println, self.pointer, init) + return casted + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + ptr = self.element.unwrap(println, var) + return declare(println, self.fullname, '*%s' % ptr) + + def wrap(self, println, var): + return self.element.wrap(println, self.as_pointer(println, var)) + + +class Pointer(object): + def __init__(self, elem): + self.element = elem + + @property + def fullname(self): + return '%s*' % self.element.fullname + + @property + def capsule_name(self): + return self.element.capsule_name + + @property + def pointer(self): + return self.element.pointer + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + ret = declare(println, self.fullname) + println2 = indent_println(println) + println('if (%(var)s == Py_None) {' % locals()) + println2('%(ret)s = NULL;' % locals()) + println('} else {') + ptr = self.element.unwrap(println2, var) + println2('%(ret)s = %(ptr)s;' % locals()) + println('}') + return ret + + def wrap(self, println, var): + return self.element.wrap(println, var) + + +class BuiltinType(object): + def __init__(self, name): + self.name = name + self.Ref = Ref(self) + self.Pointer = Pointer(self) + + @property + def fullname(self): + return self.name + + @property + def capsule_name(self): + return self.fullname + + def To(self, pytype): + return Wrapper(self, pytype) + + def From(self, pytype): + return Unwrapper(self, pytype) + +Void = BuiltinType('void') +Bool = BuiltinType('bool') +Unsigned = BuiltinType('unsigned') +ConstStdString = BuiltinType('const std::string') + +class Unwrapper(object): + def __init__(self, cls, pytype): + self.cls = cls + self.pytype = pytype + + @property + def fullname(self): + return str(self.pytype) + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + out = declare(println, self.cls.fullname) + conv = 'py_%s_to' % (self.pytype.__name__) + status = '%(conv)s(%(var)s, %(out)s)' % locals() + println('if (!%(status)s) return NULL;' % locals()) + return out + + +class Wrapper(object): + def __init__(self, cls, pytype): + self.cls = cls + self.pytype = pytype + + @property + def fullname(self): + return self.cls.fullname + + def wrap(self, println, var): + conv = 'py_%s_from' % (self.pytype.__name__) + func = '%(conv)s(%(var)s)' % locals() + out = declare(println, 'PyObject*', func) + println('if (!%(out)s) return NULL;' % locals()) + return out + +class Class(Binding): + def __init__(self, ns): + super(Class, self).__init__() + self.ctor = None + self.Ref = Ref(self) + self.Pointer = Pointer(self) + self.Subclass = lambda: Subclass(self) + self.ns = ns + self.methods = [] + self.name = None + + def To(self, pytype): + return Wrapper(self, pytype) + + def From(self, pytype): + return Unwrapper(self, pytype) + + def new(self, *args): + method = Constructor(self, self.Pointer, *args) + self.methods.append(method) + return method + + def delete(self): + method = Destructor(self, Void, self.Pointer) + self.methods.append(method) + return method + + def method(self, return_type, *args): + method = Method(self, return_type, self.Pointer, *args) + self.methods.append(method) + return method + + def staticmethod(self, return_type, *args): + sm = StaticMethod(self, return_type, *args) + self.methods.append(sm) + return sm + + def multimethod(self, *signatures): + mm = MultiMethod(self, signatures) + self.methods.append(mm) + return mm + + def compile(self, name, println): + # set name + self.name = self.name or name + + @property + def capsule_name(self): + return self.fullname + + @property + def pointer(self): + return '%s*' % self.fullname + + @property + def fullname(self): + return '::'.join([self.ns, self.name]) + + @property + def mangled_name(self): + return mangle(self.fullname) + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + typ = self.pointer + elty = self.fullname + cap = self.capsule_name + capptr = 'PyCapsule_GetPointer(%(var)s, "%(cap)s")' % locals() + ptr = declare(println, 'void*', capptr) + unwrapped = 'typecast<%(elty)s>::from(%(ptr)s)' % locals() + var = declare(println, typ, unwrapped) + println('if (!%(var)s) {' % locals()) + println2 = indent_println(println) + println2('PyErr_SetString(PyExc_TypeError, "Invalid cast");') + println2('return NULL;') + println('}') + die_if_null(println, var) + return var + + def wrap(self, println, var): + return pycapsule_new(println, var, self.capsule_name, self.fullname) + +class Subclass(Class): + def __init__(self, parent): + super(Subclass, self).__init__(parent.ns) + self.parent = parent + self.ns = self.parent.ns + + @property + def capsule_name(self): + return self.parent.capsule_name + +class Function(Binding): + def __init__(self, ns, return_type, *args): + super(Function, self).__init__() + self.return_type = return_type + self.args = args + self.ns = ns + self.name = None + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + println('%(name)s(PyObject* self, PyObject* args)' % locals()) + println('{') + self.compile_body(indent_println(println)) + println('}') + + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + call = '%s(%s)' % (self.fullname, ', '.join(args)) + if self.return_type is not Void: + callres = declare(println, self.return_type.fullname, call) + pycap = self.return_type.wrap(println, callres) + return_value(println, pycap) + else: + println('%s;' % call) + return_none(println) + + + @property + def fullname(self): + return '::'.join([self.ns, self.name]) + +class Method(Binding): + def __init__(self, cls, return_type, *args): + super(Method, self).__init__() + self.cls = cls + self.return_type = return_type + self.args = args + self.name = None + self._realname = None + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + mangled = self.mangled_name + println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) + println('{') + self.compile_body(indent_println(println)) + println('}') + + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + this = args[0] + args = ', '.join(args[1:]) + name = self.realname + call = '%(this)s->%(name)s(%(args)s)' % locals() + if self.return_type is not Void: + obj = declare(println, self.return_type.fullname, call) + ret = self.return_type.wrap(println, obj) + return_value(println, ret) + else: + println('%s;' % call) + return_none(println) + + @property + def fullname(self): + return '::'.join([self.cls.fullname, self.name]) + + @property + def realname(self): + if not self._realname: + return self.name + else: + return self._realname + + @realname.setter + def realname(self, v): + self._realname = v + + + @property + def mangled_name(self): + return mangle(self.fullname) + +class MultiMethod(Binding): + '''Can only differs by the number of arguments. + ''' + def __init__(self, cls, signatures): + super(MultiMethod, self).__init__() + nargs = set() + for sig in signatures: + n = len(sig) + if n in nargs: + raise TypeError("MultiMethod only supports overloaded version" + "with different number of arguments") + nargs.add(n) + self.cls = cls + self.signatures = signatures + self.name = None + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + mangled = self.mangled_name + println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) + println('{') + println2 = indent_println(println) + nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') + for sig in self.signatures: + expect = len(sig) + println2('if (%(nargs)s == %(expect)d) {' % locals()) + method = Method(self.cls, sig[0], self.cls.Pointer, *sig[1:]) + method.name = self.name + method.compile_body(indent_println(println2)) + println2('}') + println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') + println2('return NULL;') + println('}') + + @property + def fullname(self): + return '::'.join([self.cls.fullname, self.name]) + + @property + def mangled_name(self): + return mangle(self.fullname) + +class StaticMethod(Method): + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + args = ', '.join(args) + fullname = self.fullname + call = '%(fullname)s(%(args)s)' % locals() + if self.return_type is not Void: + obj = declare(println, self.return_type.fullname, call) + ret = self.return_type.wrap(println, obj) + return_value(println, ret) + else: + println('%s;' % call) + return_none(println) + +class Constructor(StaticMethod): + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + args = ', '.join(args) + name = self.cls.fullname + ctor = 'new %(name)s(%(args)s)' % locals() + obj = declare(println, self.cls.pointer, ctor) + ret = self.return_type.wrap(println, obj) + return_value(println, ret) + +class Destructor(Method): + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + assert len(args) == 1 + dtor = 'delete %s;' % args[0] + println(dtor) + return_none(println) + + +class Namespace(object): + def __init__(self, name): + self.name = name + + def Class(self, *args, **kwargs): + return Class(self.name, *args, **kwargs) + + def Function(self, *args, **kwargs): + return Function(self.name, *args, **kwargs) + diff --git a/newbinding/binding/gen.py b/newbinding/binding/gen.py new file mode 100644 index 0000000..f662979 --- /dev/null +++ b/newbinding/binding/gen.py @@ -0,0 +1,206 @@ +import sys +from binding import * +from utils import * +from cStringIO import StringIO + +extension_entry = ''' + +extern "C" { + +#if (PY_MAJOR_VERSION >= 3) + +PyObject * +PyInit_%(module)s(void) +{ + PyObject *module = create_python_module("%(module)s", %(methtable)s); + if (module) { + if (populate_submodules(module, submodules)) + return module; + } + return NULL; +} + +#else + +PyMODINIT_FUNC +init%(module)s(void) +{ + PyObject *module = create_python_module("%(module)s", %(methtable)s); + if (module) { + populate_submodules(module, submodules); + } +} +#endif + +} // end extern C + +''' + +def build_methoddef(name, defns, println): + println('static PyMethodDef %s[] = {' % name) + for name, func in defns: + println('{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' % + locals()) + else: + println('{ NULL }') + println('};') + println('') + + +class Context(object): + def __init__(self): + self.includes = set() + self.functions = {} + self.classes = {} + self.definitions = [] + + def generate_cpp(self, println): + for i in self.includes: + println('#include "%s"' % i) + + println('\n'.join(self.definitions)) + + # global function + defns = [] + for name, func in self.functions.items(): + defns.append((name, func.name)) + build_methoddef('global_functions', defns, println) + + # classes + for name, cls in self.classes.items(): + defns = [] + for meth in cls.methods: + defns.append((meth.name, meth.mangled_name)) + println("// %s" % cls.fullname) + build_methoddef(cls.mangled_name, defns, println) + + println('static SubModuleEntry submodules[] = {') + for name, cls in self.classes.items(): + table = cls.mangled_name + println('{ "%(name)s", %(table)s },' % locals()) + println('{ NULL },') + println('};') + println('') + + # generate entry + println(extension_entry % {'module': '_api', + 'methtable': 'global_functions',}) + + def generate_py(self, println): + println('import _api, capsule') + println('') + # global function + for name in self.functions: + println('def %(name)s(*args):' % locals()) + println2 = indent_println(println) + println2('args = map(capsule.unwrap, args)') + println2('ptr = _api.%(name)s(*args)' % locals()) + println2('return capsule.wrap(ptr)') + println('') + # classes + classes = sorted(self.classes.items(), key=lambda x: x[1].rank) + + for name, cls in classes: + if isinstance(cls, Subclass): + parent = cls.parent.name + else: + parent = 'capsule.Wrapper' + println('@capsule.register_class') + println('class %(name)s(%(parent)s):' % locals()) + self.generate_py_class(indent_println(println), cls) + println('') + + def generate_py_class(self, println, cls): + if len(cls.methods) == 0: + println('pass') + else: + mod = cls.name + for method in cls.methods: + name = method.name + if isinstance(method, StaticMethod): + println('@staticmethod') + println('def %(name)s(*args):' % locals()) + println2 = indent_println(println) + println2('args = map(capsule.unwrap, args)') + println2('ret = _api.%(mod)s.%(name)s(*args)' % locals()) + println2('return capsule.wrap(ret)') + elif isinstance(method, Destructor): + println('_delete_ = _api.%(mod)s.%(name)s' % locals()) + else: + println('def %(name)s(self, *args):' % locals()) + println2 = indent_println(println) + println2('args = map(capsule.unwrap, args)') + println2('ret = _api.%(mod)s.%(name)s(self._ptr, *args)' % + locals()) + println2('return capsule.wrap(ret)') + println('') + + + def add_module(self, modname): + module = __import__(modname) + allsyms = [(k, v) for k, v in vars(module).items() + if isinstance(v, Binding)] + symtab = sorted(allsyms, key=lambda x: x[1].rank) + + # generate includes + for k, v in symtab: + self.includes |= v.include + + # compile everything + for k, v in symtab: + buf = StringIO() + def println_to_def(s): + buf.write(s) + buf.write('\n') + v.compile(k, println_to_def) + self.definitions.append(buf.getvalue()) + buf.close() + + # generate py defintion table for global functions + for k, v in symtab: + if isinstance(v, Function): + if v.name in self.functions: + raise NameError("Duplicated function name: %s" % v.name) + self.functions[v.name] = v + + # generate sub module tables for classes + submodules = [] + for k, v in symtab: + if isinstance(v, Class): + if v.name in self.classes: + if v is not self.classes[v.name]: + raise NameError("Duplicated class: %s" % v.name) + self.classes[v.name] = v + + +def populate_headers(println): + includes = [ + 'llvm_binding/conversion.h', + 'llvm_binding/binding.h', + 'llvm_binding/extra.h', + 'llvm_binding/capsule_context.h', + ] + for inc in includes: + println('#include "%s"' % inc) + +def wrap_println(f): + def println(s): + f.write(s) + f.write('\n') + return println + +if __name__ == '__main__': + + context = Context() + for mod in sys.argv[2:]: + context.add_module(mod) + + filename = sys.argv[1] + with open('%s.cpp' % filename, 'w') as outfile: + println = wrap_println(outfile) + populate_headers(println) + context.generate_cpp(println) + with open('%s.py' % filename, 'w') as outfile: + println = wrap_println(outfile) + context.generate_py(println) + diff --git a/newbinding/binding/namespace.py b/newbinding/binding/namespace.py new file mode 100644 index 0000000..02af8c9 --- /dev/null +++ b/newbinding/binding/namespace.py @@ -0,0 +1,4 @@ +from binding import * + +extra = Namespace('llvm_extra') +llvm = Namespace('llvm') diff --git a/newbinding/binding/raw_ostream.py b/newbinding/binding/raw_ostream.py new file mode 100644 index 0000000..0275db4 --- /dev/null +++ b/newbinding/binding/raw_ostream.py @@ -0,0 +1,17 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from StringRef import StringRef + +raw_ostream = llvm.Class() +raw_ostream.include.add("llvm/Support/raw_ostream.h") + +raw_svector_ostream = raw_ostream.Subclass() +raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h") + +# extra class to help binding +raw_svector_ostream_helper = raw_svector_ostream.Subclass() +create = raw_svector_ostream_helper.staticmethod( + raw_svector_ostream_helper.Pointer) +delete = raw_svector_ostream_helper.delete() +str = raw_svector_ostream_helper.method(StringRef.To(str)) diff --git a/newbinding/binding/utils.py b/newbinding/binding/utils.py new file mode 100644 index 0000000..6c39990 --- /dev/null +++ b/newbinding/binding/utils.py @@ -0,0 +1,6 @@ + +def indent_println(println): + def _println(s): + println("%s%s" % (' '* 4, s)) + return _println + diff --git a/newbinding/capsule.cpp b/newbinding/capsule.cpp new file mode 100644 index 0000000..40d135b --- /dev/null +++ b/newbinding/capsule.cpp @@ -0,0 +1,143 @@ +#include +#include + +static +PyObject* getName(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)){ + return NULL; + } + const char* name = PyCapsule_GetName(obj); + if (!name) return NULL; + + return PyString_FromString(name); +} + +static +PyObject* getPointer(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)){ + return NULL; + } + void* pointer = PyCapsule_GetPointer(obj, PyCapsule_GetName(obj)); + if (!pointer) return NULL; + + return PyLong_FromVoidPtr(pointer); +} + +static +PyObject* check(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)){ + return NULL; + } + if (PyCapsule_CheckExact(obj)) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +// ------------------ +// PyCapsule Context +// ------------------ + +static +CapsuleContext* getContext(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + void* context = PyCapsule_GetContext(obj); + if (!context) { + PyErr_SetString(PyExc_TypeError, "PyCapsule has no context."); + return NULL; + } + return (CapsuleContext*)context; +} + +static +PyObject* getClassName(PyObject* self, PyObject* args) { + CapsuleContext* context = getContext(self, args); + if (!context) { + return NULL; + } else { + return PyString_FromString(context->className); + } +} + +static +PyObject* setDestructor(PyObject* self, PyObject* args) { + PyObject* cap; + PyObject* callable; + if (!PyArg_ParseTuple(args, "OO", &cap, &callable)) { + return NULL; + } + PyObject* arglist = Py_BuildValue("(O)", cap); + CapsuleContext* context = getContext(self, arglist); + Py_DECREF(arglist); + if (!context) { + return NULL; + } else { + void* ptr; + if (callable != Py_None) { + if (PyCallable_Check(callable)) { + ptr = callable; + } else { + PyErr_SetString(PyExc_TypeError, "Argument is not callable."); + return NULL; + } + } else { + ptr = NULL; + } + context->destructor = (Destructor_Fn)ptr; + } + Py_RETURN_NONE; +} + +static PyMethodDef core_methods[] = { +#define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS , NULL } + declmethod(getName), + declmethod(getPointer), + declmethod(check), + declmethod(getClassName), + declmethod(setDestructor), + { NULL }, +#undef declmethod +}; + +// Module main function, hairy because of py3k port +extern "C" { + +#if (PY_MAJOR_VERSION >= 3) + struct PyModuleDef module_def = { + PyModuleDef_HEAD_INIT, + "_capsule", + NULL, + -1, + core_methods, + NULL, NULL, NULL, NULL + }; +#define INITERROR return NULL + PyObject * + PyInit__capsule(void) +#else +#define INITERROR return + PyMODINIT_FUNC + init_capsule(void) +#endif + { +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create( &module_def ); +#else + PyObject *module = Py_InitModule("_capsule", core_methods); +#endif + if (module == NULL) + INITERROR; +#if PY_MAJOR_VERSION >= 3 + + return module; +#endif + } + +} // end extern C diff --git a/newbinding/capsule.py b/newbinding/capsule.py new file mode 100644 index 0000000..b82154b --- /dev/null +++ b/newbinding/capsule.py @@ -0,0 +1,74 @@ +import _capsule +from weakref import WeakValueDictionary + +_pyclasses = {} +_addr2obj = WeakValueDictionary() + + +def _sentry(ptr): + assert _capsule.check(ptr) + + +def classof(cap): + cls = _capsule.getClassName(cap) + return _pyclasses[cls] + + +def wrap(cap): + '''Wrap a PyCapsule with the corresponding Wrapper class. + If `cap` is not a PyCapsule, returns `cap` + ''' + if not _capsule.check(cap): # bypass if cap is not a PyCapsule + return cap + addr = _capsule.getPointer(cap) + try: + # find cached object by pointer address + obj = _addr2obj[addr] + except KeyError: + # create new object and cache it + cls = classof(cap) + obj = cls(cap) + _addr2obj[addr] = obj # cache object by address + # set destructor if cls.delete is defined + if hasattr(cls, '_delete_'): + _capsule.setDestructor(cap, cls._delete_) + else: + assert classof(obj._ptr) is classof(cap) + # Unset destructor for capsules that are repeated + _capsule.setDestructor(cap, None) + return obj + + +def unwrap(obj): + '''Unwrap a Wrapper instance into the underlying PyCapsule. + If `obj` is not a Wrapper instance, returns `obj`. + ''' + if isinstance(obj, Wrapper): + return obj._ptr + else: + return obj + + +def register_class(cls): + clsname = cls.__name__ + _pyclasses['llvm::%s' % clsname] = cls + return cls + + +class Wrapper(object): + + __slots__ = '__ptr' + + def __init__(self, ptr): + _sentry(ptr) + self.__ptr = ptr + + @property + def _ptr(self): + return self.__ptr + + def _release_ownership(self): + _capsule.setDestructor(self._ptr, None) + + + diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h new file mode 100644 index 0000000..f7bfde6 --- /dev/null +++ b/newbinding/include/llvm_binding/binding.h @@ -0,0 +1,73 @@ +#include +#include + +#if (PY_MAJOR_VERSION >= 3) + +static +PyObject* +create_python_module(const char *name, PyMethodDef* methtable){ + PyModuleDef module_def_tmp = { + PyModuleDef_HEAD_INIT, + name, + NULL, + -1, + methtable, + NULL, NULL, NULL, NULL + }; + + PyModuleDef* module_def = new PyModuleDef(module_def_tmp); // will leak?? + PyObject* module = PyModule_Create(module_def); + if (module == NULL){ + delete module_def; + return NULL; + } + return module; +} + +#else + +static +PyObject* +create_python_module(const char *name, PyMethodDef* methtable){ + PyObject* module = Py_InitModule(name, methtable); + if (module == NULL) return NULL; + return module; +} + +#endif + +static +PyObject* +create_python_submodule(PyObject* parent, const char* name, + PyMethodDef* methtable) +{ + const char* parentname = PyModule_GetName(parent); + const unsigned len_parent = strlen(parentname); + const unsigned len_sub = strlen(name); + const unsigned len = len_parent + 1 + len_sub; + char* fullname = new char[len + 1]; + strcpy(fullname, parentname); + fullname[len_parent] = '.'; + strcpy(fullname + len_parent + 1, name); + PyObject* submod = create_python_module(fullname, methtable); + delete [] fullname; + if (!submod) + return NULL; + if( -1 == PyModule_AddObject(parent, name, submod) ) + return NULL; + return submod; +} + +struct SubModuleEntry{ + const char* name; + PyMethodDef* methtable; +}; + +static +int populate_submodules(PyObject* parent, SubModuleEntry* entries){ + for(SubModuleEntry* iter = entries; iter->name; ++iter){ + if (!create_python_submodule(parent, iter->name, iter->methtable)) + return 0; + } + return 1; +} \ No newline at end of file diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h new file mode 100644 index 0000000..bb45566 --- /dev/null +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -0,0 +1,48 @@ +#ifndef LLVMPY_CAPSULE_CONTEXT_H_ +#define LLVMPY_CAPSULE_CONTEXT_H_ +#include +#include + +typedef PyObject* Destructor_Fn; + +static bool CapsuleContextDebug = false; + +struct CapsuleContext { + const char* className; + Destructor_Fn destructor; + + CapsuleContext(const char* cn, Destructor_Fn dtor=NULL) + : className(cn), destructor(dtor) { } +}; + +void capsule_destructor(PyObject* capsule){ + using std::cerr; + using std::endl; + CapsuleContext* context = (CapsuleContext*)PyCapsule_GetContext(capsule); + if (context->destructor) { + if (CapsuleContextDebug) { + cerr << clock() + << " == DEBUG ==" + << " destroy pointer: " + << context->className + << endl; + } + PyObject_CallMethodObjArgs(context->destructor, capsule, NULL); + } else { + if (CapsuleContextDebug) { + cerr << clock() + << " == DEBUG ==" + << " keep pointer alive: " + << context->className + << endl; + } + } + delete context; +} + +void enable_capsule_dtor_debug(bool enabled){ + CapsuleContextDebug = enabled; +} + +#endif //LLVMPY_CAPSULE_CONTEXT_H_ + diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h new file mode 100644 index 0000000..c3d6e36 --- /dev/null +++ b/newbinding/include/llvm_binding/conversion.h @@ -0,0 +1,93 @@ +#include +#include +#include + +// python object unwrapper + +static +int py_str_to(PyObject *strobj, llvm::StringRef &strref){ + // type check + if (!PyString_Check(strobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get len and buffer + const Py_ssize_t len = PyString_Size(strobj); + const char * buf = PyString_AsString(strobj); + if (!buf) { + // raises TypeError + return 0; + } + // set output + strref = llvm::StringRef(buf, len); + // success + return 1; +} + +static +int py_int_to(PyObject *intobj, unsigned & val){ + if (!PyInt_Check(intobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting an int"); + return 0; + } + val = PyInt_AsUnsignedLongMask(intobj); + // success + return 1; +} + +static +int py_bool_to(PyObject *boolobj, bool & val){ + if (!PyBool_Check(boolobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a bool"); + return 0; + } + if (boolobj == Py_True) { + val = true; + } else if (boolobj == Py_False) { + val = false; + } else { + PyErr_SetString(PyExc_TypeError, "Invalid boolean object"); + return 0; + } + // success + return 1; +} + +// python object wrapper + +static +PyObject* py_str_from(const std::string &str){ + return PyString_FromStringAndSize(str.c_str(), str.size()); +} + +static +PyObject* py_bool_from(bool val){ + if (val) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static +PyObject* py_int_from(int val){ + return PyInt_FromLong(val); +} + +// casting +template +struct typecast { + template static + Td* from(Ts* src) { + return llvm::dyn_cast(src); + } + + static + Td* from(void* src) { + return static_cast(src); + } +}; + diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h new file mode 100644 index 0000000..a7388a2 --- /dev/null +++ b/newbinding/include/llvm_binding/extra.h @@ -0,0 +1,34 @@ +#include +#include +#include + +namespace llvm{ + +class raw_svector_ostream_helper: public raw_svector_ostream { + SmallVectorImpl *SV; +public: + static + raw_svector_ostream_helper* create(){ + SmallVectorImpl* sv = new SmallVector(); + return new raw_svector_ostream_helper(sv); + } + + ~raw_svector_ostream_helper(){ + delete SV; + } + +protected: + + explicit + raw_svector_ostream_helper(SmallVectorImpl* sv) + : raw_svector_ostream(*sv), SV(sv) {} + +private: + // no copy + raw_svector_ostream_helper(const raw_svector_ostream_helper&); + // no assign + void operator = (const raw_svector_ostream_helper&); +}; + +} + diff --git a/newbinding/setup.py b/newbinding/setup.py new file mode 100644 index 0000000..6e2ceb5 --- /dev/null +++ b/newbinding/setup.py @@ -0,0 +1,54 @@ +import sys, os +from distutils.core import setup, Extension + +llvm_config = os.environ.get('LLVM_CONFIG_PATH') + +def run_llvm_config(args): + cmd = llvm_config + ' ' + ' '.join(args) + return os.popen(cmd).read().rstrip() + +def get_libs_and_objs(components): + parts = run_llvm_config(['--libs'] + components).split() + libs = [] + objs = [] + for part in parts: + if part.startswith('-l'): + libs.append(part[2:]) + elif part.endswith('.o'): + objs.append(part) + return libs, objs + +incdir = run_llvm_config(['--includedir']) +libdir = run_llvm_config(['--libdir']) +ldflags = run_llvm_config(['--ldflags']) +macros = [('__STDC_CONSTANT_MACROS', None), + ('__STDC_LIMIT_MACROS', None)] + +extra_link_args = ldflags.split() + +libs_core, objs_core = get_libs_and_objs(['core', 'analysis', 'scalaropts', + 'executionengine', 'jit', 'native', + 'interpreter', 'bitreader', + 'bitwriter', 'instrumentation', 'ipa', + 'ipo', 'transformutils', 'asmparser', + 'linker', 'support', 'vectorize']) + +ext_modules = [Extension(name='_api', + sources=['api.cpp'], + include_dirs = ['include', incdir], + library_dirs = [libdir], + libraries = libs_core, + define_macros = macros, + extra_objects = objs_core, + extra_link_args = extra_link_args), + Extension(name='_capsule', + sources=['capsule.cpp'], + include_dirs = ['include'],), + ] + + +setup(name = 'llvmpy2', + description = 'Python bindings for LLVM', + author = 'Siu Kwan Lam', + ext_modules = ext_modules, + license = "BSD") diff --git a/newbinding/test.py b/newbinding/test.py new file mode 100644 index 0000000..bed9e1a --- /dev/null +++ b/newbinding/test.py @@ -0,0 +1,32 @@ +import _api + +context = _api.getGlobalContext() +modname = "modname" +module = _api.Module.new(modname, context) +assert modname == _api.Module.getModuleIdentifier(module) +modname2 = "newmodname" +_api.Module.setModuleIdentifier(module, modname2) +assert modname2 == _api.Module.getModuleIdentifier(module) + +_api.Module.dump(module) + +_api.Module.delete(module) + +voidty = _api.Type.getVoidTy(context) +assert _api.Type.isVoidTy(voidty) +assert not _api.Type.isLabelTy(voidty) + +int21ty = _api.Type.getIntNTy(context, 21) +assert _api.Type.isIntegerTy(int21ty) +assert _api.Type.isIntegerTy(int21ty, 21) +_api.Type.dump(int21ty) + +halfty = _api.Type.getHalfTy(context) +assert _api.Type.isHalfTy(halfty) +_api.Type.dump(halfty) + +fnty = _api.FunctionType.get(halfty, False) +_api.Type.dump(fnty) + + + diff --git a/newbinding/test2.py b/newbinding/test2.py new file mode 100644 index 0000000..25a59d7 --- /dev/null +++ b/newbinding/test2.py @@ -0,0 +1,20 @@ +import api +#api.enable_capsule_dtor_debug(True) +context = api.getGlobalContext() + +m = api.Module.new("modname", context) +print m.getModuleIdentifier() +m.setModuleIdentifier('modname2') +print m.getModuleIdentifier() +m.dump() +os = api.raw_svector_ostream_helper.create() +m.print_(os, None) +print os.str() + +int1ty = api.Type.getInt1Ty(context) +int1ty.dump() + +print int1ty.isIntegerTy(1) + + + From 47771d8dbcd61d86c01dab07696e1238b7d64d9b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:13:41 -0600 Subject: [PATCH 025/338] Add README --- newbinding/README | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 newbinding/README diff --git a/newbinding/README b/newbinding/README new file mode 100644 index 0000000..2bfabcd --- /dev/null +++ b/newbinding/README @@ -0,0 +1,5 @@ +# 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. From 5c1e8985a13f2ef4deb44015d74a856ec7977d29 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:16:15 -0600 Subject: [PATCH 026/338] Delete empty unused Makefile --- newbinding/binding/Makefile | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 newbinding/binding/Makefile diff --git a/newbinding/binding/Makefile b/newbinding/binding/Makefile deleted file mode 100644 index e69de29..0000000 From d0935fe53383a3916d3fdd62aeb448c0339726af Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:41:22 -0600 Subject: [PATCH 027/338] Organize code layout --- newbinding/Makefile | 10 ++++---- newbinding/{binding => }/binding.py | 0 newbinding/{binding => }/gen.py | 23 ++++++++++++++----- .../AssemblyAnnotationWriter.py | 0 newbinding/{binding => src}/DerivedTypes.py | 0 newbinding/{binding => src}/LLVMContext.py | 0 newbinding/{binding => src}/Module.py | 0 newbinding/{binding => src}/StringRef.py | 0 newbinding/{binding => src}/Type.py | 0 newbinding/{binding => src}/_Debug.py | 0 newbinding/src/__init__.py | 0 newbinding/{binding => src}/namespace.py | 0 newbinding/{binding => src}/raw_ostream.py | 0 newbinding/{binding => }/utils.py | 0 14 files changed, 22 insertions(+), 11 deletions(-) rename newbinding/{binding => }/binding.py (100%) rename newbinding/{binding => }/gen.py (92%) rename newbinding/{binding => src}/AssemblyAnnotationWriter.py (100%) rename newbinding/{binding => src}/DerivedTypes.py (100%) rename newbinding/{binding => src}/LLVMContext.py (100%) rename newbinding/{binding => src}/Module.py (100%) rename newbinding/{binding => src}/StringRef.py (100%) rename newbinding/{binding => src}/Type.py (100%) rename newbinding/{binding => src}/_Debug.py (100%) create mode 100644 newbinding/src/__init__.py rename newbinding/{binding => src}/namespace.py (100%) rename newbinding/{binding => src}/raw_ostream.py (100%) rename newbinding/{binding => }/utils.py (100%) diff --git a/newbinding/Makefile b/newbinding/Makefile index ba902e3..0db1f29 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -5,14 +5,14 @@ all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp python setup.py build_ext --inplace - -api.cpp api.py: binding/*.py include/llvm_binding/*.h - cd binding; python gen.py api $(PYMODS) - mv binding/api.cpp api.cpp - mv binding/api.py api.py +api.cpp api.py: src/*.py include/llvm_binding/*.h + python gen.py api src $(PYMODS) clean: rm -f _api.so _capsule.so rm -f api.cpp api.py +check: _api.so api.py + python test2.py +@PHONY: all clean check diff --git a/newbinding/binding/binding.py b/newbinding/binding.py similarity index 100% rename from newbinding/binding/binding.py rename to newbinding/binding.py diff --git a/newbinding/binding/gen.py b/newbinding/gen.py similarity index 92% rename from newbinding/binding/gen.py rename to newbinding/gen.py index f662979..c2126ab 100644 --- a/newbinding/binding/gen.py +++ b/newbinding/gen.py @@ -136,8 +136,7 @@ class Context(object): println('') - def add_module(self, modname): - module = __import__(modname) + def add_module(self, module): allsyms = [(k, v) for k, v in vars(module).items() if isinstance(v, Binding)] symtab = sorted(allsyms, key=lambda x: x[1].rank) @@ -190,17 +189,29 @@ def wrap_println(f): return println if __name__ == '__main__': + outputfilename = sys.argv[1] + srcdir = sys.argv[2] + modnames = sys.argv[3:] + + modules = [] + for m in modnames: + path = '%s.%s' % (srcdir, m) + print path + module = __import__(path) + for token in path.split('.')[1:]: + module = getattr(module, token) + modules.append(module) context = Context() - for mod in sys.argv[2:]: + + for mod in modules: context.add_module(mod) - filename = sys.argv[1] - with open('%s.cpp' % filename, 'w') as outfile: + with open('%s.cpp' % outputfilename, 'w') as outfile: println = wrap_println(outfile) populate_headers(println) context.generate_cpp(println) - with open('%s.py' % filename, 'w') as outfile: + with open('%s.py' % outputfilename, 'w') as outfile: println = wrap_println(outfile) context.generate_py(println) diff --git a/newbinding/binding/AssemblyAnnotationWriter.py b/newbinding/src/AssemblyAnnotationWriter.py similarity index 100% rename from newbinding/binding/AssemblyAnnotationWriter.py rename to newbinding/src/AssemblyAnnotationWriter.py diff --git a/newbinding/binding/DerivedTypes.py b/newbinding/src/DerivedTypes.py similarity index 100% rename from newbinding/binding/DerivedTypes.py rename to newbinding/src/DerivedTypes.py diff --git a/newbinding/binding/LLVMContext.py b/newbinding/src/LLVMContext.py similarity index 100% rename from newbinding/binding/LLVMContext.py rename to newbinding/src/LLVMContext.py diff --git a/newbinding/binding/Module.py b/newbinding/src/Module.py similarity index 100% rename from newbinding/binding/Module.py rename to newbinding/src/Module.py diff --git a/newbinding/binding/StringRef.py b/newbinding/src/StringRef.py similarity index 100% rename from newbinding/binding/StringRef.py rename to newbinding/src/StringRef.py diff --git a/newbinding/binding/Type.py b/newbinding/src/Type.py similarity index 100% rename from newbinding/binding/Type.py rename to newbinding/src/Type.py diff --git a/newbinding/binding/_Debug.py b/newbinding/src/_Debug.py similarity index 100% rename from newbinding/binding/_Debug.py rename to newbinding/src/_Debug.py diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newbinding/binding/namespace.py b/newbinding/src/namespace.py similarity index 100% rename from newbinding/binding/namespace.py rename to newbinding/src/namespace.py diff --git a/newbinding/binding/raw_ostream.py b/newbinding/src/raw_ostream.py similarity index 100% rename from newbinding/binding/raw_ostream.py rename to newbinding/src/raw_ostream.py diff --git a/newbinding/binding/utils.py b/newbinding/utils.py similarity index 100% rename from newbinding/binding/utils.py rename to newbinding/utils.py From 36df29ba71df48beb838e60d9a5a2616fb3a8fb3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 11:49:41 -0600 Subject: [PATCH 028/338] Add enum support --- newbinding/binding.py | 46 +++++++++++++++++++++++++++++++++++++++++++ newbinding/gen.py | 8 ++++++++ 2 files changed, 54 insertions(+) diff --git a/newbinding/binding.py b/newbinding/binding.py index 1230813..fa9ce90 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -222,6 +222,50 @@ class Wrapper(object): println('if (!%(out)s) return NULL;' % locals()) return out +class Enum(Binding): + def __init__(self, ns, *values): + super(Enum, self).__init__() + self.values = values + self.ns = ns + self.name = None + + def compile(self, name, println): + self.name = self.name or name + + @property + def fullname(self): + return '::'.join([self.ns, self.name]) + +class ClassEnum(Enum): + def __init__(self, cls, *values): + super(ClassEnum, self).__init__(None, *values) + self.cls = cls + self.cls.enums.append(self) + + def compile(self, name, println): + self.ns = self.cls.fullname + super(ClassEnum, self).compile(name, println) + + def wrap(self, println, var): + println2 = indent_println(println) + ret = declare(println, 'PyObject*', NULL) + println('switch(%s) { ' % var) + for v in self.values: + println('case %s::%s:' % (self.ns, v)) + println2('%(ret)s = PyString_FromString("%(v)s");' % locals()) + println2('break;') + else: + println('default:') + println2('PyErr_SetString(PyExc_TypeError, "Invalid enum: %s");' % + v) + println2('return NULL;') + println('}') + return ret + + def unwrap(self, println, var): + pass + + class Class(Binding): def __init__(self, ns): super(Class, self).__init__() @@ -229,6 +273,8 @@ class Class(Binding): self.Ref = Ref(self) self.Pointer = Pointer(self) self.Subclass = lambda: Subclass(self) + self.Enum = lambda *v: ClassEnum(self, *v) + self.enums = [] self.ns = ns self.methods = [] self.name = None diff --git a/newbinding/gen.py b/newbinding/gen.py index c2126ab..87c0697 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -115,6 +115,14 @@ class Context(object): println('pass') else: mod = cls.name + # generate class enums + for enum in cls.enums: + println('class %s:' % enum.name) + println2 = indent_println(println) + for v in enum.values: + println2('%(v)s = "%(v)s"' % locals()) + println('') + # generate class methods for method in cls.methods: name = method.name if isinstance(method, StaticMethod): From e39e1c72057981f2cf3bbc42354e3f85e7592c62 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 11:50:06 -0600 Subject: [PATCH 029/338] Add logging --- newbinding/binding.py | 3 +++ newbinding/gen.py | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index fa9ce90..ab0e1c0 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,5 +1,8 @@ +import logging from utils import * +logger = logging.getLogger(__name__) + _py2capi_fmtmap = { str: 's#', } diff --git a/newbinding/gen.py b/newbinding/gen.py index 87c0697..81a4815 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -1,8 +1,11 @@ -import sys +import sys, logging from binding import * from utils import * from cStringIO import StringIO +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + extension_entry = ''' extern "C" { @@ -143,7 +146,6 @@ class Context(object): println2('return capsule.wrap(ret)') println('') - def add_module(self, module): allsyms = [(k, v) for k, v in vars(module).items() if isinstance(v, Binding)] @@ -159,6 +161,7 @@ class Context(object): def println_to_def(s): buf.write(s) buf.write('\n') + logger.info('compiling %s', k) v.compile(k, println_to_def) self.definitions.append(buf.getvalue()) buf.close() @@ -200,11 +203,11 @@ if __name__ == '__main__': outputfilename = sys.argv[1] srcdir = sys.argv[2] modnames = sys.argv[3:] - + modules = [] for m in modnames: path = '%s.%s' % (srcdir, m) - print path + logger.info("import module %s", path) module = __import__(path) for token in path.split('.')[1:]: module = getattr(module, token) From 089c825b0cdd89384b639f1f1b233f8aab59074d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 11:50:39 -0600 Subject: [PATCH 030/338] Add cleantemp rule in Makefile --- newbinding/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index 0db1f29..77a012b 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -8,9 +8,13 @@ _api.so _capsule.so: api.cpp capsule.cpp api.cpp api.py: src/*.py include/llvm_binding/*.h python gen.py api src $(PYMODS) -clean: +clean: cleantemp rm -f _api.so _capsule.so + +cleantemp: rm -f api.cpp api.py + rm -f src/*.pyc + check: _api.so api.py python test2.py From f88036274a3d9e7de2a7cbcd3e064f16e847962e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:31:13 -0600 Subject: [PATCH 031/338] Fix and rewrite the memory management for capsules. --- newbinding/Makefile | 3 +- newbinding/binding.py | 4 +- newbinding/capsule.cpp | 29 -------------- newbinding/capsule.py | 39 ++++++++++++++++--- .../include/llvm_binding/capsule_context.h | 39 +++---------------- newbinding/src/_Debug.py | 3 -- newbinding/test2.py | 26 ++++++++++++- 7 files changed, 69 insertions(+), 74 deletions(-) delete mode 100644 newbinding/src/_Debug.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 77a012b..49e244b 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,4 +1,5 @@ -PYMODS = _Debug raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module +PYTHON = python +PYMODS = raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module all: _api.so _capsule.so diff --git a/newbinding/binding.py b/newbinding/binding.py index ab0e1c0..63fcf9e 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -45,13 +45,15 @@ def mangle(name): name = name.replace('_', '__').replace(' ', '_') return name.replace('::', '_').rstrip('*&') -def pycapsule_new(println, ptr, name, clsname, dtor='capsule_destructor'): +def pycapsule_new(println, ptr, name, clsname, dtor=NULL): # build capsule name_soften = mangle(name) var = new_symbol('pycap_%s' % name_soften) fmt = 'PyObject* %(var)s = PyCapsule_New(%(ptr)s, "%(name)s", %(dtor)s);' println(fmt % locals()) + println('if (!%(var)s) return NULL;' % locals()) + # build context fmt = 'new CapsuleContext("%(clsname)s")' context = declare(println, 'CapsuleContext*', fmt % locals()) diff --git a/newbinding/capsule.cpp b/newbinding/capsule.cpp index 40d135b..e7e4932 100644 --- a/newbinding/capsule.cpp +++ b/newbinding/capsule.cpp @@ -66,34 +66,6 @@ PyObject* getClassName(PyObject* self, PyObject* args) { } } -static -PyObject* setDestructor(PyObject* self, PyObject* args) { - PyObject* cap; - PyObject* callable; - if (!PyArg_ParseTuple(args, "OO", &cap, &callable)) { - return NULL; - } - PyObject* arglist = Py_BuildValue("(O)", cap); - CapsuleContext* context = getContext(self, arglist); - Py_DECREF(arglist); - if (!context) { - return NULL; - } else { - void* ptr; - if (callable != Py_None) { - if (PyCallable_Check(callable)) { - ptr = callable; - } else { - PyErr_SetString(PyExc_TypeError, "Argument is not callable."); - return NULL; - } - } else { - ptr = NULL; - } - context->destructor = (Destructor_Fn)ptr; - } - Py_RETURN_NONE; -} static PyMethodDef core_methods[] = { #define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS , NULL } @@ -101,7 +73,6 @@ static PyMethodDef core_methods[] = { declmethod(getPointer), declmethod(check), declmethod(getClassName), - declmethod(setDestructor), { NULL }, #undef declmethod }; diff --git a/newbinding/capsule.py b/newbinding/capsule.py index b82154b..509b4c4 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -1,18 +1,44 @@ import _capsule -from weakref import WeakValueDictionary +from weakref import WeakValueDictionary, ref +import logging +logger = logging.getLogger(__name__) + +def set_debug(enabled): + ''' + Side-effect: configure logger with it is not configured. + ''' + if enabled: + # If no handlers are configured for the root logger, + # build a default handler for debugging. + # Can we do better? + if not logger.root.handlers: + logging.basicConfig() + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.WARNING) + + +class WeakRef(ref): + __slots__ = 'capsule', 'dtor' _pyclasses = {} _addr2obj = WeakValueDictionary() - +_owners = {} def _sentry(ptr): assert _capsule.check(ptr) - def classof(cap): cls = _capsule.getClassName(cap) return _pyclasses[cls] +def _capsule_destructor(weak): + cap = weak.capsule + addr = _capsule.getPointer(cap) + cls = _capsule.getClassName(cap) + logger.debug("destroy pointer %s to %s", addr, cls) + weak.dtor(cap) + del _owners[addr] def wrap(cap): '''Wrap a PyCapsule with the corresponding Wrapper class. @@ -29,9 +55,12 @@ def wrap(cap): cls = classof(cap) obj = cls(cap) _addr2obj[addr] = obj # cache object by address - # set destructor if cls.delete is defined + # set ownership if *cls* defines *_delete_* if hasattr(cls, '_delete_'): - _capsule.setDestructor(cap, cls._delete_) + weak = WeakRef(obj, _capsule_destructor) + _owners[addr] = weak + weak.capsule = cap + weak.dtor = cls._delete_ else: assert classof(obj._ptr) is classof(cap) # Unset destructor for capsules that are repeated diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index bb45566..dacfc89 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -1,48 +1,19 @@ #ifndef LLVMPY_CAPSULE_CONTEXT_H_ #define LLVMPY_CAPSULE_CONTEXT_H_ + #include #include typedef PyObject* Destructor_Fn; -static bool CapsuleContextDebug = false; - struct CapsuleContext { const char* className; - Destructor_Fn destructor; - - CapsuleContext(const char* cn, Destructor_Fn dtor=NULL) - : className(cn), destructor(dtor) { } + + CapsuleContext(const char* cn) + : className(cn) + { } }; -void capsule_destructor(PyObject* capsule){ - using std::cerr; - using std::endl; - CapsuleContext* context = (CapsuleContext*)PyCapsule_GetContext(capsule); - if (context->destructor) { - if (CapsuleContextDebug) { - cerr << clock() - << " == DEBUG ==" - << " destroy pointer: " - << context->className - << endl; - } - PyObject_CallMethodObjArgs(context->destructor, capsule, NULL); - } else { - if (CapsuleContextDebug) { - cerr << clock() - << " == DEBUG ==" - << " keep pointer alive: " - << context->className - << endl; - } - } - delete context; -} - -void enable_capsule_dtor_debug(bool enabled){ - CapsuleContextDebug = enabled; -} #endif //LLVMPY_CAPSULE_CONTEXT_H_ diff --git a/newbinding/src/_Debug.py b/newbinding/src/_Debug.py deleted file mode 100644 index be092f3..0000000 --- a/newbinding/src/_Debug.py +++ /dev/null @@ -1,3 +0,0 @@ -from binding import * - -enable_capsule_dtor_debug = Function('', Void, Bool.From(bool)) diff --git a/newbinding/test2.py b/newbinding/test2.py index 25a59d7..872dfc0 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,20 +1,44 @@ import api -#api.enable_capsule_dtor_debug(True) +#api.capsule.set_debug(True) context = api.getGlobalContext() +def test(): + print '*' * 80 + m = api.Module.new("modname", context) + print m.getModuleIdentifier() + m.setModuleIdentifier('modname2') + print m.getModuleIdentifier() + print 'endianness', m.getEndianness() + assert m.getEndianness() == api.Module.Endianness.AnyEndianness + print 'pointer-size', m.getPointerSize() + assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize + m.dump() + m = api.Module.new("modname", context) print m.getModuleIdentifier() m.setModuleIdentifier('modname2') print m.getModuleIdentifier() +print 'endianness', m.getEndianness() +assert m.getEndianness() == api.Module.Endianness.AnyEndianness +print 'pointer-size', m.getPointerSize() +assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() + + + os = api.raw_svector_ostream_helper.create() m.print_(os, None) print os.str() + int1ty = api.Type.getInt1Ty(context) int1ty.dump() print int1ty.isIntegerTy(1) +fnty = api.FunctionType.get(int1ty, False) +os2 = api.raw_svector_ostream_helper.create() +fnty.print_(os2) +print os2.str() From bd550e3c0ed70dfe4c55864c3ea3b95a4c250d24 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:33:23 -0600 Subject: [PATCH 032/338] Implement StaticMultiMethod --- newbinding/binding.py | 52 ++++++++++++++++++++++++++++++++++ newbinding/gen.py | 3 +- newbinding/src/DerivedTypes.py | 6 +++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 63fcf9e..de68b55 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -314,6 +314,11 @@ class Class(Binding): mm = MultiMethod(self, signatures) self.methods.append(mm) return mm + + def staticmultimethod(self, *signatures): + smm = StaticMultiMethod(self, signatures) + self.methods.append(smm) + return smm def compile(self, name, println): # set name @@ -518,6 +523,53 @@ class StaticMethod(Method): println('%s;' % call) return_none(println) +class StaticMultiMethod(Binding): + '''Can only differs by the number of arguments. + ''' + def __init__(self, cls, signatures): + super(StaticMultiMethod, self).__init__() + nargs = set() + for sig in signatures: + n = len(sig) + if n in nargs: + raise TypeError("StaticMultiMethod only supports overloaded " + "version with different number of arguments") + nargs.add(n) + self.cls = cls + self.signatures = signatures + self.name = None + + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + mangled = self.mangled_name + println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) + println('{') + println2 = indent_println(println) + nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') + for sig in self.signatures: + expect = len(sig) - 1 + println2('if (%(nargs)s == %(expect)d) {' % locals()) + method = StaticMethod(self.cls, sig[0], *sig[1:]) + method.name = self.name + method.compile_body(indent_println(println2)) + println2('}') + println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') + println2('return NULL;') + println('}') + + @property + def fullname(self): + return '::'.join([self.cls.fullname, self.name]) + + @property + def mangled_name(self): + return mangle(self.fullname) + class Constructor(StaticMethod): def compile_body(self, println): args = parse_arguments(println, 'args', *self.args) diff --git a/newbinding/gen.py b/newbinding/gen.py index 81a4815..4081f01 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -128,7 +128,8 @@ class Context(object): # generate class methods for method in cls.methods: name = method.name - if isinstance(method, StaticMethod): + if(isinstance(method, StaticMethod) or + isinstance(method, StaticMultiMethod)): println('@staticmethod') println('def %(name)s(*args):' % locals()) println2 = indent_println(println) diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index 10d5fbf..edf4297 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -6,7 +6,11 @@ from Type import Type FunctionType = Type.Subclass() FunctionType.include.add('llvm/DerivedTypes.h') -get = FunctionType.staticmethod(FunctionType.Pointer, Type.Pointer, Bool.From(bool)) +get = FunctionType.staticmultimethod([FunctionType.Pointer, + Type.Pointer, Bool.From(bool)],) +# (FunctionType.Pointer, +# Type.Pointer, )]) + isVarArg = FunctionType.method(Bool.To(bool)) getReturnType = FunctionType.method(Type.Pointer) getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int)) From 3e89a97fdb22e97c529f55380ca632dd53f18fb0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:33:50 -0600 Subject: [PATCH 033/338] Improve Makefile --- newbinding/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index 49e244b..3996d8b 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -4,10 +4,10 @@ PYMODS = raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationW all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp - python setup.py build_ext --inplace + $(PYTHON) setup.py build_ext --inplace api.cpp api.py: src/*.py include/llvm_binding/*.h - python gen.py api src $(PYMODS) + $(PYTHON) gen.py api src $(PYMODS) clean: cleantemp rm -f _api.so _capsule.so @@ -18,6 +18,6 @@ cleantemp: check: _api.so api.py - python test2.py + $(PYTHON) test2.py @PHONY: all clean check From f95b691b61520f8f0d6a7be12ca112ab8bf6e841 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:35:05 -0600 Subject: [PATCH 034/338] Expand Module binding --- newbinding/src/Module.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index a458401..5923859 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -5,21 +5,42 @@ from StringRef import StringRef from raw_ostream import raw_svector_ostream_helper from AssemblyAnnotationWriter import AssemblyAnnotationWriter +# class Module Module = llvm.Class() Module.include.add("llvm/Module.h") +# Enumerators +Endianness = Module.Enum('AnyEndianness', 'LittleEndian', 'BigEndian') +PointerSize = Module.Enum('AnyPointerSize', 'Pointer32', 'Pointer64') + +# Constructors & Destructors new = Module.new(StringRef.From(str), LLVMContext.Ref) delete = Module.delete() + +# Module Level Accessor getModuleIdentifier = Module.method(ConstStdString.To(str)) +getDataLayout = Module.method(ConstStdString.To(str)) +getTargetTriple = Module.method(ConstStdString.To(str)) +getEndianness = Module.method(Endianness) +getPointerSize = Module.method(PointerSize) +getContext = Module.method(LLVMContext.Ref) +getModuleInlineAsm = Module.method(ConstStdString.To(str)) + +# Module Level Mutators setModuleIdentifier = Module.method(Void, StringRef.From(str)) setDataLayout = Module.method(Void, StringRef.From(str)) setTargetTriple = Module.method(Void, StringRef.From(str)) setModuleInlineAsm = Module.method(Void, StringRef.From(str)) appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) -getContext = Module.method(LLVMContext.Ref) + +# Function Accessors +#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) + + + +# Utilities dump = Module.method(Void) print_ = Module.method(Void, raw_svector_ostream_helper.Ref, AssemblyAnnotationWriter.Pointer) print_.realname = 'print' -#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) - +dropAllReferences = Module.method(Void) From ce103975b853d5fc53246153f617a392a6a79a8d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:40:44 -0600 Subject: [PATCH 035/338] Clean up test --- newbinding/test2.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/newbinding/test2.py b/newbinding/test2.py index 872dfc0..0d64716 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -2,17 +2,6 @@ import api #api.capsule.set_debug(True) context = api.getGlobalContext() -def test(): - print '*' * 80 - m = api.Module.new("modname", context) - print m.getModuleIdentifier() - m.setModuleIdentifier('modname2') - print m.getModuleIdentifier() - print 'endianness', m.getEndianness() - assert m.getEndianness() == api.Module.Endianness.AnyEndianness - print 'pointer-size', m.getPointerSize() - assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize - m.dump() m = api.Module.new("modname", context) print m.getModuleIdentifier() From 6b88ffbaed4757f95814aa650c7297bd8e6d8f6a Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 21:23:20 -0600 Subject: [PATCH 036/338] Add custom binding to SmallVector --- newbinding/Makefile | 4 +++- newbinding/binding.py | 10 ++++++++++ newbinding/include/llvm_binding/extra.h | 24 +++++++++++++++++++++++- newbinding/src/DerivedTypes.py | 11 +++++++---- newbinding/test2.py | 10 ++++++++-- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index 3996d8b..6ae50be 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,5 +1,7 @@ PYTHON = python -PYMODS = raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module + +PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef +PYMODS += LLVMContext AssemblyAnnotationWriter Module all: _api.so _capsule.so diff --git a/newbinding/binding.py b/newbinding/binding.py index de68b55..adeb284 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -190,6 +190,16 @@ Bool = BuiltinType('bool') Unsigned = BuiltinType('unsigned') ConstStdString = BuiltinType('const std::string') +class PyObjectImpl(object): + name = 'PyObject*' + fullname = name + format = 'O' + + def unwrap(self, println, var): + return var + +PyObject = PyObjectImpl() + class Unwrapper(object): def __init__(self, cls, pytype): self.cls = cls diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index a7388a2..e78f0e2 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -4,6 +4,8 @@ namespace llvm{ +class Type; //forward declaration + class raw_svector_ostream_helper: public raw_svector_ostream { SmallVectorImpl *SV; public: @@ -30,5 +32,25 @@ private: void operator = (const raw_svector_ostream_helper&); }; -} + +class SmallVector_Type : public SmallVector { +public: + static + SmallVector_Type* fromPySequence(PyObject* obj) { + SmallVector_Type* SV = new SmallVector_Type; + Py_ssize_t sz = PySequence_Size(obj); + for (Py_ssize_t i = 0; i < sz; ++i) { + PyObject* item = PySequence_GetItem(obj, i); + PyObject* cap = PyObject_GetAttrString(item, "_ptr"); + Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); + SV->push_back(type); + Py_XDECREF(cap); + Py_XDECREF(item); + } + return SV; + } +}; + + +} // end namespace llvm diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index edf4297..d9dbb53 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -2,14 +2,17 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from Type import Type +from SmallVector import SmallVector_Type FunctionType = Type.Subclass() FunctionType.include.add('llvm/DerivedTypes.h') -get = FunctionType.staticmultimethod([FunctionType.Pointer, - Type.Pointer, Bool.From(bool)],) -# (FunctionType.Pointer, -# Type.Pointer, )]) +_get_signatures = [(FunctionType.Pointer, + Type.Pointer, Bool.From(bool)), + (FunctionType.Pointer, + Type.Pointer, SmallVector_Type.Ref, Bool.From(bool))] + +get = FunctionType.staticmultimethod(*_get_signatures) isVarArg = FunctionType.method(Bool.To(bool)) getReturnType = FunctionType.method(Type.Pointer) diff --git a/newbinding/test2.py b/newbinding/test2.py index 0d64716..6cb8a06 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,5 +1,5 @@ import api -#api.capsule.set_debug(True) +api.capsule.set_debug(True) context = api.getGlobalContext() @@ -14,7 +14,6 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() - os = api.raw_svector_ostream_helper.create() m.print_(os, None) print os.str() @@ -26,6 +25,13 @@ int1ty.dump() print int1ty.isIntegerTy(1) fnty = api.FunctionType.get(int1ty, False) +fnty.dump() +print + +types = [int1ty, api.Type.getIntNTy(context, 21)] +sv = api.SmallVector_Type.fromPySequence(types) + +fnty = api.FunctionType.get(int1ty, sv, False) os2 = api.raw_svector_ostream_helper.create() fnty.print_(os2) From 6afab6268cca2ff0bdd3c689a22e98dfc1395cb9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 21:24:14 -0600 Subject: [PATCH 037/338] Refactor mangle --- newbinding/binding.py | 17 +++++++++++++++-- newbinding/capsule.py | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index adeb284..57d7c7d 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,4 +1,5 @@ import logging +import re from utils import * logger = logging.getLogger(__name__) @@ -41,9 +42,21 @@ def parse_arguments(println, var, *args): return unwrapped +_re_mangle_pattern = re.compile(r'[ _<>\*&]') + def mangle(name): - name = name.replace('_', '__').replace(' ', '_') - return name.replace('::', '_').rstrip('*&') + def repl(m): + s = m.group(0) + if s in '<>*&': + return '' + elif s in ' ': + return '_' + elif s in '_': + return '__' + else: + assert False + name = _re_mangle_pattern.sub(repl, name) + return name.replace('::', '_') def pycapsule_new(println, ptr, name, clsname, dtor=NULL): # build capsule diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 509b4c4..e4cd4fa 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -36,7 +36,7 @@ def _capsule_destructor(weak): cap = weak.capsule addr = _capsule.getPointer(cap) cls = _capsule.getClassName(cap) - logger.debug("destroy pointer %s to %s", addr, cls) + logger.debug("destroy pointer 0x%08X to %s", addr, cls) weak.dtor(cap) del _owners[addr] From ef4c0d3be395a3c756d414667b4f07ec4a3a48e1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 11:18:06 -0600 Subject: [PATCH 038/338] Rename extra.h to llvm_extra.h --- newbinding/gen.py | 10 +++++----- .../include/llvm_binding/{extra.h => llvm_extra.h} | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) rename newbinding/include/llvm_binding/{extra.h => llvm_extra.h} (98%) diff --git a/newbinding/gen.py b/newbinding/gen.py index 4081f01..bfde891 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -186,11 +186,11 @@ class Context(object): def populate_headers(println): includes = [ - 'llvm_binding/conversion.h', - 'llvm_binding/binding.h', - 'llvm_binding/extra.h', - 'llvm_binding/capsule_context.h', - ] + 'llvm_binding/conversion.h', + 'llvm_binding/binding.h', + 'llvm_binding/llvm_extra.h', + 'llvm_binding/capsule_context.h', + ] for inc in includes: println('#include "%s"' % inc) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/llvm_extra.h similarity index 98% rename from newbinding/include/llvm_binding/extra.h rename to newbinding/include/llvm_binding/llvm_extra.h index e78f0e2..620c3e2 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/llvm_extra.h @@ -2,10 +2,10 @@ #include #include -namespace llvm{ +namespace llvm{ class Type; //forward declaration - + class raw_svector_ostream_helper: public raw_svector_ostream { SmallVectorImpl *SV; public: @@ -51,6 +51,6 @@ public: } }; - + } // end namespace llvm From 6a861d82e6a46fca38565946dac1e604c8bcd093 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 14:50:17 -0600 Subject: [PATCH 039/338] Implement SmallVector_Type, pycapsule_new --- newbinding/binding.py | 14 ++--------- newbinding/gen.py | 21 ++++++++++++++++- newbinding/include/llvm_binding/binding.h | 9 +++++--- .../include/llvm_binding/capsule_context.h | 22 ++++++++++++++++++ newbinding/include/llvm_binding/extra.h | 23 +++++++++++++++++++ newbinding/include/llvm_binding/llvm_extra.h | 20 +--------------- newbinding/src/SmallVector.py | 5 ++++ newbinding/test2.py | 7 +++--- 8 files changed, 82 insertions(+), 39 deletions(-) create mode 100644 newbinding/include/llvm_binding/extra.h create mode 100644 newbinding/src/SmallVector.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 57d7c7d..c9de593 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -58,23 +58,13 @@ def mangle(name): name = _re_mangle_pattern.sub(repl, name) return name.replace('::', '_') -def pycapsule_new(println, ptr, name, clsname, dtor=NULL): +def pycapsule_new(println, ptr, name, clsname): # build capsule name_soften = mangle(name) var = new_symbol('pycap_%s' % name_soften) - fmt = 'PyObject* %(var)s = PyCapsule_New(%(ptr)s, "%(name)s", %(dtor)s);' + fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");' println(fmt % locals()) - println('if (!%(var)s) return NULL;' % locals()) - - # build context - fmt = 'new CapsuleContext("%(clsname)s")' - context = declare(println, 'CapsuleContext*', fmt % locals()) - - fmt = 'PyCapsule_SetContext(%(var)s, (void*)%(context)s)' - err = declare(println, 'int', fmt % locals()) - - println('if (%(err)s) return NULL;' % locals()) return var diff --git a/newbinding/gen.py b/newbinding/gen.py index bfde891..d73b29a 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -81,7 +81,8 @@ class Context(object): for name, cls in self.classes.items(): table = cls.mangled_name println('{ "%(name)s", %(table)s },' % locals()) - println('{ NULL },') + println('{ "extra", extra_methodtable },') + println('{ NULL }') println('};') println('') @@ -92,6 +93,23 @@ class Context(object): def generate_py(self, println): println('import _api, capsule') println('') + # wraps all extras + extra_wrapper = ''' +def _init_extra_wrapper(): + def wrap(callee): + def _wrapped(*args): + args = map(capsule.unwrap, args) + ret = callee(*args) + return capsule.wrap(ret) + return _wrapped + for k in dir(_api.extra): + v = getattr(_api.extra, k) + if not k.startswith('__') and callable(v): + globals()[k] = wrap(v) +_init_extra_wrapper() + ''' + println(extra_wrapper) + println('') # global function for name in self.functions: println('def %(name)s(*args):' % locals()) @@ -190,6 +208,7 @@ def populate_headers(println): 'llvm_binding/binding.h', 'llvm_binding/llvm_extra.h', 'llvm_binding/capsule_context.h', + 'llvm_binding/extra.h', # extra submodule to add ] for inc in includes: println('#include "%s"' % inc) diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h index f7bfde6..58a8ad0 100644 --- a/newbinding/include/llvm_binding/binding.h +++ b/newbinding/include/llvm_binding/binding.h @@ -51,10 +51,12 @@ create_python_submodule(PyObject* parent, const char* name, strcpy(fullname + len_parent + 1, name); PyObject* submod = create_python_module(fullname, methtable); delete [] fullname; - if (!submod) + if (!submod){ return NULL; - if( -1 == PyModule_AddObject(parent, name, submod) ) + } + if (-1 == PyModule_AddObject(parent, name, submod)) { return NULL; + } return submod; } @@ -70,4 +72,5 @@ int populate_submodules(PyObject* parent, SubModuleEntry* entries){ return 0; } return 1; -} \ No newline at end of file +} + diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index dacfc89..a4070dc 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -15,5 +15,27 @@ struct CapsuleContext { }; +static +PyObject* pycapsule_new(void* ptr, + const char* basename, + const char* classname=NULL) +{ + if (!classname) { + classname = basename; + } + PyObject* cap = PyCapsule_New(ptr, basename, NULL); + if (!cap) { + PyErr_SetString(PyExc_TypeError, "Error creating new PyCapsule"); + return NULL; + } + CapsuleContext* context = new CapsuleContext(classname); + if (PyCapsule_SetContext(cap, context)) { + return NULL; + } + return cap; +} + + + #endif //LLVMPY_CAPSULE_CONTEXT_H_ diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h new file mode 100644 index 0000000..23548ff --- /dev/null +++ b/newbinding/include/llvm_binding/extra.h @@ -0,0 +1,23 @@ +#include +#include + +static +PyObject* small_vector_from_types(PyObject* self, PyObject* args) { + using llvm::Type; + using llvm::SmallVector_Type; + SmallVector_Type* SV = new SmallVector_Type; + Py_ssize_t size = PyTuple_Size(args); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject* cap = PyTuple_GetItem(args, i); + Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); + SV->push_back(type); + } + return pycapsule_new(SV, "llvm::SmallVector_Type"); +} + +static PyMethodDef extra_methodtable[] = { +#define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } +method( small_vector_from_types ), +{ NULL } +#undef method +}; diff --git a/newbinding/include/llvm_binding/llvm_extra.h b/newbinding/include/llvm_binding/llvm_extra.h index 620c3e2..f920a47 100644 --- a/newbinding/include/llvm_binding/llvm_extra.h +++ b/newbinding/include/llvm_binding/llvm_extra.h @@ -32,25 +32,7 @@ private: void operator = (const raw_svector_ostream_helper&); }; +typedef SmallVector SmallVector_Type; -class SmallVector_Type : public SmallVector { -public: - static - SmallVector_Type* fromPySequence(PyObject* obj) { - SmallVector_Type* SV = new SmallVector_Type; - Py_ssize_t sz = PySequence_Size(obj); - for (Py_ssize_t i = 0; i < sz; ++i) { - PyObject* item = PySequence_GetItem(obj, i); - PyObject* cap = PyObject_GetAttrString(item, "_ptr"); - Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); - SV->push_back(type); - Py_XDECREF(cap); - Py_XDECREF(item); - } - return SV; - } -}; - - } // end namespace llvm diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py new file mode 100644 index 0000000..225c720 --- /dev/null +++ b/newbinding/src/SmallVector.py @@ -0,0 +1,5 @@ +from binding import * +from namespace import llvm + +SmallVector_Type = llvm.Class() +delete = SmallVector_Type.delete() diff --git a/newbinding/test2.py b/newbinding/test2.py index 6cb8a06..6f087c2 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,4 +1,5 @@ import api +import _capsule api.capsule.set_debug(True) context = api.getGlobalContext() @@ -26,12 +27,10 @@ print int1ty.isIntegerTy(1) fnty = api.FunctionType.get(int1ty, False) fnty.dump() -print types = [int1ty, api.Type.getIntNTy(context, 21)] -sv = api.SmallVector_Type.fromPySequence(types) - -fnty = api.FunctionType.get(int1ty, sv, False) +svt = api.small_vector_from_types(*types) +fnty = api.FunctionType.get(int1ty, svt, False) os2 = api.raw_svector_ostream_helper.create() fnty.print_(os2) From e9be14ca0e18fbe8fe4b79af20288db8f9dcad4f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:24:37 -0600 Subject: [PATCH 040/338] Refactor raw_svector_stream_helper --- newbinding/include/llvm_binding/extra.h | 26 +++++++++++++++++++++++-- newbinding/src/Module.py | 11 +++++------ newbinding/src/Type.py | 4 ++-- newbinding/src/raw_ostream.py | 9 ++------- newbinding/test2.py | 14 ++++++++----- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 23548ff..417c0f8 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,15 +1,36 @@ #include #include +#include static -PyObject* small_vector_from_types(PyObject* self, PyObject* args) { +PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { + using llvm::raw_svector_ostream_helper; + using llvm::raw_svector_ostream; + + if (!PyArg_ParseTuple(args, "")) { + return NULL; + } + raw_svector_ostream* RSOH = raw_svector_ostream_helper::create(); + return pycapsule_new(RSOH, "llvm::raw_ostream", + "llvm::raw_svector_ostream"); +} + +static +PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { using llvm::Type; using llvm::SmallVector_Type; + SmallVector_Type* SV = new SmallVector_Type; Py_ssize_t size = PyTuple_Size(args); for (Py_ssize_t i = 0; i < size; ++i) { PyObject* cap = PyTuple_GetItem(args, i); + if (!cap) { + return NULL; + } Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); + if (!type) { + return NULL; + } SV->push_back(type); } return pycapsule_new(SV, "llvm::SmallVector_Type"); @@ -17,7 +38,8 @@ PyObject* small_vector_from_types(PyObject* self, PyObject* args) { static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } -method( small_vector_from_types ), +method( make_raw_ostream_for_printing ), +method( make_small_vector_from_types ), { NULL } #undef method }; diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 5923859..67ac8b0 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -2,7 +2,9 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from StringRef import StringRef -from raw_ostream import raw_svector_ostream_helper +from Constant import Constant +from DerivedTypes import FunctionType +from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter # class Module @@ -34,13 +36,10 @@ setModuleInlineAsm = Module.method(Void, StringRef.From(str)) appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) # Function Accessors -#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) - - +getOrInsertFunction = Module.method(Constant.Pointer, StringRef.From(str), FunctionType.Pointer) # Utilities dump = Module.method(Void) -print_ = Module.method(Void, raw_svector_ostream_helper.Ref, - AssemblyAnnotationWriter.Pointer) +print_ = Module.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) print_.realname = 'print' dropAllReferences = Module.method(Void) diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 19f6d61..3703200 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -1,7 +1,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from raw_ostream import raw_svector_ostream_helper +from raw_ostream import raw_ostream Type = llvm.Class() Type.include.add('llvm/Type.h') @@ -13,7 +13,7 @@ PointerType = SequentialType.Subclass() getContext = Type.method(LLVMContext.Ref) dump = Type.method(Void) -print_ = Type.method(Void, raw_svector_ostream_helper.Ref) +print_ = Type.method(Void, raw_ostream.Ref) print_.realname = 'print' def type_checker(): diff --git a/newbinding/src/raw_ostream.py b/newbinding/src/raw_ostream.py index 0275db4..64e8046 100644 --- a/newbinding/src/raw_ostream.py +++ b/newbinding/src/raw_ostream.py @@ -5,13 +5,8 @@ from StringRef import StringRef raw_ostream = llvm.Class() raw_ostream.include.add("llvm/Support/raw_ostream.h") +delete = raw_ostream.delete() raw_svector_ostream = raw_ostream.Subclass() raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h") - -# extra class to help binding -raw_svector_ostream_helper = raw_svector_ostream.Subclass() -create = raw_svector_ostream_helper.staticmethod( - raw_svector_ostream_helper.Pointer) -delete = raw_svector_ostream_helper.delete() -str = raw_svector_ostream_helper.method(StringRef.To(str)) +str = raw_svector_ostream.method(StringRef.To(str)) diff --git a/newbinding/test2.py b/newbinding/test2.py index 6f087c2..b866f59 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -15,7 +15,7 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() -os = api.raw_svector_ostream_helper.create() +os = api.make_raw_ostream_for_printing() m.print_(os, None) print os.str() @@ -29,10 +29,14 @@ fnty = api.FunctionType.get(int1ty, False) fnty.dump() types = [int1ty, api.Type.getIntNTy(context, 21)] -svt = api.small_vector_from_types(*types) +svt = api.make_small_vector_from_types(*types) fnty = api.FunctionType.get(int1ty, svt, False) -os2 = api.raw_svector_ostream_helper.create() -fnty.print_(os2) -print os2.str() +os = api.make_raw_ostream_for_printing() +fnty.print_(os) +print os.str() +fn = m.getOrInsertFunction("foo", fnty) +os = api.make_raw_ostream_for_printing() +fn.print_(os, None) +print os.str() From e9e1f5703dd43b850735397bd005173a8ae9831d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:25:04 -0600 Subject: [PATCH 041/338] Add Value, User, Constant --- newbinding/Makefile | 2 ++ newbinding/src/Constant.py | 5 +++++ newbinding/src/User.py | 5 +++++ newbinding/src/Value.py | 8 ++++++++ 4 files changed, 20 insertions(+) create mode 100644 newbinding/src/Constant.py create mode 100644 newbinding/src/User.py create mode 100644 newbinding/src/Value.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 6ae50be..d07bc8f 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,8 +1,10 @@ PYTHON = python PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef +PYMODS += Value User Constant PYMODS += LLVMContext AssemblyAnnotationWriter Module + all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py new file mode 100644 index 0000000..24045bb --- /dev/null +++ b/newbinding/src/Constant.py @@ -0,0 +1,5 @@ +from binding import * +from namespace import llvm +from User import User + +Constant = User.Subclass() diff --git a/newbinding/src/User.py b/newbinding/src/User.py new file mode 100644 index 0000000..8753983 --- /dev/null +++ b/newbinding/src/User.py @@ -0,0 +1,5 @@ +from binding import * +from namespace import llvm +from Value import Value + +User = Value.Subclass() diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py new file mode 100644 index 0000000..ec7aa9a --- /dev/null +++ b/newbinding/src/Value.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm +from raw_ostream import raw_ostream +from AssemblyAnnotationWriter import AssemblyAnnotationWriter + +Value = llvm.Class() +print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) +print_.realname = 'print' From c247cf95271de8ca29d89ffcce3b94920e0599d0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:28:46 -0600 Subject: [PATCH 042/338] Update generator script so that order of modules does not matter. --- newbinding/Makefile | 4 ++-- newbinding/gen.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index d07bc8f..61227e5 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,9 +1,9 @@ PYTHON = python PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef -PYMODS += Value User Constant -PYMODS += LLVMContext AssemblyAnnotationWriter Module +PYMODS += LLVMContext AssemblyAnnotationWriter Module +PYMODS += Value User Constant all: _api.so _capsule.so diff --git a/newbinding/gen.py b/newbinding/gen.py index d73b29a..cee71f1 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -56,6 +56,7 @@ class Context(object): self.functions = {} self.classes = {} self.definitions = [] + self._pending_symbols = [] def generate_cpp(self, println): for i in self.includes: @@ -168,12 +169,15 @@ _init_extra_wrapper() def add_module(self, module): allsyms = [(k, v) for k, v in vars(module).items() if isinstance(v, Binding)] - symtab = sorted(allsyms, key=lambda x: x[1].rank) - # generate includes - for k, v in symtab: + for k, v in allsyms: self.includes |= v.include + self._pending_symbols.extend(allsyms) + + def materialize(self): + symtab = sorted(self._pending_symbols, key=lambda x: x[1].rank) + # compile everything for k, v in symtab: buf = StringIO() @@ -237,6 +241,7 @@ if __name__ == '__main__': for mod in modules: context.add_module(mod) + context.materialize() with open('%s.cpp' % outputfilename, 'w') as outfile: println = wrap_println(outfile) From a3da74c416579ebdc6bc1f1b72dd68c7811b53e0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:44:19 -0600 Subject: [PATCH 043/338] Expand Value class --- newbinding/src/Value.py | 18 +++++++++++++++++- newbinding/test2.py | 4 ++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index ec7aa9a..062ad43 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -2,7 +2,23 @@ from binding import * from namespace import llvm from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter - +from Type import Type +from LLVMContext import LLVMContext +from StringRef import StringRef +# Value = llvm.Class() + +dump = Value.method(Void) + print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) print_.realname = 'print' + +getType = Value.method(Type.Pointer) +getContext = Value.method(LLVMContext.Ref) + +hasName = Value.method(Bool.To(bool)) +# skip getValueName, setValueName +getName = Value.method(StringRef.To(str)) +setName = Value.method(Void, StringRef.From(str)) + +replaceAllUsesWith = Value.method(Void, Value.Pointer) \ No newline at end of file diff --git a/newbinding/test2.py b/newbinding/test2.py index b866f59..ac74594 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -40,3 +40,7 @@ fn = m.getOrInsertFunction("foo", fnty) os = api.make_raw_ostream_for_printing() fn.print_(os, None) print os.str() +assert fn.hasName() +assert 'foo' == fn.getName() +fn.setName('bar') +assert 'bar' == fn.getName() From eba88b32ba5fb5597e664f8662fd6dcce00f2dc9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 25 Jan 2013 12:29:31 -0600 Subject: [PATCH 044/338] Major refactoring --- newbinding/Makefile | 9 +- newbinding/binding.py | 924 +++++++----------- newbinding/codegen.py | 279 ++++++ newbinding/extra.py | 20 + newbinding/gen.py | 305 ++---- .../include/llvm_binding/auto_pyobject.h | 38 + newbinding/include/llvm_binding/conversion.h | 5 + newbinding/src/AssemblyAnnotationWriter.py | 5 +- newbinding/src/Constant.py | 4 +- newbinding/src/DerivedTypes.py | 22 +- newbinding/src/LLVMContext.py | 8 +- newbinding/src/Module.py | 60 +- newbinding/src/SmallVector.py | 5 +- newbinding/src/StringRef.py | 5 +- newbinding/src/Type.py | 169 ++-- newbinding/src/User.py | 5 +- newbinding/src/Value.py | 25 +- newbinding/src/__init__.py | 2 + newbinding/src/namespace.py | 1 - newbinding/src/raw_ostream.py | 17 +- newbinding/test2.py | 9 +- newbinding/utils.py | 6 - 22 files changed, 999 insertions(+), 924 deletions(-) create mode 100644 newbinding/codegen.py create mode 100644 newbinding/extra.py create mode 100644 newbinding/include/llvm_binding/auto_pyobject.h delete mode 100644 newbinding/utils.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 61227e5..735d4ff 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,17 +1,12 @@ PYTHON = python -PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef - -PYMODS += LLVMContext AssemblyAnnotationWriter Module -PYMODS += Value User Constant - all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp $(PYTHON) setup.py build_ext --inplace -api.cpp api.py: src/*.py include/llvm_binding/*.h - $(PYTHON) gen.py api src $(PYMODS) +api.cpp api.py: src/*.py include/llvm_binding/*.h gen.py binding.py + $(PYTHON) gen.py api src clean: cleantemp rm -f _api.so _capsule.so diff --git a/newbinding/binding.py b/newbinding/binding.py index c9de593..fc26d92 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,108 +1,352 @@ -import logging -import re -from utils import * +import functools +import codegen as cg -logger = logging.getLogger(__name__) +_rank = 0 +namespaces = {} -_py2capi_fmtmap = { - str: 's#', -} +class Namespace(object): + def __init__(self, name): + self.name = name + self.classes = [] + self.functions = [] + namespaces[name] = self -NULL = 'NULL' + def Class(self, *bases): + cls = Class(self, *bases) + self.classes.append(cls) + return cls -_symbols = set() + def Function(self, *args): + fn = Function(self, *args) + self.functions.append(fn) + return fn -def new_symbol(name): - if name in _symbols: - ct = 1 - orig = name - while name in _symbols: - name = '%s%d' % (orig, ct) - ct += 1 - _symbols.add(name) - return name + @property + def fullname(self): + return self.name -def parse_arguments(println, var, *args): - typecodes = [] - holders = [] - argvals = [] - for arg in args: - typecodes.append(arg.format) - val = declare(println, 'PyObject*') - argvals.append(val) - holders.append('&' + val) + def __str__(self): + return self.name - items = [var, '"%s"' % (''.join(typecodes))] + holders - println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items)) +class Type(object): + pass - # unwrap - unwrapped = [] - for arg, val in zip(args, argvals): - unwrapped.append(arg.unwrap(println, val)) +class BuiltinTypes(Type): + def __init__(self, name): + self.name = name - return unwrapped + @property + def fullname(self): + return self.name -_re_mangle_pattern = re.compile(r'[ _<>\*&]') + def wrap(self, writer, var): + return var -def mangle(name): - def repl(m): - s = m.group(0) - if s in '<>*&': - return '' - elif s in ' ': - return '_' - elif s in '_': - return '__' +Void = BuiltinTypes('void') +Unsigned = BuiltinTypes('unsigned') +Bool = BuiltinTypes('bool') +ConstStdString = BuiltinTypes('const std::string') + +class Class(Type): + format = 'O' + + def __init__(self, ns, *bases): + self.ns = ns + self.bases = bases + self._is_defined = False + self.methods = [] + self.enums = [] + self.includes = set() + + def __call__(self, defn): + assert not self._is_defined + self.name = defn.__name__ + for k, v in defn.__dict__.items(): + if isinstance(v, Method): + self.methods.append(v) + if isinstance(v, Constructor): + for sig in v.signatures: + sig[0] = ptr(self) + v.name = k + v.parent = self + elif isinstance(v, Enum): + self.enums.append(v) + v.name = k + v.parent = self + elif k == '_include_': + if isinstance(v, str): + self.includes.add(v) + else: + for i in v: + self.includes.add(i) + return self + + def compile_cpp(self, writer): + # generate methods + for meth in self.methods: + meth.compile_cpp(writer) + + # generate method table + writer.println('static') + writer.println('PyMethodDef %s[] = {' % cg.mangle(self.fullname)) + with writer.indent(): + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for meth in self.methods: + name = meth.name + func = cg.mangle(meth.fullname) + writer.println(fmt % locals()) + writer.println('{ NULL },') + writer.println('};') + writer.println() + + def compile_py(self, writer): + clsname = self.name + bases = 'capsule.Wrapper' + if self.bases: + bases = ', '.join(x.name for x in self.bases) + writer.println('@capsule.register_class') + with writer.block('class %(clsname)s(%(bases)s):' % locals()): + for enum in self.enums: + enum.compile_py(writer) + for meth in self.methods: + meth.compile_py(writer) + if not self.enums and not self.methods: + writer.println('pass') + writer.println() + + @property + def capsule_name(self): + if self.bases: + return self.bases[-1].capsule_name else: - assert False - name = _re_mangle_pattern.sub(repl, name) - return name.replace('::', '_') + return self.fullname -def pycapsule_new(println, ptr, name, clsname): - # build capsule - name_soften = mangle(name) - var = new_symbol('pycap_%s' % name_soften) - fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");' - println(fmt % locals()) - println('if (!%(var)s) return NULL;' % locals()) - return var + @property + def fullname(self): + try: + name = self.realname + except AttributeError: + name = self.name + return '::'.join([self.ns.fullname, name]) + + def __str__(self): + return self.fullname + + def unwrap(self, writer, val): + fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")' + name = self.capsule_name + raw = writer.declare('void*', fmt % locals()) + writer.die_if_false(raw) + ptrty = ptr(self).fullname + ty = self.fullname + fmt = 'typecast<%(ty)s>::from(%(raw)s)' + casted = writer.declare(ptrty, fmt % locals()) + writer.die_if_false(casted) + return casted -def declare(println, typ, init=None): - typ_soften = mangle(typ) - var = new_symbol('var_%s' % typ_soften) - if init is None: - println('%(typ)s %(var)s;' % locals()) - else: - println('%(typ)s %(var)s = %(init)s;' % locals()) - return var +class Enum(object): + def __init__(self, *value_names): + self.parent = None + self.value_names = value_names + + @property + def fullname(self): + try: + name = self.realname + except AttributeError: + name = self.name + return '::'.join([self.parent.fullname, name]) + + def __str__(self): + return self.fullname + + def wrap(self, writer, val): + ret = writer.declare('PyObject*', 'NULL') + with writer.block('switch(%s) ' % val): + for v in self.value_names: + writer.println('case %s::%s:' % (self.parent, v)) + with writer.indent(): + fmt = '%(ret)s = PyString_FromString("%(v)s");' + writer.println(fmt % locals()) + writer.println('break;') + else: + writer.println('default:') + with writer.indent(): + writer.raises(ValueError, 'Invalid enum %s' % v) + return ret + + def compile_py(self, writer): + with writer.block('class %s:' % self.name): + for v in self.value_names: + writer.println('%(v)s = "%(v)s"' % locals()) + writer.println() + +class Method(object): + _kind_ = 'meth' + + def __init__(self, return_type=Void, *args): + self.parent = None + self.signatures = [] + self.includes = set() + self._add_signature(return_type, *args) + + def _add_signature(self, return_type, *args): + prev_lens = set(map(len, self.signatures)) + cur_len = len(args) + 1 + if cur_len in prev_lens: + raise Exception('Only support overloading with different number' + ' of arguments') + self.signatures.append([return_type] + list(args)) + + def __ior__(self, method): + assert type(self) is type(method) + for sig in method.signatures: + self._add_signature(sig[0], *sig[1:]) + return self + + @property + def fullname(self): + return '::'.join([self.parent.fullname, self.realname]) + + @property + def realname(self): + try: + return self.__realname + except AttributeError: + return self.name + + @realname.setter + def realname(self, v): + self.__realname = v + + def __str__(self): + return self.fullname + + def compile_cpp(self, writer): + with writer.py_function(self.fullname): + if len(self.signatures) == 1: + sig = self.signatures[0] + retty = sig[0] + argtys = sig[1:] + self.compile_cpp_body(writer, retty, argtys) + else: + nargs = writer.declare('Py_ssize_t', 'PyTuple_Size(args)') + for sig in self.signatures: + retty = sig[0] + argtys = sig[1:] + expect = len(argtys) + if (not isinstance(self, StaticMethod) and + isinstance(self.parent, Class)): + # Is a instance method, add 1 for "this". + expect += 1 + with writer.block('if (%(expect)d == %(nargs)s)' % locals()): + self.compile_cpp_body(writer, retty, argtys) + writer.raises(TypeError, 'Invalid number of args') + + def compile_cpp_body(self, writer, retty, argtys): + if isinstance(self.parent, Class): + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + ret = writer.method_call(self.realname, retty.fullname, *args) + else: + args = writer.parse_arguments('args', *argtys) + ret = writer.call(self.fullname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + + def compile_py(self, writer): + decl = writer.function(self.name, args=('self',), varargs='args') + with decl as (this, varargs): + unwrap_this = writer.unwrap(this) + unwrapped = writer.unwrap_many(varargs) + func = '.'.join([self.parent.name, self.name]) + ret = writer.call('_api.%s' % func, + args=(unwrap_this,), varargs=unwrapped) + wrapped = writer.wrap(ret) + writer.return_value(wrapped) + writer.println() -def return_value(println, var): - println('return %(var)s;' % locals()) +class StaticMethod(Method): + + def compile_cpp_body(self, writer, retty, argtys): + assert isinstance(self.parent, Class) + args = writer.parse_arguments('args', *argtys) + ret = self.compile_cpp_call(writer, retty, args) + writer.return_value(retty.wrap(writer, ret)) + + def compile_cpp_call(self, writer, retty, args): + ret = writer.call(self.fullname, retty.fullname, *args) + return ret + + def compile_py(self, writer): + writer.println('@staticmethod') + decl = writer.function(self.name, varargs='args') + with decl as varargs: + unwrapped = writer.unwrap_many(varargs) + func = '.'.join([self.parent.name, self.name]) + ret = writer.call('_api.%s' % func, varargs=unwrapped) + wrapped = writer.wrap(ret) + writer.return_value(wrapped) + writer.println() -def return_none(println): - println('Py_RETURN_NONE;') +class Function(Method): + _kind_ = 'func' + + def __init__(self, parent, name, return_type=Void, *args): + super(Function, self).__init__(return_type, *args) + self.parent = parent + self.name = name + + def compile_py(self, writer): + with writer.function(self.name, varargs='args') as varargs: + unwrapped = writer.unwrap_many(varargs) + func = self.fullname.split('::', 1)[1].replace('::', '.') + ret = writer.call('_api.%s' % func, + varargs=unwrapped) + wrapped = writer.wrap(ret) + writer.return_value(wrapped) + writer.println() -def die_if_null(println, var): - println('if (!%(var)s) return NULL;' % locals()) +class Destructor(Method): + _kind_ = 'dtor' - -class Binding(object): - __rank_global = 0 def __init__(self): - self.rank = Binding.__rank_global - Binding.__rank_global += 1 - self.include = set() + super(Destructor, self).__init__() - def compile(self, name, println): - raise NotImplementedError(type(self)) + def compile_cpp_body(self, writer, retty, argtys): + assert isinstance(self.parent, Class) + assert not argtys + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + writer.println('delete %s;' % args[0]) + writer.return_value(None) -class Ref(object): - def __init__(self, elem): - self.element = elem + def compile_py(self, writer): + func = '.'.join([self.parent.name, self.name]) + writer.println('_delete_ = _api.%s' % func) + + +class Constructor(StaticMethod): + _kind_ = 'ctor' + + def __init__(self, *args): + super(Constructor, self).__init__(Void, *args) + + def compile_cpp_call(self, writer, retty, args): + alloctype = retty.fullname.rstrip(' *') + arglist = ', '.join(args) + stmt = 'new %(alloctype)s(%(arglist)s)' % locals() + ret = writer.declare(retty.fullname, stmt) + return ret + +class ref(Type): + def __init__(self, element): + assert isinstance(element, Class), type(element) + self.element = element + + def __str__(self): + return self.fullname @property def fullname(self): @@ -112,503 +356,79 @@ class Ref(object): def capsule_name(self): return self.element.capsule_name - @property - def pointer(self): - return self.element.pointer - - def as_pointer(self, println, var): - init = '&%s' % (var) - casted = declare(println, self.pointer, init) - return casted - @property def format(self): - return 'O' + return self.element.format - def unwrap(self, println, var): - ptr = self.element.unwrap(println, var) - return declare(println, self.fullname, '*%s' % ptr) + def wrap(self, writer, val): + p = writer.declare(ptr(self.element).fullname, '&%s' % val) + return writer.pycapsule_new(p, self.capsule_name, self.element.fullname) - def wrap(self, println, var): - return self.element.wrap(println, self.as_pointer(println, var)) + def unwrap(self, writer, val): + p = self.element.unwrap(writer, val) + return writer.declare(self.fullname, '*%s' % p) -class Pointer(object): - def __init__(self, elem): - self.element = elem +class ptr(Type): + def __init__(self, element): + assert isinstance(element, Class) + self.element = element @property def fullname(self): - return '%s*' % self.element.fullname - - @property - def capsule_name(self): - return self.element.capsule_name - - @property - def pointer(self): - return self.element.pointer + return '%s*' % self.element @property def format(self): - return 'O' + return self.element.format - def unwrap(self, println, var): - ret = declare(println, self.fullname) - println2 = indent_println(println) - println('if (%(var)s == Py_None) {' % locals()) - println2('%(ret)s = NULL;' % locals()) - println('} else {') - ptr = self.element.unwrap(println2, var) - println2('%(ret)s = %(ptr)s;' % locals()) - println('}') + def unwrap(self, writer, val): + ret = writer.declare(self.fullname, 'NULL') + with writer.block('if (%(val)s != Py_None)' % locals()): + val = self.element.unwrap(writer, val) + writer.println('%(ret)s = %(val)s;' % locals()) return ret - def wrap(self, println, var): - return self.element.wrap(println, var) + def wrap(self, writer, val): + return writer.pycapsule_new(val, self.element.capsule_name, + self.element.fullname) - -class BuiltinType(object): - def __init__(self, name): - self.name = name - self.Ref = Ref(self) - self.Pointer = Pointer(self) - - @property - def fullname(self): - return self.name - - @property - def capsule_name(self): - return self.fullname - - def To(self, pytype): - return Wrapper(self, pytype) - - def From(self, pytype): - return Unwrapper(self, pytype) - -Void = BuiltinType('void') -Bool = BuiltinType('bool') -Unsigned = BuiltinType('unsigned') -ConstStdString = BuiltinType('const std::string') - -class PyObjectImpl(object): - name = 'PyObject*' - fullname = name +class cast(Type): format = 'O' - def unwrap(self, println, var): - return var - -PyObject = PyObjectImpl() - -class Unwrapper(object): - def __init__(self, cls, pytype): - self.cls = cls - self.pytype = pytype + def __init__(self, original, target): + self.original = original + self.target = target @property def fullname(self): - return str(self.pytype) + return self.binding_type.fullname @property - def format(self): - return 'O' - - def unwrap(self, println, var): - out = declare(println, self.cls.fullname) - conv = 'py_%s_to' % (self.pytype.__name__) - status = '%(conv)s(%(var)s, %(out)s)' % locals() - println('if (!%(status)s) return NULL;' % locals()) - return out - - -class Wrapper(object): - def __init__(self, cls, pytype): - self.cls = cls - self.pytype = pytype - - @property - def fullname(self): - return self.cls.fullname - - def wrap(self, println, var): - conv = 'py_%s_from' % (self.pytype.__name__) - func = '%(conv)s(%(var)s)' % locals() - out = declare(println, 'PyObject*', func) - println('if (!%(out)s) return NULL;' % locals()) - return out - -class Enum(Binding): - def __init__(self, ns, *values): - super(Enum, self).__init__() - self.values = values - self.ns = ns - self.name = None - - def compile(self, name, println): - self.name = self.name or name - - @property - def fullname(self): - return '::'.join([self.ns, self.name]) - -class ClassEnum(Enum): - def __init__(self, cls, *values): - super(ClassEnum, self).__init__(None, *values) - self.cls = cls - self.cls.enums.append(self) - - def compile(self, name, println): - self.ns = self.cls.fullname - super(ClassEnum, self).compile(name, println) - - def wrap(self, println, var): - println2 = indent_println(println) - ret = declare(println, 'PyObject*', NULL) - println('switch(%s) { ' % var) - for v in self.values: - println('case %s::%s:' % (self.ns, v)) - println2('%(ret)s = PyString_FromString("%(v)s");' % locals()) - println2('break;') + def python_type(self): + if not isinstance(self.target, Type): + return self.target else: - println('default:') - println2('PyErr_SetString(PyExc_TypeError, "Invalid enum: %s");' % - v) - println2('return NULL;') - println('}') + return self.original + + @property + def binding_type(self): + if isinstance(self.target, Type): + return self.target + else: + return self.original + + def wrap(self, writer, val): + dst = self.python_type.__name__ + return writer.call('py_%(dst)s_from' % locals(), 'PyObject*', val) + + def unwrap(self, writer, val): + src = self.python_type.__name__ + dst = self.binding_type.fullname + ret = writer.declare(dst) + status = writer.call('py_%(src)s_to' % locals(), 'int', val, ret) + writer.die_if_false(status) return ret - def unwrap(self, println, var): - pass -class Class(Binding): - def __init__(self, ns): - super(Class, self).__init__() - self.ctor = None - self.Ref = Ref(self) - self.Pointer = Pointer(self) - self.Subclass = lambda: Subclass(self) - self.Enum = lambda *v: ClassEnum(self, *v) - self.enums = [] - self.ns = ns - self.methods = [] - self.name = None - - def To(self, pytype): - return Wrapper(self, pytype) - - def From(self, pytype): - return Unwrapper(self, pytype) - - def new(self, *args): - method = Constructor(self, self.Pointer, *args) - self.methods.append(method) - return method - - def delete(self): - method = Destructor(self, Void, self.Pointer) - self.methods.append(method) - return method - - def method(self, return_type, *args): - method = Method(self, return_type, self.Pointer, *args) - self.methods.append(method) - return method - - def staticmethod(self, return_type, *args): - sm = StaticMethod(self, return_type, *args) - self.methods.append(sm) - return sm - - def multimethod(self, *signatures): - mm = MultiMethod(self, signatures) - self.methods.append(mm) - return mm - - def staticmultimethod(self, *signatures): - smm = StaticMultiMethod(self, signatures) - self.methods.append(smm) - return smm - - def compile(self, name, println): - # set name - self.name = self.name or name - - @property - def capsule_name(self): - return self.fullname - - @property - def pointer(self): - return '%s*' % self.fullname - - @property - def fullname(self): - return '::'.join([self.ns, self.name]) - - @property - def mangled_name(self): - return mangle(self.fullname) - - @property - def format(self): - return 'O' - - def unwrap(self, println, var): - typ = self.pointer - elty = self.fullname - cap = self.capsule_name - capptr = 'PyCapsule_GetPointer(%(var)s, "%(cap)s")' % locals() - ptr = declare(println, 'void*', capptr) - unwrapped = 'typecast<%(elty)s>::from(%(ptr)s)' % locals() - var = declare(println, typ, unwrapped) - println('if (!%(var)s) {' % locals()) - println2 = indent_println(println) - println2('PyErr_SetString(PyExc_TypeError, "Invalid cast");') - println2('return NULL;') - println('}') - die_if_null(println, var) - return var - - def wrap(self, println, var): - return pycapsule_new(println, var, self.capsule_name, self.fullname) - -class Subclass(Class): - def __init__(self, parent): - super(Subclass, self).__init__(parent.ns) - self.parent = parent - self.ns = self.parent.ns - - @property - def capsule_name(self): - return self.parent.capsule_name - -class Function(Binding): - def __init__(self, ns, return_type, *args): - super(Function, self).__init__() - self.return_type = return_type - self.args = args - self.ns = ns - self.name = None - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - println('%(name)s(PyObject* self, PyObject* args)' % locals()) - println('{') - self.compile_body(indent_println(println)) - println('}') - - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - call = '%s(%s)' % (self.fullname, ', '.join(args)) - if self.return_type is not Void: - callres = declare(println, self.return_type.fullname, call) - pycap = self.return_type.wrap(println, callres) - return_value(println, pycap) - else: - println('%s;' % call) - return_none(println) - - - @property - def fullname(self): - return '::'.join([self.ns, self.name]) - -class Method(Binding): - def __init__(self, cls, return_type, *args): - super(Method, self).__init__() - self.cls = cls - self.return_type = return_type - self.args = args - self.name = None - self._realname = None - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - mangled = self.mangled_name - println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) - println('{') - self.compile_body(indent_println(println)) - println('}') - - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - this = args[0] - args = ', '.join(args[1:]) - name = self.realname - call = '%(this)s->%(name)s(%(args)s)' % locals() - if self.return_type is not Void: - obj = declare(println, self.return_type.fullname, call) - ret = self.return_type.wrap(println, obj) - return_value(println, ret) - else: - println('%s;' % call) - return_none(println) - - @property - def fullname(self): - return '::'.join([self.cls.fullname, self.name]) - - @property - def realname(self): - if not self._realname: - return self.name - else: - return self._realname - - @realname.setter - def realname(self, v): - self._realname = v - - - @property - def mangled_name(self): - return mangle(self.fullname) - -class MultiMethod(Binding): - '''Can only differs by the number of arguments. - ''' - def __init__(self, cls, signatures): - super(MultiMethod, self).__init__() - nargs = set() - for sig in signatures: - n = len(sig) - if n in nargs: - raise TypeError("MultiMethod only supports overloaded version" - "with different number of arguments") - nargs.add(n) - self.cls = cls - self.signatures = signatures - self.name = None - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - mangled = self.mangled_name - println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) - println('{') - println2 = indent_println(println) - nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') - for sig in self.signatures: - expect = len(sig) - println2('if (%(nargs)s == %(expect)d) {' % locals()) - method = Method(self.cls, sig[0], self.cls.Pointer, *sig[1:]) - method.name = self.name - method.compile_body(indent_println(println2)) - println2('}') - println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') - println2('return NULL;') - println('}') - - @property - def fullname(self): - return '::'.join([self.cls.fullname, self.name]) - - @property - def mangled_name(self): - return mangle(self.fullname) - -class StaticMethod(Method): - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - args = ', '.join(args) - fullname = self.fullname - call = '%(fullname)s(%(args)s)' % locals() - if self.return_type is not Void: - obj = declare(println, self.return_type.fullname, call) - ret = self.return_type.wrap(println, obj) - return_value(println, ret) - else: - println('%s;' % call) - return_none(println) - -class StaticMultiMethod(Binding): - '''Can only differs by the number of arguments. - ''' - def __init__(self, cls, signatures): - super(StaticMultiMethod, self).__init__() - nargs = set() - for sig in signatures: - n = len(sig) - if n in nargs: - raise TypeError("StaticMultiMethod only supports overloaded " - "version with different number of arguments") - nargs.add(n) - self.cls = cls - self.signatures = signatures - self.name = None - - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - mangled = self.mangled_name - println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) - println('{') - println2 = indent_println(println) - nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') - for sig in self.signatures: - expect = len(sig) - 1 - println2('if (%(nargs)s == %(expect)d) {' % locals()) - method = StaticMethod(self.cls, sig[0], *sig[1:]) - method.name = self.name - method.compile_body(indent_println(println2)) - println2('}') - println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') - println2('return NULL;') - println('}') - - @property - def fullname(self): - return '::'.join([self.cls.fullname, self.name]) - - @property - def mangled_name(self): - return mangle(self.fullname) - -class Constructor(StaticMethod): - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - args = ', '.join(args) - name = self.cls.fullname - ctor = 'new %(name)s(%(args)s)' % locals() - obj = declare(println, self.cls.pointer, ctor) - ret = self.return_type.wrap(println, obj) - return_value(println, ret) - -class Destructor(Method): - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - assert len(args) == 1 - dtor = 'delete %s;' % args[0] - println(dtor) - return_none(println) - - -class Namespace(object): - def __init__(self, name): - self.name = name - - def Class(self, *args, **kwargs): - return Class(self.name, *args, **kwargs) - - def Function(self, *args, **kwargs): - return Function(self.name, *args, **kwargs) - diff --git a/newbinding/codegen.py b/newbinding/codegen.py new file mode 100644 index 0000000..9398b14 --- /dev/null +++ b/newbinding/codegen.py @@ -0,0 +1,279 @@ +import re, contextlib + +NULL = 'NULL' + +_symbols = set() + +def indent(println): + def _println(s=''): + println("%s%s" % (' '* 4, s)) + return _println + +def quote(txt): + return '"%s"' % txt + +def new_symbol(name): + if name in _symbols: + ct = 1 + orig = name + while name in _symbols: + name = '%s%d' % (orig, ct) + ct += 1 + _symbols.add(name) + return name + +def parse_arguments(println, var, *args): + typecodes = [] + holders = [] + argvals = [] + for arg in args: + typecodes.append(arg.format) + val = declare(println, 'PyObject*') + argvals.append(val) + holders.append('&' + val) + + items = [var, '"%s"' % (''.join(typecodes))] + holders + println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items)) + + # unwrap + unwrapped = [] + for arg, val in zip(args, argvals): + unwrapped.append(arg.unwrap(println, val)) + + return unwrapped + +_re_mangle_pattern = re.compile(r'[ _<>\*&]') + +def mangle(name): + def repl(m): + s = m.group(0) + if s in '<>*&': + return '' + elif s in ' ': + return '_' + elif s in '_': + return '__' + else: + assert False + name = _re_mangle_pattern.sub(repl, name) + return name.replace('::', '_') + +def pycapsule_new(println, ptr, name, clsname): + # build capsule + name_soften = mangle(name) + var = new_symbol('pycap_%s' % name_soften) + fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");' + println(fmt % locals()) + println('if (!%(var)s) return NULL;' % locals()) + return var + + +def declare(println, typ, init=None): + typ_soften = mangle(typ) + var = new_symbol('var_%s' % typ_soften) + if init is None: + println('%(typ)s %(var)s;' % locals()) + else: + println('%(typ)s %(var)s = %(init)s;' % locals()) + return var + + +def return_value(println, var): + println('return %(var)s;' % locals()) + + +def return_none(println): + println('Py_RETURN_NONE;') + + +def die_if_null(println, var): + println('if (!%(var)s) return NULL;' % locals()) + + +class CodeWriterBase(object): + def __init__(self, println): + self.println = println + self.used_symbols = set() + + @contextlib.contextmanager + def indent(self): + old = self.println + self.println = indent(self.println) + yield + self.println = old + + @contextlib.contextmanager + def py_function(self, name): + mangled = mangle(name) + self.println('static') + self.println('PyObject*') + with self.block('%(mangled)s(PyObject* self, PyObject* args)' % locals()): + self.used_symbols.add('self') + self.used_symbols.add('args') + yield + self.println() + + def new_symbol(self, name): + if name in self.used_symbols: + ct = 1 + orig = name + while name in self.used_symbols: + name = '%s%d' % (orig, ct) + ct += 1 + self.used_symbols.add(name) + return name + +class CppCodeWriter(CodeWriterBase): + @contextlib.contextmanager + def block(self, lead): + self.println(lead) + self.println('{') + with self.indent(): + yield + self.println('}') + + def declare(self, typ, init=None): + typ_soften = mangle(typ) + var = self.new_symbol('var_%s' % typ_soften) + if init is None: + self.println('%(typ)s %(var)s;' % locals()) + else: + self.println('%(typ)s %(var)s = %(init)s;' % locals()) + return var + + def return_value(self, val): + if val is None: + self.println('Py_RETURN_NONE;') + else: + self.println('return %s;' % val) + + def return_null(self): + self.return_value(NULL) + + def parse_arguments(self, var, *args): + typecodes = [] + holders = [] + argvals = [] + for arg in args: + typecodes.append(arg.format) + val = self.declare('PyObject*') + argvals.append(val) + holders.append('&' + val) + + items = [var, '"%s"' % (''.join(typecodes))] + holders + with self.block('if(!PyArg_ParseTuple(%s))' % ', '.join(items)): + self.return_null() + + # unwrap + unwrapped = [] + for arg, val in zip(args, argvals): + unwrapped.append(arg.unwrap(self, val)) + + return unwrapped + + def call(self, func, retty, *args): + arglist = ', '.join(args) + stmt = '%(func)s(%(arglist)s)' % locals() + if retty == 'void': + self.println(stmt) + else: + return self.declare(retty, stmt) + + def method_call(self, func, retty, *args): + this = args[0] + arglist = ', '.join(args[1:]) + if func == 'delete': + assert not arglist + stmt = 'delete %(this)s;' % locals() + elif func == 'new': + alloctype = retty.rstrip(' *') + stmt = 'new %(alloctype)s(%(arglist)s);' % locals() + else: + stmt = '%(this)s->%(func)s(%(arglist)s);' % locals() + if retty == 'void': + self.println(stmt) + else: + return self.declare(retty, stmt) + + def pycapsule_new(self, ptr, name, clsname): + name_soften = mangle(name) + ret = self.call('pycapsule_new', 'PyObject*', ptr, quote(name), + quote(clsname)) + with self.block('if (!%(ret)s)' % locals()): + self.return_null() + return ret + + def die_if_false(self, val): + with self.block('if(!%(val)s)' % locals()): + self.return_null() + + def raises(self, exccls, msg): + exc = 'PyExc_%s' % exccls.__name__ + self.println('PyErr_SetString(%s, "%s");' % (exc, msg)) + self.return_null() + + +class PyCodeWriter(CodeWriterBase): + @contextlib.contextmanager + def block(self, lead): + self.println(lead) + with self.indent(): + yield + + @contextlib.contextmanager + def function(self, func, args=(), varargs=None): + with self.scope(): + arguments = [] + for arg in args: + arguments.append(self.new_symbol(arg)) + if varargs: + varargs = self.new_symbol(varargs) + arguments.append('*%s' % varargs) + arglist = ', '.join(arguments) + with self.block('def %(func)s(%(arglist)s):' % locals()): + if arguments: + arguments[-1] = arguments[-1].lstrip('*') + if len(arguments) > 1: + yield arguments + else: + yield arguments[0] + else: + yield + + @contextlib.contextmanager + def scope(self): + self.old = self.used_symbols + self.used_symbols = set() + yield + self.used_symbols = self.old + + def unwrap_many(self, args): + unwrapped = self.new_symbol('unwrapped') + self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) + return unwrapped + + def unwrap(self, val): + return self.call('capsule.unwrap', args=(val,), ret='unwrapped') + + def wrap(self, val): + wrapped = self.new_symbol('wrapped') + self.println('%(wrapped)s = capsule.wrap(%(val)s)' % locals()) + return wrapped + + def call(self, func, args=(), varargs=None, ret='ret'): + arguments = [] + for arg in args: + arguments.append(arg) + if varargs: + arguments.append('*%s' % varargs) + arglist = ', '.join(arguments) + ret = self.new_symbol(ret) + self.println('%(ret)s = %(func)s(%(arglist)s)' % locals()) + return ret + + def return_value(self, val=None): + if val is None: + val = '' + self.println('return %s' % val) + + diff --git a/newbinding/extra.py b/newbinding/extra.py new file mode 100644 index 0000000..1af4e5f --- /dev/null +++ b/newbinding/extra.py @@ -0,0 +1,20 @@ +''' +Wrapped the extra functions in _api.so +''' + +import capsule + +def _wrapper(func): + def _core(*args): + unwrapped = map(capsule.unwrap, args) + ret = func(*unwrapped) + return capsule.wrap(ret) + return _core + +def _init(glob): + from _api import extra + for k, v in extra.__dict__.items(): + glob[k] = _wrapper(v) + +_init(globals()) + diff --git a/newbinding/gen.py b/newbinding/gen.py index cee71f1..4d8709e 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -1,26 +1,23 @@ -import sys, logging +import sys from binding import * -from utils import * -from cStringIO import StringIO +import codegen -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) extension_entry = ''' - + extern "C" { #if (PY_MAJOR_VERSION >= 3) - + PyObject * PyInit_%(module)s(void) { - PyObject *module = create_python_module("%(module)s", %(methtable)s); - if (module) { - if (populate_submodules(module, submodules)) - return module; - } - return NULL; +PyObject *module = create_python_module("%(module)s", %(methtable)s); +if (module) { +if (populate_submodules(module, submodules)) +return module; +} +return NULL; } #else @@ -28,10 +25,10 @@ PyInit_%(module)s(void) PyMODINIT_FUNC init%(module)s(void) { - PyObject *module = create_python_module("%(module)s", %(methtable)s); - if (module) { - populate_submodules(module, submodules); - } +PyObject *module = create_python_module("%(module)s", %(methtable)s); +if (module) { +populate_submodules(module, submodules); +} } #endif @@ -39,172 +36,6 @@ init%(module)s(void) ''' -def build_methoddef(name, defns, println): - println('static PyMethodDef %s[] = {' % name) - for name, func in defns: - println('{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' % - locals()) - else: - println('{ NULL }') - println('};') - println('') - - -class Context(object): - def __init__(self): - self.includes = set() - self.functions = {} - self.classes = {} - self.definitions = [] - self._pending_symbols = [] - - def generate_cpp(self, println): - for i in self.includes: - println('#include "%s"' % i) - - println('\n'.join(self.definitions)) - - # global function - defns = [] - for name, func in self.functions.items(): - defns.append((name, func.name)) - build_methoddef('global_functions', defns, println) - - # classes - for name, cls in self.classes.items(): - defns = [] - for meth in cls.methods: - defns.append((meth.name, meth.mangled_name)) - println("// %s" % cls.fullname) - build_methoddef(cls.mangled_name, defns, println) - - println('static SubModuleEntry submodules[] = {') - for name, cls in self.classes.items(): - table = cls.mangled_name - println('{ "%(name)s", %(table)s },' % locals()) - println('{ "extra", extra_methodtable },') - println('{ NULL }') - println('};') - println('') - - # generate entry - println(extension_entry % {'module': '_api', - 'methtable': 'global_functions',}) - - def generate_py(self, println): - println('import _api, capsule') - println('') - # wraps all extras - extra_wrapper = ''' -def _init_extra_wrapper(): - def wrap(callee): - def _wrapped(*args): - args = map(capsule.unwrap, args) - ret = callee(*args) - return capsule.wrap(ret) - return _wrapped - for k in dir(_api.extra): - v = getattr(_api.extra, k) - if not k.startswith('__') and callable(v): - globals()[k] = wrap(v) -_init_extra_wrapper() - ''' - println(extra_wrapper) - println('') - # global function - for name in self.functions: - println('def %(name)s(*args):' % locals()) - println2 = indent_println(println) - println2('args = map(capsule.unwrap, args)') - println2('ptr = _api.%(name)s(*args)' % locals()) - println2('return capsule.wrap(ptr)') - println('') - # classes - classes = sorted(self.classes.items(), key=lambda x: x[1].rank) - - for name, cls in classes: - if isinstance(cls, Subclass): - parent = cls.parent.name - else: - parent = 'capsule.Wrapper' - println('@capsule.register_class') - println('class %(name)s(%(parent)s):' % locals()) - self.generate_py_class(indent_println(println), cls) - println('') - - def generate_py_class(self, println, cls): - if len(cls.methods) == 0: - println('pass') - else: - mod = cls.name - # generate class enums - for enum in cls.enums: - println('class %s:' % enum.name) - println2 = indent_println(println) - for v in enum.values: - println2('%(v)s = "%(v)s"' % locals()) - println('') - # generate class methods - for method in cls.methods: - name = method.name - if(isinstance(method, StaticMethod) or - isinstance(method, StaticMultiMethod)): - println('@staticmethod') - println('def %(name)s(*args):' % locals()) - println2 = indent_println(println) - println2('args = map(capsule.unwrap, args)') - println2('ret = _api.%(mod)s.%(name)s(*args)' % locals()) - println2('return capsule.wrap(ret)') - elif isinstance(method, Destructor): - println('_delete_ = _api.%(mod)s.%(name)s' % locals()) - else: - println('def %(name)s(self, *args):' % locals()) - println2 = indent_println(println) - println2('args = map(capsule.unwrap, args)') - println2('ret = _api.%(mod)s.%(name)s(self._ptr, *args)' % - locals()) - println2('return capsule.wrap(ret)') - println('') - - def add_module(self, module): - allsyms = [(k, v) for k, v in vars(module).items() - if isinstance(v, Binding)] - # generate includes - for k, v in allsyms: - self.includes |= v.include - - self._pending_symbols.extend(allsyms) - - def materialize(self): - symtab = sorted(self._pending_symbols, key=lambda x: x[1].rank) - - # compile everything - for k, v in symtab: - buf = StringIO() - def println_to_def(s): - buf.write(s) - buf.write('\n') - logger.info('compiling %s', k) - v.compile(k, println_to_def) - self.definitions.append(buf.getvalue()) - buf.close() - - # generate py defintion table for global functions - for k, v in symtab: - if isinstance(v, Function): - if v.name in self.functions: - raise NameError("Duplicated function name: %s" % v.name) - self.functions[v.name] = v - - # generate sub module tables for classes - submodules = [] - for k, v in symtab: - if isinstance(v, Class): - if v.name in self.classes: - if v is not self.classes[v.name]: - raise NameError("Duplicated class: %s" % v.name) - self.classes[v.name] = v - def populate_headers(println): includes = [ @@ -216,38 +47,96 @@ def populate_headers(println): ] for inc in includes: println('#include "%s"' % inc) + println() -def wrap_println(f): - def println(s): - f.write(s) - f.write('\n') + +def wrap_println_from_file(file): + def println(s=''): + file.write(s) + file.write('\n') return println -if __name__ == '__main__': +def main(): outputfilename = sys.argv[1] - srcdir = sys.argv[2] - modnames = sys.argv[3:] + entry_modname = sys.argv[2] - modules = [] - for m in modnames: - path = '%s.%s' % (srcdir, m) - logger.info("import module %s", path) - module = __import__(path) - for token in path.split('.')[1:]: - module = getattr(module, token) - modules.append(module) + entry_module = __import__(entry_modname) - context = Context() + units = [] + for ns in namespaces.values(): + print 'namespace', ns + for fn in ns.functions: + print fn + units.append(fn) + for cls in ns.classes: + print cls + units.append(cls) - for mod in modules: - context.add_module(mod) - context.materialize() + with open('%s.cpp' % outputfilename, 'w') as cppfile: + println = wrap_println_from_file(cppfile) - with open('%s.cpp' % outputfilename, 'w') as outfile: - println = wrap_println(outfile) + # extra headers populate_headers(println) - context.generate_cpp(println) - with open('%s.py' % outputfilename, 'w') as outfile: - println = wrap_println(outfile) - context.generate_py(println) + # required headers + includes = set() + for u in units: + includes |= u.includes + + for inc in includes: + println('#include "%s"' % inc) + println() + + # write methods and method tables + for u in units: + writer = codegen.CppCodeWriter(println) + u.compile_cpp(writer) + else: + del writer + + # write function table + writer = codegen.CppCodeWriter(println) + writer.println('static') + writer.println('PyMethodDef methtable[] = {') + with writer.indent(): + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for u in units: + if isinstance(u, Function): + name = u.name + func = codegen.mangle(u.fullname) + writer.println(fmt % locals()) + writer.println('{ NULL },') + writer.println('};') + writer.println() + del writer + + + # write submodule table + writer = codegen.CppCodeWriter(println) + writer.println('static') + writer.println('SubModuleEntry submodules[] = {') + with writer.indent(): + for cls in units: + if isinstance(cls, Class): + name = cls.name + table = codegen.mangle(cls.fullname) + writer.println('{ "%(name)s", %(table)s },' % locals()) + writer.println('{ "extra", extra_methodtable },') + writer.println('{ NULL }') + writer.println('};') + writer.println('') + del writer + + println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) + + with open('%s.py' % outputfilename, 'w') as pyfile: + println = wrap_println_from_file(pyfile) + println('import _api, capsule') + println() + for u in units: + writer = codegen.PyCodeWriter(println) + u.compile_py(writer) + + +if __name__ == '__main__': + main() diff --git a/newbinding/include/llvm_binding/auto_pyobject.h b/newbinding/include/llvm_binding/auto_pyobject.h new file mode 100644 index 0000000..451f2d9 --- /dev/null +++ b/newbinding/include/llvm_binding/auto_pyobject.h @@ -0,0 +1,38 @@ +#ifndef AUTO_PYOBJECT_H_ +#define AUTO_PYOBJECT_H_ + +#include + +class auto_pyobject{ + mutable PyObject* PO; +public: + auto_pyobject(): PO(NULL) { } + + auto_pyobject(PyObject* po) : PO(po) { } + + auto_pyobject(const auto_pyobject& other) : PO(*other){ + other.PO = NULL; + } + + ~auto_pyobject() { + Py_XDECREF(PO); + } + + bool operator ! () const { + return !PO; + } + + PyObject* operator * () const { + return PO; + } + + PyObject* get() const { + return PO; + } +private: + // disable assign + void operator = (const auto_pyobject&); +}; + +#endif AUTO_PYOBJECT_H_ + diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h index c3d6e36..0e30c60 100644 --- a/newbinding/include/llvm_binding/conversion.h +++ b/newbinding/include/llvm_binding/conversion.h @@ -62,6 +62,11 @@ static PyObject* py_str_from(const std::string &str){ return PyString_FromStringAndSize(str.c_str(), str.size()); } +// +//static +//PyObject* py_str_from(const llvm::StringRef *str){ +// return py_str_from(str->str()); +//} static PyObject* py_bool_from(bool val){ diff --git a/newbinding/src/AssemblyAnnotationWriter.py b/newbinding/src/AssemblyAnnotationWriter.py index 5641232..d2b5a5d 100644 --- a/newbinding/src/AssemblyAnnotationWriter.py +++ b/newbinding/src/AssemblyAnnotationWriter.py @@ -1,6 +1,7 @@ from binding import * from namespace import llvm -AssemblyAnnotationWriter = llvm.Class() -AssemblyAnnotationWriter.include.add("llvm/Assembly/AssemblyAnnotationWriter.h") +@llvm.Class() +class AssemblyAnnotationWriter: + _include_ = "llvm/Assembly/AssemblyAnnotationWriter.h" diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index 24045bb..14ff6bb 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -2,4 +2,6 @@ from binding import * from namespace import llvm from User import User -Constant = User.Subclass() +@llvm.Class(User) +class Constant: + pass diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index d9dbb53..c57e01b 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -4,17 +4,15 @@ from LLVMContext import LLVMContext from Type import Type from SmallVector import SmallVector_Type -FunctionType = Type.Subclass() -FunctionType.include.add('llvm/DerivedTypes.h') +FunctionType = llvm.Class(Type) -_get_signatures = [(FunctionType.Pointer, - Type.Pointer, Bool.From(bool)), - (FunctionType.Pointer, - Type.Pointer, SmallVector_Type.Ref, Bool.From(bool))] +@FunctionType +class FunctionType: + _include_ = 'llvm/DerivedTypes.h' + get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) + get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), cast(bool, Bool)) + isVarArg = Method(cast(Bool, bool)) + getReturnType = Method(ptr(Type)) + getParamType = Method(ptr(Type), cast(int, Unsigned)) + getNumParams = Method(cast(Unsigned, int)) -get = FunctionType.staticmultimethod(*_get_signatures) - -isVarArg = FunctionType.method(Bool.To(bool)) -getReturnType = FunctionType.method(Type.Pointer) -getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int)) -getNumParams = FunctionType.method(Unsigned.To(int)) diff --git a/newbinding/src/LLVMContext.py b/newbinding/src/LLVMContext.py index 0965748..f2526db 100644 --- a/newbinding/src/LLVMContext.py +++ b/newbinding/src/LLVMContext.py @@ -1,8 +1,8 @@ from binding import * from namespace import llvm -LLVMContext = llvm.Class() -LLVMContext.include.add("llvm/LLVMContext.h") - -getGlobalContext = llvm.Function(LLVMContext.Ref) +@llvm.Class() +class LLVMContext: + _include_ = "llvm/LLVMContext.h" +llvm.Function('getGlobalContext', ref(LLVMContext)) diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 67ac8b0..6a6a806 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -7,39 +7,39 @@ from DerivedTypes import FunctionType from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter -# class Module -Module = llvm.Class() -Module.include.add("llvm/Module.h") +@llvm.Class() +class Module: + _include_ = "llvm/Module.h" + # Enumerators + Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian') + PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64') -# Enumerators -Endianness = Module.Enum('AnyEndianness', 'LittleEndian', 'BigEndian') -PointerSize = Module.Enum('AnyPointerSize', 'Pointer32', 'Pointer64') + # Constructors & Destructors + new = Constructor(cast(str, StringRef), ref(LLVMContext)) + delete = Destructor() -# Constructors & Destructors -new = Module.new(StringRef.From(str), LLVMContext.Ref) -delete = Module.delete() + # Module Level Accessor + getModuleIdentifier = Method(cast(ConstStdString, str)) + getDataLayout = Method(cast(ConstStdString, str)) + getTargetTriple = Method(cast(ConstStdString, str)) + getEndianness = Method(Endianness) + getPointerSize = Method(PointerSize) + getContext = Method(ref(LLVMContext)) + getModuleInlineAsm = Method(cast(ConstStdString, str)) -# Module Level Accessor -getModuleIdentifier = Module.method(ConstStdString.To(str)) -getDataLayout = Module.method(ConstStdString.To(str)) -getTargetTriple = Module.method(ConstStdString.To(str)) -getEndianness = Module.method(Endianness) -getPointerSize = Module.method(PointerSize) -getContext = Module.method(LLVMContext.Ref) -getModuleInlineAsm = Module.method(ConstStdString.To(str)) + # Module Level Mutators + setModuleIdentifier = Method(Void, cast(str, StringRef)) + setDataLayout = Method(Void, cast(str, StringRef)) + setTargetTriple = Method(Void, cast(str, StringRef)) + setModuleInlineAsm = Method(Void, cast(str, StringRef)) + appendModuleInlineAsm = Method(Void, cast(str, StringRef)) -# Module Level Mutators -setModuleIdentifier = Module.method(Void, StringRef.From(str)) -setDataLayout = Module.method(Void, StringRef.From(str)) -setTargetTriple = Module.method(Void, StringRef.From(str)) -setModuleInlineAsm = Module.method(Void, StringRef.From(str)) -appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) + # Function Accessors + getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) -# Function Accessors -getOrInsertFunction = Module.method(Constant.Pointer, StringRef.From(str), FunctionType.Pointer) + # Utilities + dump = Method(Void) + print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) + print_.realname = 'print' -# Utilities -dump = Module.method(Void) -print_ = Module.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) -print_.realname = 'print' -dropAllReferences = Module.method(Void) + dropAllReferences = Method() diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index 225c720..d00b294 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -1,5 +1,6 @@ from binding import * from namespace import llvm -SmallVector_Type = llvm.Class() -delete = SmallVector_Type.delete() +@llvm.Class() +class SmallVector_Type: + delete = Destructor() diff --git a/newbinding/src/StringRef.py b/newbinding/src/StringRef.py index 554629b..fb3b896 100644 --- a/newbinding/src/StringRef.py +++ b/newbinding/src/StringRef.py @@ -1,6 +1,7 @@ from binding import * from namespace import llvm -StringRef = llvm.Class() -StringRef.include.add("llvm/ADT/StringRef.h") +@llvm.Class() +class StringRef: + _include_ = "llvm/ADT/StringRef.h" diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 3703200..45f9444 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -4,93 +4,112 @@ from LLVMContext import LLVMContext from raw_ostream import raw_ostream Type = llvm.Class() -Type.include.add('llvm/Type.h') +IntegerType = llvm.Class(Type) +CompositeType = llvm.Class(Type) +SequentialType = llvm.Class(CompositeType) +PointerType = llvm.Class(SequentialType) -IntegerType = Type.Subclass() -CompositeType = Type.Subclass() -SequentialType = CompositeType.Subclass() -PointerType = SequentialType.Subclass() +@Type +class Type: + _include_ = 'llvm/Type.h' -getContext = Type.method(LLVMContext.Ref) -dump = Type.method(Void) -print_ = Type.method(Void, raw_ostream.Ref) -print_.realname = 'print' + getContext = Method(ref(LLVMContext)) + dump = Method() + print_ = Method(Void, ref(raw_ostream)) + print_.realname = 'print' -def type_checker(): - return Type.method(Bool.To(bool)) + def type_checker(): + return Method(cast(Bool, bool)) -isVoidTy = type_checker() -isHalfTy = type_checker() -isFloatTy = type_checker() -isDoubleTy = type_checker() -isX86_FP80Ty = type_checker() -isFP128Ty = type_checker() -isPPC_FP128Ty = type_checker() -isFloatingPointTy = type_checker() -isX86_MMXTy = type_checker() -isFPOrFPVectorTy = type_checker() -isLabelTy = type_checker() -isMetadataTy = type_checker() -isIntOrIntVectorTy = type_checker() -isFunctionTy = type_checker() -isStructTy = type_checker() -isArrayTy = type_checker() -isPointerTy = type_checker() -isPtrOrPtrVectorTy = type_checker() -isVectorTy = type_checker() -isEmptyTy = type_checker() -isPrimitiveType = type_checker() -isDerivedType = type_checker() -isFirstClassType = type_checker() -isSingleValueType = type_checker() -isAggregateType = type_checker() -isSized = type_checker() + isVoidTy = type_checker() + isHalfTy = type_checker() + isFloatTy = type_checker() + isDoubleTy = type_checker() + isX86_FP80Ty = type_checker() + isFP128Ty = type_checker() + isPPC_FP128Ty = type_checker() + isFloatingPointTy = type_checker() + isX86_MMXTy = type_checker() + isFPOrFPVectorTy = type_checker() + isLabelTy = type_checker() + isMetadataTy = type_checker() + isIntOrIntVectorTy = type_checker() + isFunctionTy = type_checker() + isStructTy = type_checker() + isArrayTy = type_checker() + isPointerTy = type_checker() + isPtrOrPtrVectorTy = type_checker() + isVectorTy = type_checker() + isEmptyTy = type_checker() + isPrimitiveType = type_checker() + isDerivedType = type_checker() + isFirstClassType = type_checker() + isSingleValueType = type_checker() + isAggregateType = type_checker() + isSized = type_checker() -isIntegerTy = Type.multimethod([Bool.To(bool)], - [Bool.To(bool), Unsigned.From(int)]) + isIntegerTy = Method(cast(Bool, bool)) + isIntegerTy |= Method(cast(Bool, bool), cast(int, Unsigned)) -def type_factory(): - return Type.staticmethod(Type.Pointer, LLVMContext.Ref) + def type_factory(): + return StaticMethod(ptr(Type), ref(LLVMContext)) -getVoidTy = type_factory() -getLabelTy = type_factory() -getHalfTy = type_factory() -getFloatTy = type_factory() -getDoubleTy = type_factory() -getMetadataTy = type_factory() -getX86_FP80Ty = type_factory() -getFP128Ty = type_factory() -getPPC_FP128Ty = type_factory() -getX86_MMXTy = type_factory() + getVoidTy = type_factory() + getLabelTy = type_factory() + getHalfTy = type_factory() + getFloatTy = type_factory() + getDoubleTy = type_factory() + getMetadataTy = type_factory() + getX86_FP80Ty = type_factory() + getFP128Ty = type_factory() + getPPC_FP128Ty = type_factory() + getX86_MMXTy = type_factory() -getIntNTy = Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref, Unsigned.From(int)) + getIntNTy = StaticMethod(ptr(IntegerType), ref(LLVMContext), cast(Unsigned, int)) -def integer_factory(): - return Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref) + def integer_factory(): + return StaticMethod(ptr(IntegerType), ref(LLVMContext)) -getInt1Ty = integer_factory() -getInt8Ty = integer_factory() -getInt16Ty = integer_factory() -getInt32Ty = integer_factory() -getInt64Ty = integer_factory() + getInt1Ty = integer_factory() + getInt8Ty = integer_factory() + getInt16Ty = integer_factory() + getInt32Ty = integer_factory() + getInt64Ty = integer_factory() -def pointer_factory(): - return Type.staticmethod(PointerType.Pointer, LLVMContext.Ref) + def pointer_factory(): + return StaticMethod(ptr(PointerType), ref(LLVMContext)) -getHalfPtrTy = pointer_factory() -getFloatPtrTy = pointer_factory() -getDoublePtrTy = pointer_factory() -getX86_FP80PtrTy = pointer_factory() -getFP128PtrTy = pointer_factory() -getPPC_FP128PtrTy = pointer_factory() -getX86_MMXPtrTy = pointer_factory() -getInt1PtrTy = pointer_factory() -getInt8PtrTy = pointer_factory() -getInt16PtrTy = pointer_factory() -getInt32PtrTy = pointer_factory() -getInt64PtrTy = pointer_factory() -getIntNPtrTy = Type.staticmethod(PointerType.Pointer, - LLVMContext.Ref, Unsigned.From(int)) + getHalfPtrTy = pointer_factory() + getFloatPtrTy = pointer_factory() + getDoublePtrTy = pointer_factory() + getX86_FP80PtrTy = pointer_factory() + getFP128PtrTy = pointer_factory() + getPPC_FP128PtrTy = pointer_factory() + getX86_MMXPtrTy = pointer_factory() + getInt1PtrTy = pointer_factory() + getInt8PtrTy = pointer_factory() + getInt16PtrTy = pointer_factory() + getInt32PtrTy = pointer_factory() + getInt64PtrTy = pointer_factory() + getIntNPtrTy = StaticMethod(ptr(PointerType), + ref(LLVMContext), cast(int, Unsigned)) +@IntegerType +class IntegerType: + pass + + +@CompositeType +class CompositeType: + pass + +@SequentialType +class SequentialType: + pass + +@PointerType +class PointerType: + pass + diff --git a/newbinding/src/User.py b/newbinding/src/User.py index 8753983..dbc290d 100644 --- a/newbinding/src/User.py +++ b/newbinding/src/User.py @@ -2,4 +2,7 @@ from binding import * from namespace import llvm from Value import Value -User = Value.Subclass() +@llvm.Class(Value) +class User: + pass + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 062ad43..9d1a2dd 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -5,20 +5,23 @@ from AssemblyAnnotationWriter import AssemblyAnnotationWriter from Type import Type from LLVMContext import LLVMContext from StringRef import StringRef -# + Value = llvm.Class() -dump = Value.method(Void) +@Value +class Value: -print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) -print_.realname = 'print' + dump = Method() -getType = Value.method(Type.Pointer) -getContext = Value.method(LLVMContext.Ref) + print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) + print_.realname = 'print' -hasName = Value.method(Bool.To(bool)) -# skip getValueName, setValueName -getName = Value.method(StringRef.To(str)) -setName = Value.method(Void, StringRef.From(str)) + getType = Method(ptr(Type)) + getContext = Method(ref(LLVMContext)) -replaceAllUsesWith = Value.method(Void, Value.Pointer) \ No newline at end of file + hasName = Method(cast(Bool, bool)) + # skip getValueName, setValueName + getName = Method(cast(StringRef, str)) + setName = Method(Void, cast(str, StringRef)) + + replaceAllUsesWith = Method(Void, ptr(Value)) \ No newline at end of file diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index e69de29..6e24918 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -0,0 +1,2 @@ +from . import Module + diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index 02af8c9..c50256d 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,4 +1,3 @@ from binding import * -extra = Namespace('llvm_extra') llvm = Namespace('llvm') diff --git a/newbinding/src/raw_ostream.py b/newbinding/src/raw_ostream.py index 64e8046..2f5a6f5 100644 --- a/newbinding/src/raw_ostream.py +++ b/newbinding/src/raw_ostream.py @@ -3,10 +3,15 @@ from namespace import llvm from LLVMContext import LLVMContext from StringRef import StringRef -raw_ostream = llvm.Class() -raw_ostream.include.add("llvm/Support/raw_ostream.h") -delete = raw_ostream.delete() +@llvm.Class() +class raw_ostream: + _include_ = "llvm/Support/raw_ostream.h" + delete = Destructor() + +@llvm.Class(raw_ostream) +class raw_svector_ostream: + _include_ = "llvm/Support/raw_os_ostream.h" + _base_ = raw_ostream + + str = Method(cast(str, StringRef)) -raw_svector_ostream = raw_ostream.Subclass() -raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h") -str = raw_svector_ostream.method(StringRef.To(str)) diff --git a/newbinding/test2.py b/newbinding/test2.py index ac74594..afb3608 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,4 +1,5 @@ import api +import extra import _capsule api.capsule.set_debug(True) context = api.getGlobalContext() @@ -15,7 +16,7 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() -os = api.make_raw_ostream_for_printing() +os = extra.make_raw_ostream_for_printing() m.print_(os, None) print os.str() @@ -29,15 +30,15 @@ fnty = api.FunctionType.get(int1ty, False) fnty.dump() types = [int1ty, api.Type.getIntNTy(context, 21)] -svt = api.make_small_vector_from_types(*types) +svt = extra.make_small_vector_from_types(*types) fnty = api.FunctionType.get(int1ty, svt, False) -os = api.make_raw_ostream_for_printing() +os = extra.make_raw_ostream_for_printing() fnty.print_(os) print os.str() fn = m.getOrInsertFunction("foo", fnty) -os = api.make_raw_ostream_for_printing() +os = extra.make_raw_ostream_for_printing() fn.print_(os, None) print os.str() assert fn.hasName() diff --git a/newbinding/utils.py b/newbinding/utils.py deleted file mode 100644 index 6c39990..0000000 --- a/newbinding/utils.py +++ /dev/null @@ -1,6 +0,0 @@ - -def indent_println(println): - def _println(s): - println("%s%s" % (' '* 4, s)) - return _println - From 3c81157ede77dae545dea76988df117441b8bb16 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 25 Jan 2013 15:35:23 -0600 Subject: [PATCH 045/338] Add downcasting --- newbinding/binding.py | 28 +++++++++------ newbinding/capsule.py | 46 +++++++++++++++++-------- newbinding/extra.py | 27 +++++++++++++-- newbinding/gen.py | 26 ++++++++++++++ newbinding/include/llvm_binding/extra.h | 10 +++--- newbinding/src/namespace.py | 1 + 6 files changed, 106 insertions(+), 32 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index fc26d92..8c58aa9 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -28,10 +28,10 @@ class Namespace(object): def __str__(self): return self.name -class Type(object): +class _Type(object): pass -class BuiltinTypes(Type): +class BuiltinTypes(_Type): def __init__(self, name): self.name = name @@ -47,7 +47,7 @@ Unsigned = BuiltinTypes('unsigned') Bool = BuiltinTypes('bool') ConstStdString = BuiltinTypes('const std::string') -class Class(Type): +class Class(_Type): format = 'O' def __init__(self, ns, *bases): @@ -57,9 +57,11 @@ class Class(Type): self.methods = [] self.enums = [] self.includes = set() + self.downcastables = set() def __call__(self, defn): assert not self._is_defined + # process the definition in "defn" self.name = defn.__name__ for k, v in defn.__dict__.items(): if isinstance(v, Method): @@ -79,6 +81,12 @@ class Class(Type): else: for i in v: self.includes.add(i) + elif k == '_downcast_': + if isinstance(v, Class): + self.downcastables.add(v) + else: + for i in v: + self.downcastables.add(i) return self def compile_cpp(self, writer): @@ -106,12 +114,11 @@ class Class(Type): bases = ', '.join(x.name for x in self.bases) writer.println('@capsule.register_class') with writer.block('class %(clsname)s(%(bases)s):' % locals()): + writer.println('_llvm_type_ = "%s"' % self.fullname) for enum in self.enums: enum.compile_py(writer) for meth in self.methods: meth.compile_py(writer) - if not self.enums and not self.methods: - writer.println('pass') writer.println() @property @@ -178,6 +185,7 @@ class Enum(object): def compile_py(self, writer): with writer.block('class %s:' % self.name): + writer.println('_llvm_type_ = "%s"' % self.fullname) for v in self.value_names: writer.println('%(v)s = "%(v)s"' % locals()) writer.println() @@ -340,7 +348,7 @@ class Constructor(StaticMethod): ret = writer.declare(retty.fullname, stmt) return ret -class ref(Type): +class ref(_Type): def __init__(self, element): assert isinstance(element, Class), type(element) self.element = element @@ -369,7 +377,7 @@ class ref(Type): return writer.declare(self.fullname, '*%s' % p) -class ptr(Type): +class ptr(_Type): def __init__(self, element): assert isinstance(element, Class) self.element = element @@ -393,7 +401,7 @@ class ptr(Type): return writer.pycapsule_new(val, self.element.capsule_name, self.element.fullname) -class cast(Type): +class cast(_Type): format = 'O' def __init__(self, original, target): @@ -406,14 +414,14 @@ class cast(Type): @property def python_type(self): - if not isinstance(self.target, Type): + if not isinstance(self.target, _Type): return self.target else: return self.original @property def binding_type(self): - if isinstance(self.target, Type): + if isinstance(self.target, _Type): return self.target else: return self.original diff --git a/newbinding/capsule.py b/newbinding/capsule.py index e4cd4fa..d999e30 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -19,7 +19,7 @@ def set_debug(enabled): class WeakRef(ref): - __slots__ = 'capsule', 'dtor' + __slots__ = 'capsule', 'dtor', 'owning' _pyclasses = {} _addr2obj = WeakValueDictionary() @@ -33,12 +33,20 @@ def classof(cap): return _pyclasses[cls] def _capsule_destructor(weak): - cap = weak.capsule - addr = _capsule.getPointer(cap) - cls = _capsule.getClassName(cap) - logger.debug("destroy pointer 0x%08X to %s", addr, cls) - weak.dtor(cap) - del _owners[addr] + if weak.owning: + cap = weak.capsule + addr = _capsule.getPointer(cap) + cls = _capsule.getClassName(cap) + logger.debug("destroy pointer 0x%08X to %s", addr, cls) + weak.dtor(cap) + del _owners[addr] + +def release_ownership(old): + addr = _capsule.getPointer(old) + if hasattr(old, '_delete_'): + oldweak = _owners[addr] + oldweak.owning = False # dis-own + del _owners[addr] def wrap(cap): '''Wrap a PyCapsule with the corresponding Wrapper class. @@ -60,13 +68,26 @@ def wrap(cap): weak = WeakRef(obj, _capsule_destructor) _owners[addr] = weak weak.capsule = cap + weak.owning = True weak.dtor = cls._delete_ else: - assert classof(obj._ptr) is classof(cap) - # Unset destructor for capsules that are repeated - _capsule.setDestructor(cap, None) + oldcls = classof(obj._ptr) + newcls = classof(cap) + if issubclass(oldcls, newcls): + # do auto downcast + pass + else: + assert oldcls is newcls return obj +def downcast(old, new): + assert old is not new + oldcls = classof(old) + newcls = classof(new) + assert issubclass(newcls, oldcls) + release_ownership(old) + del _addr2obj[_capsule.getPointer(old)] # clear cache + return wrap(new) def unwrap(obj): '''Unwrap a Wrapper instance into the underlying PyCapsule. @@ -96,8 +117,3 @@ class Wrapper(object): def _ptr(self): return self.__ptr - def _release_ownership(self): - _capsule.setDestructor(self._ptr, None) - - - diff --git a/newbinding/extra.py b/newbinding/extra.py index 1af4e5f..a613296 100644 --- a/newbinding/extra.py +++ b/newbinding/extra.py @@ -3,8 +3,13 @@ Wrapped the extra functions in _api.so ''' import capsule +import _api +# +# Re-export the native API from the _api.extra and wrap the functions +# def _wrapper(func): + "Wrap the re-exported functions" def _core(*args): unwrapped = map(capsule.unwrap, args) ret = func(*unwrapped) @@ -12,9 +17,27 @@ def _wrapper(func): return _core def _init(glob): - from _api import extra - for k, v in extra.__dict__.items(): + for k, v in _api.extra.__dict__.items(): glob[k] = _wrapper(v) _init(globals()) +# +# Downcasts +# + +def downcast(obj, cls): + if type(obj) is cls: + return obj + fromty = obj._llvm_type_ + toty = cls._llvm_type_ + fname = 'downcast_%s_to_%s' % (fromty, toty) + fname = fname.replace('::', '_') + try: + caster = getattr(_api, fname) + except AttributeError: + fmt = "Downcast from %s to %s is not supported" + raise TypeError(fmt % (fromty, toty)) + old = capsule.unwrap(obj) + new = caster(old) + return capsule.downcast(old, new) \ No newline at end of file diff --git a/newbinding/gen.py b/newbinding/gen.py index 4d8709e..f1af18e 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -72,6 +72,20 @@ def main(): print cls units.append(cls) + # add extra stuffs + downcastlist = [] + ## add downcast + for cls in units: + if isinstance(cls, Class): + for bcls in cls.downcastables: + from_to = bcls.fullname, cls.fullname + name = 'downcast_%s_to_%s' % tuple(map(codegen.mangle, from_to)) + fn = Function(namespaces[''], name, ptr(cls), ptr(bcls)) + downcastlist.append((from_to, fn)) + units.append(fn) + + + # generate cpp source with open('%s.cpp' % outputfilename, 'w') as cppfile: println = wrap_println_from_file(cppfile) @@ -87,6 +101,18 @@ def main(): println('#include "%s"' % inc) println() + # generate downcast + for ((fromty, toty), fn) in downcastlist: + name = fn.name + fmt = ''' +static +%(toty)s* %(name)s(%(fromty)s* arg) +{ + return typecast<%(toty)s>::from(arg); +} +''' + println(fmt % locals()) + # write methods and method tables for u in units: writer = codegen.CppCodeWriter(println) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 417c0f8..94887b3 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -37,9 +37,9 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { } static PyMethodDef extra_methodtable[] = { -#define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } -method( make_raw_ostream_for_printing ), -method( make_small_vector_from_types ), -{ NULL } -#undef method + #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } + method( make_raw_ostream_for_printing ), + method( make_small_vector_from_types ), + #undef method + { NULL } }; diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index c50256d..3a081af 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,3 +1,4 @@ from binding import * llvm = Namespace('llvm') +default = Namespace('') From c76096bbcb01953d43b9a829f28d5e52b7fad9d7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 25 Jan 2013 15:41:38 -0600 Subject: [PATCH 046/338] Add Function and some Function methods --- newbinding/src/Function.py | 19 +++++++++++++++++++ newbinding/src/GlobalValue.py | 8 ++++++++ newbinding/src/Module.py | 1 + newbinding/src/Value.py | 2 +- newbinding/test2.py | 12 +++++++++++- 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 newbinding/src/Function.py create mode 100644 newbinding/src/GlobalValue.py diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py new file mode 100644 index 0000000..7077d3a --- /dev/null +++ b/newbinding/src/Function.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm +from GlobalValue import GlobalValue +from Constant import Constant +from Type import Type +from DerivedTypes import FunctionType +from LLVMContext import LLVMContext + +@llvm.Class(GlobalValue) +class Function: + _include_ = 'llvm/Function.h' + _downcast_ = GlobalValue, Constant + + getReturnType = Method(ptr(Type)) + getFunctionType = Method(ptr(FunctionType)) + getContext = Method(ref(LLVMContext)) + isVarArg = Method(cast(Bool, bool)) + getIntrinsicID = Method(cast(Unsigned, int)) + isIntrinsic = Method(cast(Bool, bool)) \ No newline at end of file diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py new file mode 100644 index 0000000..f1a6827 --- /dev/null +++ b/newbinding/src/GlobalValue.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm +from Constant import Constant + +@llvm.Class(Constant) +class GlobalValue: + _include_ = 'llvm/GlobalValue.h' + diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 6a6a806..730b757 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -3,6 +3,7 @@ from namespace import llvm from LLVMContext import LLVMContext from StringRef import StringRef from Constant import Constant +from Function import Function from DerivedTypes import FunctionType from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 9d1a2dd..30b3f37 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -24,4 +24,4 @@ class Value: getName = Method(cast(StringRef, str)) setName = Method(Void, cast(str, StringRef)) - replaceAllUsesWith = Method(Void, ptr(Value)) \ No newline at end of file + replaceAllUsesWith = Method(Void, ptr(Value)) diff --git a/newbinding/test2.py b/newbinding/test2.py index afb3608..3429f10 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -37,7 +37,8 @@ os = extra.make_raw_ostream_for_printing() fnty.print_(os) print os.str() -fn = m.getOrInsertFunction("foo", fnty) +const = m.getOrInsertFunction("foo", fnty) +fn = extra.downcast(const, api.Function) os = extra.make_raw_ostream_for_printing() fn.print_(os, None) print os.str() @@ -45,3 +46,12 @@ assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') assert 'bar' == fn.getName() + +os = extra.make_raw_ostream_for_printing() +assert fn.getReturnType() is int1ty + +assert fnty is fn.getFunctionType() + +assert fn.isVarArg() == False +assert fn.getIntrinsicID() == 0 +assert not fn.isIntrinsic() From 4b5cb100f71c5b9624a35e78c97324f48d0dde4f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:18:24 -0600 Subject: [PATCH 047/338] Auto discover binding modules --- newbinding/src/__init__.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index 6e24918..1042826 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -1,2 +1,11 @@ -from . import Module +import os.path, importlib +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + topname = __name__.rsplit('.', 1)[0] + importlib.import_module('.' + modname, topname) + +_init() From 01683150760f3f0778937590eac769847f7d8b64 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:19:16 -0600 Subject: [PATCH 048/338] Explicitly declare class name when registering classes --- newbinding/binding.py | 3 +-- newbinding/capsule.py | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 8c58aa9..85b74e9 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -112,7 +112,7 @@ class Class(_Type): bases = 'capsule.Wrapper' if self.bases: bases = ', '.join(x.name for x in self.bases) - writer.println('@capsule.register_class') + writer.println('@capsule.register_class("%s")' % self.fullname) with writer.block('class %(clsname)s(%(bases)s):' % locals()): writer.println('_llvm_type_ = "%s"' % self.fullname) for enum in self.enums: @@ -151,7 +151,6 @@ class Class(_Type): writer.die_if_false(casted) return casted - class Enum(object): def __init__(self, *value_names): self.parent = None diff --git a/newbinding/capsule.py b/newbinding/capsule.py index d999e30..47c32fb 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -99,10 +99,11 @@ def unwrap(obj): return obj -def register_class(cls): - clsname = cls.__name__ - _pyclasses['llvm::%s' % clsname] = cls - return cls +def register_class(clsname): + def _wrapped(cls): + _pyclasses[clsname] = cls + return cls + return _wrapped class Wrapper(object): From d1931cc4994c2ee6adf8d611c9a59d5dbc9c0362 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:20:07 -0600 Subject: [PATCH 049/338] Fix duplicated semicolon --- newbinding/codegen.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/newbinding/codegen.py b/newbinding/codegen.py index 9398b14..2a85abc 100644 --- a/newbinding/codegen.py +++ b/newbinding/codegen.py @@ -184,14 +184,14 @@ class CppCodeWriter(CodeWriterBase): arglist = ', '.join(args[1:]) if func == 'delete': assert not arglist - stmt = 'delete %(this)s;' % locals() + stmt = 'delete %(this)s' % locals() elif func == 'new': alloctype = retty.rstrip(' *') - stmt = 'new %(alloctype)s(%(arglist)s);' % locals() + stmt = 'new %(alloctype)s(%(arglist)s)' % locals() else: - stmt = '%(this)s->%(func)s(%(arglist)s);' % locals() + stmt = '%(this)s->%(func)s(%(arglist)s)' % locals() if retty == 'void': - self.println(stmt) + self.println('%s;' % stmt) else: return self.declare(retty, stmt) From 821e93783729ff74268e63c329d8a839c47fded9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:20:36 -0600 Subject: [PATCH 050/338] Add binding util for iterator to list --- newbinding/binding.py | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 85b74e9..1764559 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -46,6 +46,7 @@ Void = BuiltinTypes('void') Unsigned = BuiltinTypes('unsigned') Bool = BuiltinTypes('bool') ConstStdString = BuiltinTypes('const std::string') +PyObjectPtr = BuiltinTypes('PyObject*') class Class(_Type): format = 'O' @@ -81,6 +82,8 @@ class Class(_Type): else: for i in v: self.includes.add(i) + elif k == '_realname_': + self.realname = v elif k == '_downcast_': if isinstance(v, Class): self.downcastables.add(v) @@ -146,7 +149,7 @@ class Class(_Type): writer.die_if_false(raw) ptrty = ptr(self).fullname ty = self.fullname - fmt = 'typecast<%(ty)s>::from(%(raw)s)' + fmt = 'typecast<%(ty)s >::from(%(raw)s)' casted = writer.declare(ptrty, fmt % locals()) writer.die_if_false(casted) return casted @@ -252,12 +255,8 @@ class Method(object): writer.raises(TypeError, 'Invalid number of args') def compile_cpp_body(self, writer, retty, argtys): - if isinstance(self.parent, Class): - args = writer.parse_arguments('args', ptr(self.parent), *argtys) - ret = writer.method_call(self.realname, retty.fullname, *args) - else: - args = writer.parse_arguments('args', *argtys) - ret = writer.call(self.fullname, retty.fullname, *args) + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + ret = writer.method_call(self.realname, retty.fullname, *args) writer.return_value(retty.wrap(writer, ret)) def compile_py(self, writer): @@ -273,6 +272,29 @@ class Method(object): writer.println() +class IterToList(Method): + def __init__(self, elemty, argtys, iterty, begin, end): + super(IterToList, self).__init__(PyObjectPtr, *argtys) + self.elemty = elemty + self.iterty = iterty + self.begin = begin + self.end = end + + def compile_cpp_body(self, writer, retty, argtys): + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + it = writer.method_call(self.begin, self.iterty, *args) + end = writer.method_call(self.end, self.iterty, *args) + con = writer.call('PyList_New', 'PyObject*', '0') + writer.die_if_false(con) + with writer.block('for (; %(it)s != %(end)s; ++%(it)s)' % locals()): + elem = writer.declare(self.elemty.fullname, '*%(it)s;' % locals()) + wrapped = self.elemty.wrap(writer, elem) + ok = writer.call('PyList_Append', 'int', con, wrapped) + with writer.block('if (%(ok)s == -1)' % locals()): + writer.return_value(None) + writer.return_value(con) + + class StaticMethod(Method): def compile_cpp_body(self, writer, retty, argtys): @@ -296,7 +318,6 @@ class StaticMethod(Method): writer.return_value(wrapped) writer.println() - class Function(Method): _kind_ = 'func' @@ -305,6 +326,11 @@ class Function(Method): self.parent = parent self.name = name + def compile_cpp_body(self, writer, retty, argtys): + args = writer.parse_arguments('args', *argtys) + ret = writer.call(self.fullname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + def compile_py(self, writer): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) @@ -315,7 +341,6 @@ class Function(Method): writer.return_value(wrapped) writer.println() - class Destructor(Method): _kind_ = 'dtor' From fa4927e1fb6cb195206fbbf4d13d311148921690 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:20:50 -0600 Subject: [PATCH 051/338] Start to work on IRBuilder --- newbinding/src/Constant.py | 5 +++-- newbinding/src/Function.py | 8 ++++---- newbinding/src/GlobalValue.py | 4 ++-- newbinding/src/User.py | 5 ++--- newbinding/src/Value.py | 13 +++++++++++++ newbinding/test2.py | 12 ++++++++++++ 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index 14ff6bb..c59fef4 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -1,7 +1,8 @@ from binding import * from namespace import llvm -from User import User +from Value import Constant -@llvm.Class(User) +@Constant class Constant: pass + diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index 7077d3a..f069e30 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -1,12 +1,11 @@ from binding import * from namespace import llvm -from GlobalValue import GlobalValue -from Constant import Constant +from Value import GlobalValue, Constant, Function from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext -@llvm.Class(GlobalValue) +@Function class Function: _include_ = 'llvm/Function.h' _downcast_ = GlobalValue, Constant @@ -16,4 +15,5 @@ class Function: getContext = Method(ref(LLVMContext)) isVarArg = Method(cast(Bool, bool)) getIntrinsicID = Method(cast(Unsigned, int)) - isIntrinsic = Method(cast(Bool, bool)) \ No newline at end of file + isIntrinsic = Method(cast(Bool, bool)) + diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index f1a6827..40825a8 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -1,8 +1,8 @@ from binding import * from namespace import llvm -from Constant import Constant +from Value import GlobalValue -@llvm.Class(Constant) +@GlobalValue class GlobalValue: _include_ = 'llvm/GlobalValue.h' diff --git a/newbinding/src/User.py b/newbinding/src/User.py index dbc290d..57d58bc 100644 --- a/newbinding/src/User.py +++ b/newbinding/src/User.py @@ -1,8 +1,7 @@ from binding import * from namespace import llvm -from Value import Value +from Value import User -@llvm.Class(Value) +@User class User: pass - diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 30b3f37..a901946 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -7,6 +7,12 @@ from LLVMContext import LLVMContext from StringRef import StringRef Value = llvm.Class() +# forward declarations +User = llvm.Class(Value) +BasicBlock = llvm.Class(Value) +Constant = llvm.Class(User) +GlobalValue = llvm.Class(Constant) +Function = llvm.Class(GlobalValue) @Value class Value: @@ -25,3 +31,10 @@ class Value: setName = Method(Void, cast(str, StringRef)) replaceAllUsesWith = Method(Void, ptr(Value)) + + list_use = IterToList(ptr(User), (), 'llvm::Value::use_iterator', + 'use_begin', 'use_end') + + hasOneUse = Method(cast(Bool, bool)) + hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) + isUsedInBasicBlock = Method(cast(Bool, bool), BasicBlock) diff --git a/newbinding/test2.py b/newbinding/test2.py index 3429f10..810a7ba 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -55,3 +55,15 @@ assert fnty is fn.getFunctionType() assert fn.isVarArg() == False assert fn.getIntrinsicID() == 0 assert not fn.isIntrinsic() + +print fn.list_use() + +builder = api.IRBuilder.new(context) +print builder + +bb = api.BasicBlock.Create(context, "entry", fn, None) +builder.SetInsertPoint(bb) + +builder.CreateRetVoid() + +fn.dump() From d9397289383cb0f17ba088cf3946ad6deb46ab0c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:21:30 -0600 Subject: [PATCH 052/338] Forgot to push files for previous commit. --- newbinding/src/BasicBlock.py | 19 +++ newbinding/src/IRBuilder.py | 21 ++++ newbinding/src/Instruction.py | 230 ++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 newbinding/src/BasicBlock.py create mode 100644 newbinding/src/IRBuilder.py create mode 100644 newbinding/src/Instruction.py diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py new file mode 100644 index 0000000..c7221a5 --- /dev/null +++ b/newbinding/src/BasicBlock.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm +from Value import Function, BasicBlock +from LLVMContext import LLVMContext +from StringRef import StringRef + +@BasicBlock +class BasicBlock: + Create = StaticMethod(ptr(BasicBlock), ref(LLVMContext), + cast(str, StringRef), + ptr(Function), + ptr(BasicBlock)) + + getParent = Method(ptr(Function)) + empty = Method(cast(Bool, bool)) + dropAllReferences = Method() + isLandingPad = Method(cast(Bool, bool)) + removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool)) + removePredecessor |= Method(Void, ptr(BasicBlock)) diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py new file mode 100644 index 0000000..0919a67 --- /dev/null +++ b/newbinding/src/IRBuilder.py @@ -0,0 +1,21 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from BasicBlock import BasicBlock +from Instruction import ReturnInst + +IRBuilder = llvm.Class() + +@IRBuilder +class IRBuilder: + _include_ = 'llvm/IRBuilder.h' + _realname_ = 'IRBuilder<>' + + new = Constructor(ref(LLVMContext)) + delete = Destructor() + + SetInsertPoint = Method(Void, ptr(BasicBlock)) + + isNamePreserving = Method(cast(Bool, bool)) + + CreateRetVoid = Method(ptr(ReturnInst)) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py new file mode 100644 index 0000000..310e19d --- /dev/null +++ b/newbinding/src/Instruction.py @@ -0,0 +1,230 @@ +from binding import * +from namespace import llvm +from Value import User + +Instruction = llvm.Class(User) +AtomicCmpXchgInst = llvm.Class(Instruction) +AtomicRMWInst = llvm.Class(Instruction) +BinaryOperator = llvm.Class(Instruction) +CallInst = llvm.Class(Instruction) +CmpInst = llvm.Class(Instruction) +ExtractElementInst = llvm.Class(Instruction) +FenceInst = llvm.Class(Instruction) +GetElementPtrInst = llvm.Class(Instruction) +InsertElementInst = llvm.Class(Instruction) +InsertValueInst = llvm.Class(Instruction) +LandingPadInst = llvm.Class(Instruction) +PHINode = llvm.Class(Instruction) +SelectInst = llvm.Class(Instruction) +ShuffleVectorInst = llvm.Class(Instruction) +StoreInst = llvm.Class(Instruction) +TerminatorInst = llvm.Class(Instruction) +UnaryInstruction = llvm.Class(Instruction) + +IntrinsicInst = llvm.Class(CallInst) + +FCmpInst = llvm.Class(CmpInst) +ICmpInst = llvm.Class(CmpInst) + + +BranchInst = llvm.Class(TerminatorInst) +IndirectBrInst = llvm.Class(TerminatorInst) +ResumeInst = llvm.Class(TerminatorInst) +ReturnInst = llvm.Class(TerminatorInst) +SwitchInst = llvm.Class(TerminatorInst) +UnreachableInst = llvm.Class(TerminatorInst) + +AllocaInst = llvm.Class(UnaryInstruction) +CastInst = llvm.Class(UnaryInstruction) +ExtractValueInst = llvm.Class(UnaryInstruction) +LoadInst = llvm.Class(UnaryInstruction) +VAArgInst = llvm.Class(UnaryInstruction) + +DbgInfoIntrinsic = llvm.Class(IntrinsicInst) +MemIntrinsic = llvm.Class(IntrinsicInst) +VACopyInst = llvm.Class(IntrinsicInst) +VAEndInst = llvm.Class(IntrinsicInst) +VAStartInst = llvm.Class(IntrinsicInst) + +BitCastInst = llvm.Class(CastInst) +FPExtInst = llvm.Class(CastInst) +FPToSIInst = llvm.Class(CastInst) +FPToUIInst = llvm.Class(CastInst) +FPTruncInst = llvm.Class(CastInst) + +@Instruction +class Instruction: + pass + + +@AtomicCmpXchgInst +class AtomicCmpXchgInst: + pass + +@AtomicRMWInst +class AtomicRMWInst: + pass + +@BinaryOperator +class BinaryOperator: + pass + +@CallInst +class CallInst: + pass + +@CmpInst +class CmpInst: + pass + +@ExtractElementInst +class ExtractElementInst: + pass + +@FenceInst +class FenceInst: + pass + +@GetElementPtrInst +class GetElementPtrInst: + pass + +@InsertElementInst +class InsertElementInst: + pass + +@InsertValueInst +class InsertValueInst: + pass + +@LandingPadInst +class LandingPadInst: + pass + +@PHINode +class PHINode: + pass + +@SelectInst +class SelectInst: + pass + +@ShuffleVectorInst +class ShuffleVectorInst: + pass + +@StoreInst +class StoreInst: + pass + +@TerminatorInst +class TerminatorInst: + pass + +@UnaryInstruction +class UnaryInstruction: + pass + +#call + +@IntrinsicInst +class IntrinsicInst: + pass + +#compare + +@FCmpInst +class FCmpInst: + pass + +@ICmpInst +class ICmpInst: + pass + +# terminator +@BranchInst +class BranchInst: + pass + + +@IndirectBrInst +class IndirectBrInst: + pass + +@ResumeInst +class ResumeInst: + pass + +@ReturnInst +class ReturnInst: + pass + +@SwitchInst +class SwitchInst: + pass + +@UnreachableInst +class UnreachableInst: + pass + +# unary +@AllocaInst +class AllocaInst: + pass + +@CastInst +class CastInst: + pass + +@ExtractValueInst +class ExtractValueInst: + pass + +@LoadInst +class LoadInst: + pass + +@VAArgInst +class VAArgInst: + pass + +# intrinsic +@DbgInfoIntrinsic +class DbgInfoIntrinsic: + pass + +@MemIntrinsic +class MemIntrinsic: + pass + +@VACopyInst +class VACopyInst: + pass + +@VAEndInst +class VAEndInst: + pass + +@VAStartInst +class VAStartInst: + pass + +@BitCastInst +class BitCastInst: + pass + +@FPExtInst +class FPExtInst: + pass + +@FPToSIInst +class FPToSIInst: + pass + +@FPToUIInst +class FPToUIInst: + pass + +@FPTruncInst +class FPTruncInst: + pass From af7962a2ca835a62074c7b0c881e982ac1655c1c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:53:01 -0600 Subject: [PATCH 053/338] Remove IterToList, llvm_extra.h. Add CustomMethod. --- newbinding/binding.py | 25 +++------ newbinding/codegen.py | 4 +- newbinding/gen.py | 1 - newbinding/include/llvm_binding/extra.h | 53 ++++++++++++++++++-- newbinding/include/llvm_binding/llvm_extra.h | 38 -------------- newbinding/src/SmallVector.py | 1 + newbinding/src/Value.py | 3 +- 7 files changed, 61 insertions(+), 64 deletions(-) delete mode 100644 newbinding/include/llvm_binding/llvm_extra.h diff --git a/newbinding/binding.py b/newbinding/binding.py index 1764559..3538c9a 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -272,28 +272,17 @@ class Method(object): writer.println() -class IterToList(Method): - def __init__(self, elemty, argtys, iterty, begin, end): - super(IterToList, self).__init__(PyObjectPtr, *argtys) - self.elemty = elemty - self.iterty = iterty - self.begin = begin - self.end = end +class CustomMethod(Method): + def __init__(self, methodname, retty, *argtys): + super(CustomMethod, self).__init__(retty, *argtys) + self.methodname = methodname def compile_cpp_body(self, writer, retty, argtys): args = writer.parse_arguments('args', ptr(self.parent), *argtys) - it = writer.method_call(self.begin, self.iterty, *args) - end = writer.method_call(self.end, self.iterty, *args) - con = writer.call('PyList_New', 'PyObject*', '0') - writer.die_if_false(con) - with writer.block('for (; %(it)s != %(end)s; ++%(it)s)' % locals()): - elem = writer.declare(self.elemty.fullname, '*%(it)s;' % locals()) - wrapped = self.elemty.wrap(writer, elem) - ok = writer.call('PyList_Append', 'int', con, wrapped) - with writer.block('if (%(ok)s == -1)' % locals()): - writer.return_value(None) - writer.return_value(con) + ret = writer.call(self.methodname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + class StaticMethod(Method): diff --git a/newbinding/codegen.py b/newbinding/codegen.py index 2a85abc..7652447 100644 --- a/newbinding/codegen.py +++ b/newbinding/codegen.py @@ -42,14 +42,14 @@ def parse_arguments(println, var, *args): return unwrapped -_re_mangle_pattern = re.compile(r'[ _<>\*&]') +_re_mangle_pattern = re.compile(r'[ _<>\*&,]') def mangle(name): def repl(m): s = m.group(0) if s in '<>*&': return '' - elif s in ' ': + elif s in ' ,': return '_' elif s in '_': return '__' diff --git a/newbinding/gen.py b/newbinding/gen.py index f1af18e..d9fc14f 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -41,7 +41,6 @@ def populate_headers(println): includes = [ 'llvm_binding/conversion.h', 'llvm_binding/binding.h', - 'llvm_binding/llvm_extra.h', 'llvm_binding/capsule_context.h', 'llvm_binding/extra.h', # extra submodule to add ] diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 94887b3..639a87c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,10 +1,43 @@ #include #include +#include #include + +namespace extra{ + using namespace llvm; + + class raw_svector_ostream_helper: public raw_svector_ostream { + SmallVectorImpl *SV; + public: + static + raw_svector_ostream_helper* create(){ + SmallVectorImpl* sv = new SmallVector(); + return new raw_svector_ostream_helper(sv); + } + + ~raw_svector_ostream_helper(){ + delete SV; + } + + protected: + + explicit + raw_svector_ostream_helper(SmallVectorImpl* sv) + : raw_svector_ostream(*sv), SV(sv) {} + + private: + // no copy + raw_svector_ostream_helper(const raw_svector_ostream_helper&); + // no assign + void operator = (const raw_svector_ostream_helper&); + }; + +} + static PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { - using llvm::raw_svector_ostream_helper; + using extra::raw_svector_ostream_helper; using llvm::raw_svector_ostream; if (!PyArg_ParseTuple(args, "")) { @@ -18,7 +51,7 @@ PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { static PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { using llvm::Type; - using llvm::SmallVector_Type; + typedef llvm::SmallVector SmallVector_Type; SmallVector_Type* SV = new SmallVector_Type; Py_ssize_t size = PyTuple_Size(args); @@ -33,7 +66,7 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { } SV->push_back(type); } - return pycapsule_new(SV, "llvm::SmallVector_Type"); + return pycapsule_new(SV, "llvm::SmallVector"); } static PyMethodDef extra_methodtable[] = { @@ -43,3 +76,17 @@ static PyMethodDef extra_methodtable[] = { #undef method { NULL } }; + + +//////////// + +PyObject* Value_use_iterator_to_list(llvm::Value* val){ + typedef llvm::Value::use_iterator iterator; + PyObject* list = PyList_New(0); + for (iterator it = val->use_begin(), end = val->use_end(); it != end; ++it) { + PyObject* cap = pycapsule_new(*it, "llvm::Value", "llvm::User"); + PyList_Append(list, cap); + } + return list; +} + diff --git a/newbinding/include/llvm_binding/llvm_extra.h b/newbinding/include/llvm_binding/llvm_extra.h deleted file mode 100644 index f920a47..0000000 --- a/newbinding/include/llvm_binding/llvm_extra.h +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -namespace llvm{ - -class Type; //forward declaration - -class raw_svector_ostream_helper: public raw_svector_ostream { - SmallVectorImpl *SV; -public: - static - raw_svector_ostream_helper* create(){ - SmallVectorImpl* sv = new SmallVector(); - return new raw_svector_ostream_helper(sv); - } - - ~raw_svector_ostream_helper(){ - delete SV; - } - -protected: - - explicit - raw_svector_ostream_helper(SmallVectorImpl* sv) - : raw_svector_ostream(*sv), SV(sv) {} - -private: - // no copy - raw_svector_ostream_helper(const raw_svector_ostream_helper&); - // no assign - void operator = (const raw_svector_ostream_helper&); -}; - -typedef SmallVector SmallVector_Type; - -} // end namespace llvm - diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index d00b294..55dadb1 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -3,4 +3,5 @@ from namespace import llvm @llvm.Class() class SmallVector_Type: + _realname_ = 'SmallVector' delete = Destructor() diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index a901946..3dd5644 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -32,8 +32,7 @@ class Value: replaceAllUsesWith = Method(Void, ptr(Value)) - list_use = IterToList(ptr(User), (), 'llvm::Value::use_iterator', - 'use_begin', 'use_end') + list_use = CustomMethod('Value_use_iterator_to_list', PyObjectPtr) hasOneUse = Method(cast(Bool, bool)) hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) From 7aa9487f2f66e7003f14fe7835de2293de4b9d60 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 16:00:25 -0600 Subject: [PATCH 054/338] pycapsule_new should return a None object if ptr is NULL. --- newbinding/include/llvm_binding/capsule_context.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index a4070dc..ed63e43 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -23,6 +23,9 @@ PyObject* pycapsule_new(void* ptr, if (!classname) { classname = basename; } + if (!ptr) { + Py_RETURN_NONE; + } PyObject* cap = PyCapsule_New(ptr, basename, NULL); if (!cap) { PyErr_SetString(PyExc_TypeError, "Error creating new PyCapsule"); From 895d1147300d13608763aa61b8ab2b9f56bd7662 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 16:36:46 -0600 Subject: [PATCH 055/338] Add CustonPythonMethod and CustonPythonStaticMethod. --- newbinding/binding.py | 24 ++++++++++++++++++++++++ newbinding/src/BasicBlock.py | 3 +++ newbinding/src/DerivedTypes.py | 19 +++++++++++++++++-- newbinding/src/Value.py | 7 +++++++ newbinding/test2.py | 26 +++++++++++++++----------- 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 3538c9a..6668452 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,3 +1,4 @@ +import inspect, textwrap import functools import codegen as cg @@ -56,6 +57,7 @@ class Class(_Type): self.bases = bases self._is_defined = False self.methods = [] + self.pymethods = [] self.enums = [] self.includes = set() self.downcastables = set() @@ -76,6 +78,8 @@ class Class(_Type): self.enums.append(v) v.name = k v.parent = self + elif isinstance(v, CustomPythonMethod): + self.pymethods.append(v) elif k == '_include_': if isinstance(v, str): self.includes.add(v) @@ -122,6 +126,8 @@ class Class(_Type): enum.compile_py(writer) for meth in self.methods: meth.compile_py(writer) + for meth in self.pymethods: + meth.compile_py(writer) writer.println() @property @@ -453,3 +459,21 @@ class cast(_Type): +class CustomPythonMethod(object): + def __init__(self, fn): + src = inspect.getsource(fn) + lines = textwrap.dedent(src).splitlines() + for i, line in enumerate(lines): + if not line.startswith('@'): + break + self.sourcelines = lines[i:] + + def compile_py(self, writer): + for line in self.sourcelines: + writer.println(line) + +class CustomPythonStaticMethod(CustomPythonMethod): + def compile_py(self, writer): + writer.println('@staticmethod') + super(CustomPythonStaticMethod, self).compile_py(writer) + diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py index c7221a5..b0716cd 100644 --- a/newbinding/src/BasicBlock.py +++ b/newbinding/src/BasicBlock.py @@ -1,6 +1,7 @@ from binding import * from namespace import llvm from Value import Function, BasicBlock +from Instruction import Instruction, TerminatorInst from LLVMContext import LLVMContext from StringRef import StringRef @@ -12,6 +13,8 @@ class BasicBlock: ptr(BasicBlock)) getParent = Method(ptr(Function)) + getTerminator = Method(ptr(TerminatorInst)) + empty = Method(cast(Bool, bool)) dropAllReferences = Method() isLandingPad = Method(cast(Bool, bool)) diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index c57e01b..efce8b8 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -9,8 +9,23 @@ FunctionType = llvm.Class(Type) @FunctionType class FunctionType: _include_ = 'llvm/DerivedTypes.h' - get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) - get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), cast(bool, Bool)) + + _get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) + _get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), + cast(bool, Bool)) + _get.realname = 'get' + + @CustomPythonStaticMethod + def get(*args): + import extra + if len(args) == 3: + typelist = args[1] + sv = extra.make_small_vector_from_types(*typelist) + return FunctionType._get(args[0], sv, args[2]) + else: + return FunctionType._get(*args) + + isVarArg = Method(cast(Bool, bool)) getReturnType = Method(ptr(Type)) getParamType = Method(ptr(Type), cast(int, Unsigned)) diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 3dd5644..5345337 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -37,3 +37,10 @@ class Value: hasOneUse = Method(cast(Bool, bool)) hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) isUsedInBasicBlock = Method(cast(Bool, bool), BasicBlock) + + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() diff --git a/newbinding/test2.py b/newbinding/test2.py index 810a7ba..3e54aee 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -30,24 +30,18 @@ fnty = api.FunctionType.get(int1ty, False) fnty.dump() types = [int1ty, api.Type.getIntNTy(context, 21)] -svt = extra.make_small_vector_from_types(*types) -fnty = api.FunctionType.get(int1ty, svt, False) +fnty = api.FunctionType.get(int1ty, types, False) -os = extra.make_raw_ostream_for_printing() -fnty.print_(os) -print os.str() +print fnty const = m.getOrInsertFunction("foo", fnty) fn = extra.downcast(const, api.Function) -os = extra.make_raw_ostream_for_printing() -fn.print_(os, None) -print os.str() +print fn assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') assert 'bar' == fn.getName() -os = extra.make_raw_ostream_for_printing() assert fn.getReturnType() is int1ty assert fnty is fn.getFunctionType() @@ -56,14 +50,24 @@ assert fn.isVarArg() == False assert fn.getIntrinsicID() == 0 assert not fn.isIntrinsic() -print fn.list_use() +fn_uselist = fn.list_use() +assert isinstance(fn_uselist, list) +assert len(fn_uselist) == 0 builder = api.IRBuilder.new(context) print builder bb = api.BasicBlock.Create(context, "entry", fn, None) +assert bb.empty() builder.SetInsertPoint(bb) +assert bb.getTerminator() is None + builder.CreateRetVoid() -fn.dump() +assert not bb.empty() +assert bb.getTerminator() is not None + +print bb + + From 59d0dfddc733f44252c244bd0a5d496337f82000 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 17:55:52 -0600 Subject: [PATCH 056/338] Continue to implement IRBuilder --- newbinding/capsule.py | 8 ++- newbinding/include/llvm_binding/extra.h | 87 ++++++++++++++++++++++--- newbinding/src/Argument.py | 9 +++ newbinding/src/Function.py | 4 +- newbinding/src/IRBuilder.py | 19 +++++- newbinding/src/SmallVector.py | 6 ++ newbinding/src/Value.py | 1 + newbinding/test2.py | 10 +-- 8 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 newbinding/src/Argument.py diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 47c32fb..eaef7da 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -52,8 +52,10 @@ def wrap(cap): '''Wrap a PyCapsule with the corresponding Wrapper class. If `cap` is not a PyCapsule, returns `cap` ''' - if not _capsule.check(cap): # bypass if cap is not a PyCapsule - return cap + if not _capsule.check(cap): + if isinstance(cap, list): + return map(wrap, cap) + return cap # bypass if cap is not a PyCapsule and not a list addr = _capsule.getPointer(cap) try: # find cached object by pointer address @@ -77,7 +79,7 @@ def wrap(cap): # do auto downcast pass else: - assert oldcls is newcls + assert oldcls is newcls, (cap, obj, oldcls, newcls) return obj def downcast(old, new): diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 639a87c..9f2bd70 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -11,12 +12,14 @@ namespace extra{ SmallVectorImpl *SV; public: static - raw_svector_ostream_helper* create(){ + raw_svector_ostream_helper* create() + { SmallVectorImpl* sv = new SmallVector(); return new raw_svector_ostream_helper(sv); } - ~raw_svector_ostream_helper(){ + ~raw_svector_ostream_helper() + { delete SV; } @@ -36,7 +39,8 @@ namespace extra{ } static -PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { +PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) +{ using extra::raw_svector_ostream_helper; using llvm::raw_svector_ostream; @@ -49,7 +53,8 @@ PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { } static -PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { +PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) +{ using llvm::Type; typedef llvm::SmallVector SmallVector_Type; @@ -69,24 +74,88 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { return pycapsule_new(SV, "llvm::SmallVector"); } +static +PyObject* make_small_vector_from_values(PyObject* self, PyObject* args) +{ + using llvm::Value; + typedef llvm::SmallVector SmallVector_Value; + + SmallVector_Value* SV = new SmallVector_Value; + Py_ssize_t size = PyTuple_Size(args); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject* cap = PyTuple_GetItem(args, i); + if (!cap) { + return NULL; + } + Value* value = (Value*)PyCapsule_GetPointer(cap, "llvm::Value"); + if (!value) { + return NULL; + } + SV->push_back(value); + } + return pycapsule_new(SV, "llvm::SmallVector"); +} + + static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } method( make_raw_ostream_for_printing ), method( make_small_vector_from_types ), + method( make_small_vector_from_values ), #undef method { NULL } }; //////////// - -PyObject* Value_use_iterator_to_list(llvm::Value* val){ - typedef llvm::Value::use_iterator iterator; +template +PyObject* iterator_to_pylist_deref(iterator begin, iterator end, + const char *capsuleName, const char *className) +{ PyObject* list = PyList_New(0); - for (iterator it = val->use_begin(), end = val->use_end(); it != end; ++it) { - PyObject* cap = pycapsule_new(*it, "llvm::Value", "llvm::User"); + for(; begin != end; ++begin) { + PyObject* cap = pycapsule_new(&*begin, capsuleName, className); PyList_Append(list, cap); } return list; } +template +PyObject* iterator_to_pylist(iterator begin, iterator end, + const char *capsuleName, const char *className) +{ + PyObject* list = PyList_New(0); + for(; begin != end; ++begin) { + PyObject* cap = pycapsule_new(*begin, capsuleName, className); + PyList_Append(list, cap); + } + return list; +} + +template +PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, + const char* className){ + return iterator_to_pylist_deref(IPL.begin(), IPL.end(), capsuleName, + className); +} + +static +PyObject* Value_use_iterator_to_list(llvm::Value* val) +{ + return iterator_to_pylist(val->use_begin(), val->use_end(), + "llvm::Value", "llvm::User"); +} + +static +PyObject* Function_getArgumentList(llvm::Function* fn) +{ + return iplist_to_pylist(fn->getArgumentList(), "llvm::Value", + "llvm::Argument"); +} + +static +PyObject* Function_getBasicBlockList(llvm::Function* fn) +{ + return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value", + "llvm::BasicBlock"); +} \ No newline at end of file diff --git a/newbinding/src/Argument.py b/newbinding/src/Argument.py new file mode 100644 index 0000000..08b35be --- /dev/null +++ b/newbinding/src/Argument.py @@ -0,0 +1,9 @@ +from binding import * +from namespace import llvm +from Value import Argument + +@Argument +class Argument: + _include_ = 'llvm/Argument.h' + + diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index f069e30..5cebf84 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from Value import GlobalValue, Constant, Function +from Value import GlobalValue, Constant, Function, Argument from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext @@ -17,3 +17,5 @@ class Function: getIntrinsicID = Method(cast(Unsigned, int)) isIntrinsic = Method(cast(Bool, bool)) + getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) + getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index 0919a67..41e6681 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -2,7 +2,10 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from BasicBlock import BasicBlock -from Instruction import ReturnInst +from Instruction import ReturnInst, CallInst +from SmallVector import SmallVector_Value +from StringRef import StringRef +from Value import Value IRBuilder = llvm.Class() @@ -19,3 +22,17 @@ class IRBuilder: isNamePreserving = Method(cast(Bool, bool)) CreateRetVoid = Method(ptr(ReturnInst)) + CreateRet = Method(ptr(ReturnInst), ptr(Value)) + + _CreateCall = Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value), + cast(str, StringRef)) + _CreateCall |= Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value)) + _CreateCall.realname = 'CreateCall' + + @CustomPythonMethod + def CreateCall(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return IRBuilder._CreateCall(self, *args) diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index 55dadb1..594faf8 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -5,3 +5,9 @@ from namespace import llvm class SmallVector_Type: _realname_ = 'SmallVector' delete = Destructor() + +@llvm.Class() +class SmallVector_Value: + _realname_ = 'SmallVector' + delete = Destructor() + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5345337..5b907bd 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -8,6 +8,7 @@ from StringRef import StringRef Value = llvm.Class() # forward declarations +Argument = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) diff --git a/newbinding/test2.py b/newbinding/test2.py index 3e54aee..a7a4ddd 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -63,11 +63,11 @@ builder.SetInsertPoint(bb) assert bb.getTerminator() is None -builder.CreateRetVoid() +arg0, arg1 = fn.getArgumentList() +print arg0, arg1 -assert not bb.empty() -assert bb.getTerminator() is not None - -print bb +ret = builder.CreateCall(fn, [arg0, arg1], '') +builder.CreateRet(ret) +print fn From 437b1e949012595882f8fbb3065c0c7e4c9b0835 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 29 Jan 2013 17:47:15 -0600 Subject: [PATCH 057/338] All of DataLayout, IRBuilder and started on ExecutionEngine. --- newbinding/binding.py | 114 ++++++++- newbinding/capsule.py | 22 +- newbinding/codegen.py | 12 +- newbinding/gen.py | 11 +- .../include/llvm_binding/capsule_context.h | 10 + newbinding/include/llvm_binding/extra.h | 81 +++++- newbinding/src/CodeGen.py | 19 ++ newbinding/src/DataLayout.py | 97 +++++++ newbinding/src/ExecutionEngine.py | 34 +++ newbinding/src/GlobalVariable.py | 8 + newbinding/src/IRBuilder.py | 241 +++++++++++++++++- newbinding/src/Instruction.py | 32 ++- newbinding/src/JITMemoryManager.py | 7 + newbinding/src/Metadata.py | 7 + newbinding/src/Module.py | 3 +- newbinding/src/SmallVector.py | 4 + newbinding/src/TargetSelect.py | 8 + newbinding/src/Type.py | 4 + newbinding/src/Value.py | 1 + newbinding/test2.py | 14 + 20 files changed, 688 insertions(+), 41 deletions(-) create mode 100644 newbinding/src/CodeGen.py create mode 100644 newbinding/src/DataLayout.py create mode 100644 newbinding/src/ExecutionEngine.py create mode 100644 newbinding/src/GlobalVariable.py create mode 100644 newbinding/src/JITMemoryManager.py create mode 100644 newbinding/src/Metadata.py create mode 100644 newbinding/src/TargetSelect.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 6668452..f7d5ac4 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -5,11 +5,15 @@ import codegen as cg _rank = 0 namespaces = {} +RESERVED = frozenset(['None']) + class Namespace(object): def __init__(self, name): self.name = name + self.enums = [] self.classes = [] self.functions = [] + self.includes = set() namespaces[name] = self def Class(self, *bases): @@ -22,6 +26,13 @@ class Namespace(object): self.functions.append(fn) return fn + def Enum(self, name, *value_names): + enum = Enum(*value_names) + enum.parent = self + enum.name = name + self.enums.append(enum) + return enum + @property def fullname(self): return self.name @@ -43,11 +54,16 @@ class BuiltinTypes(_Type): def wrap(self, writer, var): return var + def unwrap(self, writer, var): + return var + Void = BuiltinTypes('void') Unsigned = BuiltinTypes('unsigned') +Uint64 = BuiltinTypes('uint64_t') Bool = BuiltinTypes('bool') ConstStdString = BuiltinTypes('const std::string') PyObjectPtr = BuiltinTypes('PyObject*') +PyObjectPtr.format='O' class Class(_Type): format = 'O' @@ -78,6 +94,7 @@ class Class(_Type): self.enums.append(v) v.name = k v.parent = self + setattr(self, k, v) elif isinstance(v, CustomPythonMethod): self.pymethods.append(v) elif k == '_include_': @@ -108,7 +125,7 @@ class Class(_Type): fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' for meth in self.methods: name = meth.name - func = cg.mangle(meth.fullname) + func = meth.c_name writer.println(fmt % locals()) writer.println('{ NULL },') writer.println('};') @@ -161,9 +178,12 @@ class Class(_Type): return casted class Enum(object): + format = 'O' + def __init__(self, *value_names): self.parent = None self.value_names = value_names + self.includes = set() @property def fullname(self): @@ -191,11 +211,34 @@ class Enum(object): writer.raises(ValueError, 'Invalid enum %s' % v) return ret + def unwrap(self, writer, val): + tostring = 'PyString_AsString(%(val)s)' % locals() + string = writer.declare('const char*', tostring) + ret = writer.declare('%s::%s' % (self.parent, self.name)) + parent = self.parent + iffmt = 'if (string_equal(%(string)s, "%(v)s"))' + for i, v in enumerate(self.value_names): + with writer.block(iffmt % locals()): + fmt = '%(ret)s = %(parent)s::%(v)s;' + writer.println(fmt % locals()) + if i == 0: + iffmt = 'else ' + iffmt + with writer.block('else'): + writer.raises(ValueError, 'Invalid enum.') + return ret + + def compile_cpp(self, writer): + pass + def compile_py(self, writer): with writer.block('class %s:' % self.name): writer.println('_llvm_type_ = "%s"' % self.fullname) for v in self.value_names: - writer.println('%(v)s = "%(v)s"' % locals()) + if v in RESERVED: + k = '%s_' % v + else: + k = v + writer.println('%(k)s = "%(v)s"' % locals()) writer.println() class Method(object): @@ -236,11 +279,15 @@ class Method(object): def realname(self, v): self.__realname = v + @property + def c_name(self): + return cg.mangle("%s_%s" % (self.parent, self.name)) + def __str__(self): return self.fullname def compile_cpp(self, writer): - with writer.py_function(self.fullname): + with writer.py_function(self.c_name): if len(self.signatures) == 1: sig = self.signatures[0] retty = sig[0] @@ -270,13 +317,40 @@ class Method(object): with decl as (this, varargs): unwrap_this = writer.unwrap(this) unwrapped = writer.unwrap_many(varargs) + self.process_ownedptr_args(writer, unwrapped) + func = '.'.join([self.parent.name, self.name]) ret = writer.call('_api.%s' % func, args=(unwrap_this,), varargs=unwrapped) - wrapped = writer.wrap(ret) + + wrapped = writer.wrap(ret, self.is_return_ownedptr()) + writer.return_value(wrapped) writer.println() + def require_only(self, num): + '''Require only "num" of argument. + ''' + assert len(self.signatures) == 1 + sig = self.signatures[0] + ret = sig[0] + args = sig[1:] + arg_ct = len(args) + + for i in range(num, arg_ct): + self._add_signature(ret, *args[:i]) + + return self + + def is_return_ownedptr(self): + retty = self.signatures[0][0] + return isinstance(retty, ownedptr) + + def process_ownedptr_args(self, writer, unwrapped): + argtys = self.signatures[0][1:] + for i, ty in enumerate(argtys): + if isinstance(ty, ownedptr): + writer.release_ownership('%s[%d]' % (unwrapped, i)) class CustomMethod(Method): def __init__(self, methodname, retty, *argtys): @@ -289,7 +363,6 @@ class CustomMethod(Method): writer.return_value(retty.wrap(writer, ret)) - class StaticMethod(Method): def compile_cpp_body(self, writer, retty, argtys): @@ -307,12 +380,24 @@ class StaticMethod(Method): decl = writer.function(self.name, varargs='args') with decl as varargs: unwrapped = writer.unwrap_many(varargs) + self.process_ownedptr_args(writer, unwrapped) + func = '.'.join([self.parent.name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) - wrapped = writer.wrap(ret) + wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() +class CustomStaticMethod(StaticMethod): + def __init__(self, methodname, retty, *argtys): + super(CustomStaticMethod, self).__init__(retty, *argtys) + self.methodname = methodname + + def compile_cpp_body(self, writer, retty, argtys): + args = writer.parse_arguments('args', *argtys) + ret = writer.call(self.methodname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + class Function(Method): _kind_ = 'func' @@ -329,10 +414,11 @@ class Function(Method): def compile_py(self, writer): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) + self.process_ownedptr_args(writer, unwrapped) func = self.fullname.split('::', 1)[1].replace('::', '.') ret = writer.call('_api.%s' % func, varargs=unwrapped) - wrapped = writer.wrap(ret) + wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() @@ -400,10 +486,14 @@ class ptr(_Type): def __init__(self, element): assert isinstance(element, Class) self.element = element + self.const = False @property def fullname(self): - return '%s*' % self.element + if self.const: + return 'const %s*' % self.element + else: + return '%s*' % self.element @property def format(self): @@ -420,6 +510,13 @@ class ptr(_Type): return writer.pycapsule_new(val, self.element.capsule_name, self.element.fullname) +class ownedptr(ptr): + pass + +def const(ptr): + ptr.const = True + return ptr + class cast(_Type): format = 'O' @@ -458,7 +555,6 @@ class cast(_Type): return ret - class CustomPythonMethod(object): def __init__(self, fn): src = inspect.getsource(fn) diff --git a/newbinding/capsule.py b/newbinding/capsule.py index eaef7da..f489c7f 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -23,10 +23,11 @@ class WeakRef(ref): _pyclasses = {} _addr2obj = WeakValueDictionary() -_owners = {} +_owners = {} # address to weak reference def _sentry(ptr): - assert _capsule.check(ptr) + if not _capsule.check(ptr): + raise ValueError('Must provide a PyCapsule object.') def classof(cap): cls = _capsule.getClassName(cap) @@ -38,17 +39,16 @@ def _capsule_destructor(weak): addr = _capsule.getPointer(cap) cls = _capsule.getClassName(cap) logger.debug("destroy pointer 0x%08X to %s", addr, cls) - weak.dtor(cap) +# weak.dtor(cap) del _owners[addr] def release_ownership(old): addr = _capsule.getPointer(old) - if hasattr(old, '_delete_'): - oldweak = _owners[addr] - oldweak.owning = False # dis-own - del _owners[addr] + oldweak = _owners[addr] + oldweak.owning = False # dis-own + del _owners[addr] -def wrap(cap): +def wrap(cap, owned=False): '''Wrap a PyCapsule with the corresponding Wrapper class. If `cap` is not a PyCapsule, returns `cap` ''' @@ -66,7 +66,8 @@ def wrap(cap): obj = cls(cap) _addr2obj[addr] = obj # cache object by address # set ownership if *cls* defines *_delete_* - if hasattr(cls, '_delete_'): + if not owned and hasattr(cls, '_delete_'): + assert addr not in _owners, "has existing owner" weak = WeakRef(obj, _capsule_destructor) _owners[addr] = weak weak.capsule = cap @@ -84,10 +85,11 @@ def wrap(cap): def downcast(old, new): assert old is not new + assert _capsule.getPointer(old) not in _owners oldcls = classof(old) newcls = classof(new) assert issubclass(newcls, oldcls) - release_ownership(old) + # release_ownership(old) del _addr2obj[_capsule.getPointer(old)] # clear cache return wrap(new) diff --git a/newbinding/codegen.py b/newbinding/codegen.py index 7652447..5a31e38 100644 --- a/newbinding/codegen.py +++ b/newbinding/codegen.py @@ -104,10 +104,9 @@ class CodeWriterBase(object): @contextlib.contextmanager def py_function(self, name): - mangled = mangle(name) self.println('static') self.println('PyObject*') - with self.block('%(mangled)s(PyObject* self, PyObject* args)' % locals()): + with self.block('%(name)s(PyObject* self, PyObject* args)' % locals()): self.used_symbols.add('self') self.used_symbols.add('args') yield @@ -175,7 +174,7 @@ class CppCodeWriter(CodeWriterBase): arglist = ', '.join(args) stmt = '%(func)s(%(arglist)s)' % locals() if retty == 'void': - self.println(stmt) + self.println(stmt + ';') else: return self.declare(retty, stmt) @@ -247,6 +246,9 @@ class PyCodeWriter(CodeWriterBase): yield self.used_symbols = self.old + def release_ownership(self, val): + self.println('capsule.release_ownership(%(val)s)' % locals()) + def unwrap_many(self, args): unwrapped = self.new_symbol('unwrapped') self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) @@ -255,9 +257,9 @@ class PyCodeWriter(CodeWriterBase): def unwrap(self, val): return self.call('capsule.unwrap', args=(val,), ret='unwrapped') - def wrap(self, val): + def wrap(self, val, owned): wrapped = self.new_symbol('wrapped') - self.println('%(wrapped)s = capsule.wrap(%(val)s)' % locals()) + self.println('%(wrapped)s = capsule.wrap(%(val)s, %(owned)s)' % locals()) return wrapped def call(self, func, args=(), varargs=None, ret='ret'): diff --git a/newbinding/gen.py b/newbinding/gen.py index d9fc14f..47f5655 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -39,6 +39,7 @@ populate_submodules(module, submodules); def populate_headers(println): includes = [ + 'cstring', 'llvm_binding/conversion.h', 'llvm_binding/binding.h', 'llvm_binding/capsule_context.h', @@ -70,6 +71,9 @@ def main(): for cls in ns.classes: print cls units.append(cls) + for enum in ns.enums: + print enum + units.append(enum) # add extra stuffs downcastlist = [] @@ -84,7 +88,7 @@ def main(): units.append(fn) - # generate cpp source + # Generate C++ source with open('%s.cpp' % outputfilename, 'w') as cppfile: println = wrap_println_from_file(cppfile) @@ -93,6 +97,8 @@ def main(): # required headers includes = set() + for ns in namespaces.values(): + includes |= ns.includes for u in units: includes |= u.includes @@ -128,7 +134,7 @@ static for u in units: if isinstance(u, Function): name = u.name - func = codegen.mangle(u.fullname) + func = u.c_name writer.println(fmt % locals()) writer.println('{ NULL },') writer.println('};') @@ -154,6 +160,7 @@ static println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) + # Generate Python source with open('%s.py' % outputfilename, 'w') as pyfile: println = wrap_println_from_file(pyfile) println('import _api, capsule') diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index ed63e43..6ed1381 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -39,6 +39,16 @@ PyObject* pycapsule_new(void* ptr, } +static +PyObject* pycapsule_new(const void* ptr, + const char* basename, + const char* classname=NULL) +{ + // Use const_cast to strip the constantness. + // Let the user take the responsibility. + return pycapsule_new(const_cast(ptr), basename, classname); +} + #endif //LLVMPY_CAPSULE_CONTEXT_H_ diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 9f2bd70..b5edd2c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,7 +3,7 @@ #include #include #include - +#include namespace extra{ using namespace llvm; @@ -97,11 +97,34 @@ PyObject* make_small_vector_from_values(PyObject* self, PyObject* args) } +static +PyObject* make_small_vector_from_unsigned(PyObject* self, PyObject* args) +{ + using llvm::Value; + typedef llvm::SmallVector SmallVector_Unsigned; + + SmallVector_Unsigned* SV = new SmallVector_Unsigned; + Py_ssize_t size = PyTuple_Size(args); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject* item = PyTuple_GetItem(args, i); + if (!item) { + return NULL; + } + unsigned value = PyLong_AsUnsignedLong(item); + if (PyErr_Occurred()){ + return NULL; + } + SV->push_back(value); + } + return pycapsule_new(SV, "llvm::SmallVector"); +} + static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } method( make_raw_ostream_for_printing ), method( make_small_vector_from_types ), method( make_small_vector_from_values ), + method( make_small_vector_from_unsigned ), #undef method { NULL } }; @@ -139,11 +162,20 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, className); } +static +bool string_equal(const char *A, const char *B){ + for (; *A and *B; ++A, ++B) { + if (*A != *B) return false; + } + return true; +} + +//////////// static PyObject* Value_use_iterator_to_list(llvm::Value* val) { return iterator_to_pylist(val->use_begin(), val->use_end(), - "llvm::Value", "llvm::User"); + "llvm::Value", "llvm::User"); } static @@ -158,4 +190,47 @@ PyObject* Function_getBasicBlockList(llvm::Function* fn) { return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value", "llvm::BasicBlock"); -} \ No newline at end of file +} + +/* + * errout --- can be any file object + * + */ +static +llvm::ExecutionEngine* ExecutionEngine_create( + llvm::Module* M, + bool ForceInterpreter = false, + PyObject* errout = 0, + llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default, + bool GVsWithCode = true) +{ + using namespace llvm; + std::string ErrorStr; + ExecutionEngine *ee = ExecutionEngine::create(M, ForceInterpreter, + &ErrorStr, OptLevel, + GVsWithCode); + PyFile_WriteString(ErrorStr.c_str(), errout); + return ee; +} + +/* + * errout --- can be any file object + * + */ +static +llvm::ExecutionEngine* ExecutionEngine_createJIT( + llvm::Module* M, + PyObject* errout = 0, + llvm::JITMemoryManager* JMM = 0, + llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default, + bool GCsWithCode = true, + llvm::Reloc::Model RM = llvm::Reloc::Default, + llvm::CodeModel::Model CMM = llvm::CodeModel::JITDefault) +{ + using namespace llvm; + std::string ErrorStr; + ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL, + GCsWithCode, RM, CMM); + PyFile_WriteString(ErrorStr.c_str(), errout); + return ee; +} diff --git a/newbinding/src/CodeGen.py b/newbinding/src/CodeGen.py new file mode 100644 index 0000000..06821aa --- /dev/null +++ b/newbinding/src/CodeGen.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm + +@llvm.Class() +class Reloc: + Model = Enum('Default', 'Static', 'PIC_', 'DynamicNoPIC') + +@llvm.Class() +class CodeModel: + Model = Enum('Default', 'JITDefault', 'Small', 'Kernel', 'Medium', 'Large') + +@llvm.Class() +class TLSModel: + Model = Enum('GeneralDynamic', 'LocalDynamic', 'InitialExec', 'LocalExec') + +@llvm.Class() +class CodeGenOpt: + 'Actually a namespace' + Level = Enum('None', 'Less', 'Default', 'Aggressive') diff --git a/newbinding/src/DataLayout.py b/newbinding/src/DataLayout.py new file mode 100644 index 0000000..a1ef8bc --- /dev/null +++ b/newbinding/src/DataLayout.py @@ -0,0 +1,97 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from StringRef import StringRef +from Module import Module +from Type import Type, IntegerType, StructType +from SmallVector import SmallVector_Value +from GlobalVariable import GlobalVariable + +DataLayout = llvm.Class() +StructLayout = llvm.Class() + +@DataLayout +class DataLayout: + _include_ = 'llvm/DataLayout.h' + + _new_string = Constructor(cast(str, StringRef)) + _new_module = Constructor(ptr(Module)) + + @CustomPythonStaticMethod + def new(arg): + if isinstance(arg, Module): + return DataLayout._new_module(arg) + else: + return DataLayout._new_string(arg) + + delete = Destructor() + + isLittleEndian = Method(cast(Bool, bool)) + isBigEndian = Method(cast(Bool, bool)) + + getStringRepresentation = Method(cast(StringRef, str)) + + @CustomPythonMethod + def __str__(self): + return self.getStringRepresentation() + + isLegalInteger = Method(cast(Bool, bool), cast(int, Unsigned)) + isIllegalInteger = Method(cast(Bool, bool), cast(int, Unsigned)) + exceedsNaturalStackAlignment = Method(cast(Bool, bool), cast(int, Unsigned)) + fitsInLegalInteger = Method(cast(Bool, bool), cast(int, Unsigned)) + + getPointerABIAlignment = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + getPointerPrefAlignment = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + getPointerSize = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + getPointerSizeInBits = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + + getTypeSizeInBits = Method(cast(Uint64, int), ptr(Type)) + getTypeStoreSize = Method(cast(Uint64, int), ptr(Type)) + getTypeStoreSizeInBits = Method(cast(Uint64, int), ptr(Type)) + getTypeAllocSize = Method(cast(Uint64, int), ptr(Type)) + getTypeAllocSizeInBits = Method(cast(Uint64, int), ptr(Type)) + + getABITypeAlignment = Method(cast(Unsigned, int), ptr(Type)) + getABIIntegerTypeAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) + getCallFrameTypeAlignment = Method(cast(Unsigned, int), ptr(Type)) + getPrefTypeAlignment = Method(cast(Unsigned, int), ptr(Type)) + getPreferredTypeAlignmentShift = Method(cast(Unsigned, int), ptr(Type)) + + _getIntPtrType = Method(ptr(IntegerType), + ref(LLVMContext), cast(int, Unsigned)) + _getIntPtrType.require_only(1) + _getIntPtrType.realname = 'getIntPtrType' + + _getIntPtrType2 = Method(ptr(Type), ptr(Type)) + _getIntPtrType2.realname = 'getIntPtrType' + + @CustomPythonMethod + def getIntPtrType(self, *args): + if isinstance(args[0], LLVMContext): + return self._getIntPtrType(*args) + else: + return self._getIntPtrType(*args) + + _getIndexedOffset = Method(cast(Uint64, int), ptr(Type), + ref(SmallVector_Value)) + _getIndexedOffset.realname = 'getIndexedOffset' + + @CustomPythonMethod + def getIndexedOffset(self, *args): + import extra + args = list(args) + args[1] = extra.make_small_vector_from_values(args[1]) + return self.getIndexedOffset(*args) + + getStructLayout = Method(const(ptr(StructLayout)), ptr(StructType)) + + getPreferredAlignment = Method(cast(Unsigned, int), ptr(GlobalVariable)) + getPreferredAlignmentLog = Method(cast(Unsigned, int), ptr(GlobalVariable)) + +@StructLayout +class StructLayout: + pass diff --git a/newbinding/src/ExecutionEngine.py b/newbinding/src/ExecutionEngine.py new file mode 100644 index 0000000..0fbe387 --- /dev/null +++ b/newbinding/src/ExecutionEngine.py @@ -0,0 +1,34 @@ +from binding import * +from namespace import llvm +from Module import Module +from JITMemoryManager import JITMemoryManager +from CodeGen import CodeGenOpt, Reloc, CodeModel +from DataLayout import DataLayout + +ExecutionEngine = llvm.Class() + +@ExecutionEngine +class ExecutionEngine: + _include_ = ('llvm/ExecutionEngine/ExecutionEngine.h', + 'llvm/ExecutionEngine/JIT.h') # force linking of jit + + delete = Destructor() + + create = CustomStaticMethod('ExecutionEngine_create', + ptr(ExecutionEngine), + ownedptr(Module), cast(bool, Bool), + PyObjectPtr, CodeGenOpt.Level, + cast(bool, Bool)).require_only(1) + + createJIT = CustomStaticMethod('ExecutionEngine_createJIT', + ptr(ExecutionEngine), + ownedptr(Module), PyObjectPtr, + ptr(JITMemoryManager), + CodeGenOpt.Level, + cast(bool, Bool), + Reloc.Model, + CodeModel.Model).require_only(1) + + addModule = Method(Void, ptr(Module)) + getDataLayout = Method(const(ownedptr(DataLayout))) + removeModule = Method(cast(Bool, bool), ptr(Module)) diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py new file mode 100644 index 0000000..548a8d1 --- /dev/null +++ b/newbinding/src/GlobalVariable.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm +from GlobalValue import GlobalValue + +@llvm.Class(GlobalValue) +class GlobalVariable: + pass + diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index 41e6681..cea94ce 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -2,10 +2,16 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from BasicBlock import BasicBlock -from Instruction import ReturnInst, CallInst -from SmallVector import SmallVector_Value +from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst +from Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode +from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst +from Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst +from Instruction import LandingPadInst, VAArgInst +from Instruction import AtomicOrdering, SynchronizationScope +from SmallVector import SmallVector_Value, SmallVector_Unsigned from StringRef import StringRef -from Value import Value +from Value import Value, MDNode +from Type import Type, IntegerType IRBuilder = llvm.Class() @@ -24,15 +30,238 @@ class IRBuilder: CreateRetVoid = Method(ptr(ReturnInst)) CreateRet = Method(ptr(ReturnInst), ptr(Value)) - _CreateCall = Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value), + CreateBr = Method(ptr(BranchInst), ptr(BasicBlock)) + + + CreateCondBr = Method(ptr(BranchInst), ptr(Value), ptr(BasicBlock), + ptr(BasicBlock), ptr(MDNode)).require_only(3) + + CreateSwitch = Method(ptr(SwitchInst), ptr(Value), ptr(BasicBlock), + cast(int, Unsigned), ptr(MDNode)).require_only(2) + + CreateIndirectBr = Method(ptr(IndirectBrInst), ptr(Value), + cast(int, Unsigned)).require_only(1) + + CreateInvoke = Method(ptr(InvokeInst), ptr(Value), ptr(BasicBlock), + ptr(BasicBlock), ref(SmallVector_Value), + cast(str, StringRef)).require_only(4) + + CreateResume = Method(ptr(ResumeInst), ptr(Value)) + + CreateUnreachable = Method(ptr(UnreachableInst)) + + def _binop_has_nsw_nuw(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef), + cast(bool, Bool), cast(bool, Bool)] + op = Method(*sig).require_only(2) + return op + + CreateAdd = _binop_has_nsw_nuw() + CreateSub = _binop_has_nsw_nuw() + CreateMul = _binop_has_nsw_nuw() + CreateShl = _binop_has_nsw_nuw() + + def _binop_is_exact(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef), + cast(bool, Bool)] + op = Method(*sig).require_only(2) + return op + + CreateUDiv = _binop_is_exact() + CreateSDiv = _binop_is_exact() + CreateLShr = _binop_is_exact() + CreateAShr = _binop_is_exact() + + def _binop_basic(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef)] + op = Method(*sig).require_only(2) + return op + + CreateURem = _binop_basic() + CreateSRem = _binop_basic() + CreateAnd = _binop_basic() + CreateOr = _binop_basic() + CreateXor = _binop_basic() + + def _float_binop(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef), + ptr(MDNode)] + op = Method(*sig).require_only(2) + return op + + CreateFAdd = _float_binop() + CreateFSub = _float_binop() + CreateFMul = _float_binop() + CreateFDiv = _float_binop() + CreateFRem = _float_binop() + + def _unop_has_nsw_nuw(): + sig = [ptr(Value), ptr(Value), cast(str, StringRef), + cast(bool, Bool), cast(bool, Bool)] + op = Method(*sig).require_only(1) + return op + + CreateNeg = _unop_has_nsw_nuw() + + def _float_unop(): + sig = [ptr(Value), ptr(Value), cast(str, StringRef), ptr(MDNode)] + op = Method(*sig).require_only(1) + return op + + CreateFNeg = _float_unop() + + CreateNot = Method(ptr(Value), + ptr(Value), cast(str, StringRef)).require_only(1) + + + CreateAlloca = Method(ptr(AllocaInst), ptr(Type), ptr(Value), + cast(str, StringRef)).require_only(2) + + CreateLoad = Method(ptr(LoadInst), + ptr(Value), cast(str, StringRef)).require_only(1) + + CreateStore = Method(ptr(StoreInst), ptr(Value), ptr(Value), + cast(bool, Bool)).require_only(2) + + CreateAlignedLoad = Method(ptr(LoadInst), ptr(Value), cast(int, Unsigned), + cast(bool, Bool), cast(str, StringRef)) + CreateAlignedLoad.require_only(2) + + CreateAlignedStore = Method(ptr(StoreInst), ptr(Value), ptr(Value), + cast(int, Unsigned), cast(bool, Bool)) + CreateAlignedStore.require_only(3) + + CreateFence = Method(ptr(FenceInst), + AtomicOrdering, SynchronizationScope).require_only(1) + + CreateAtomicCmpXchg = Method(ptr(AtomicCmpXchgInst), ptr(Value), ptr(Value), + ptr(Value), AtomicOrdering, SynchronizationScope) + CreateAtomicCmpXchg.require_only(4) + + CreateAtomicRMW = Method(ptr(AtomicRMWInst), AtomicRMWInst.BinOp, + ptr(Value), ptr(Value), AtomicOrdering, + SynchronizationScope) + CreateAtomicRMW.require_only(4) + + _CreateGEP = Method(ptr(Value), ptr(Value), ref(SmallVector_Value), + cast(str, StringRef)) + _CreateGEP.require_only(2) + _CreateGEP.realname = 'CreateGEP' + + @CustomPythonMethod + def CreateGEP(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return self._CreateGEP(*args) + + _CreateInBoundsGEP = Method(ptr(Value), ptr(Value), ref(SmallVector_Value), cast(str, StringRef)) - _CreateCall |= Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value)) + _CreateInBoundsGEP.require_only(2) + _CreateInBoundsGEP.realname = 'CreateInBoundsGEP' + + @CustomPythonMethod + def CreateInBoundsGEP(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return self._CreateInBoundsGEP(*args) + + CreateStructGEP = Method(ptr(Value), ptr(Value), cast(int, Unsigned), + cast(str, StringRef)).require_only(2) + + CreateGlobalStringPtr = Method(ptr(Value), cast(str, StringRef), + cast(str, StringRef)).require_only(1) + + def _value_type(): + sig = [ptr(Value), ptr(Value), ptr(Type), cast(str, StringRef)] + op = Method(*sig).require_only(2) + return op + + CreateTrunc = _value_type() + CreateZExt = _value_type() + CreateSExt = _value_type() + CreateZExtOrTrunc = Method(ptr(Value), ptr(Value), ptr(IntegerType), + cast(str, StringRef)).require_only(2) + CreateSExtOrTrunc = Method(ptr(Value), ptr(Value), ptr(IntegerType), + cast(str, StringRef)).require_only(2) + CreateFPToUI = _value_type() + CreateFPToSI = _value_type() + CreateUIToFP = _value_type() + CreateSIToFP = _value_type() + CreateFPTrunc = _value_type() + CreateFPExt = _value_type() + CreatePtrToInt = _value_type() + CreateIntToPtr = _value_type() + CreateBitCast = _value_type() + CreateZExtOrBitCast = _value_type() + CreateSExtOrBitCast = _value_type() + # Skip CreateCast + CreateTruncOrBitCast = _value_type() + CreateIntCast = Method(ptr(Value), ptr(Value), ptr(Type), cast(bool, Bool), + cast(str, StringRef)).require_only(3) + CreateFPCast = _value_type() + + _CreateCall = Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value), + cast(str, StringRef)).require_only(2) _CreateCall.realname = 'CreateCall' + # Skip specialized CreateICmp* and CreateFCmp* + + CreateICmp = Method(ptr(Value), CmpInst.Predicate, ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreateFCmp = Method(ptr(Value), CmpInst.Predicate, ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreatePHI = Method(ptr(PHINode), ptr(Type), cast(int, Unsigned), + cast(str, StringRef)).require_only(2) + @CustomPythonMethod def CreateCall(self, *args): import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) - return IRBuilder._CreateCall(self, *args) + return self._CreateCall(*args) + + CreateSelect = Method(ptr(Value), ptr(Value), ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreateVAArg = Method(ptr(VAArgInst), ptr(Value), ptr(Type), + cast(str, StringRef)).require_only(2) + + CreateExtractElement = _binop_basic() + + CreateInsertElement = Method(ptr(Value), ptr(Value), ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreateShuffleVector = Method(ptr(Value), ptr(Value), ptr(Value), + ptr(Value), cast(str, StringRef)) + CreateShuffleVector.require_only(3) + + CreateExtractValue = Method(ptr(Value), ptr(Value), ref(SmallVector_Unsigned), + cast(str, StringRef)) + CreateExtractValue.require_only(2) + + CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), + ref(SmallVector_Unsigned), cast(str, StringRef)) + CreateInsertValue.require_only(3) + + CreateLandingPad = Method(ptr(LandingPadInst), ptr(Type), ptr(Value), + cast(int, Unsigned), cast(str, StringRef)) + CreateLandingPad.require_only(3) + + CreateIsNull = Method(ptr(Value), ptr(Value), cast(str, StringRef)) + CreateIsNull.require_only(1) + + CreateIsNotNull = Method(ptr(Value), ptr(Value), cast(str, StringRef)) + CreateIsNotNull.require_only(1) + + CreatePtrDiff = _binop_basic() + + # New in llvm 3.3 + #CreateVectorSplat = Method(ptr(Value), cast(int, Unsigned), ptr(Value), + # cast(str, StringRef)) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py index 310e19d..dda6b48 100644 --- a/newbinding/src/Instruction.py +++ b/newbinding/src/Instruction.py @@ -26,9 +26,9 @@ IntrinsicInst = llvm.Class(CallInst) FCmpInst = llvm.Class(CmpInst) ICmpInst = llvm.Class(CmpInst) - BranchInst = llvm.Class(TerminatorInst) IndirectBrInst = llvm.Class(TerminatorInst) +InvokeInst = llvm.Class(TerminatorInst) ResumeInst = llvm.Class(TerminatorInst) ReturnInst = llvm.Class(TerminatorInst) SwitchInst = llvm.Class(TerminatorInst) @@ -56,14 +56,14 @@ FPTruncInst = llvm.Class(CastInst) class Instruction: pass - @AtomicCmpXchgInst class AtomicCmpXchgInst: pass @AtomicRMWInst class AtomicRMWInst: - pass + BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min', + 'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP') @BinaryOperator class BinaryOperator: @@ -75,7 +75,17 @@ class CallInst: @CmpInst class CmpInst: - pass + Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', + 'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO', + 'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE', + 'FCMP_UNE', 'FCMP_TRUE', 'FIRST_FCMP_PREDICATE', + 'LAST_FCMP_PREDICATE', + 'BAD_FCMP_PREDICATE', + 'ICMP_EQ', 'ICMP_NE', 'ICMP_UGT', 'ICMP_UGE', 'ICMP_ULT', + 'ICMP_ULE', 'ICMP_SGT', 'ICMP_SGE', 'ICMP_SLT', 'ICMP_SLE', + 'FIRST_ICMP_PREDICATE', + 'LAST_ICMP_PREDICATE', + 'BAD_ICMP_PREDICATE',) @ExtractElementInst class ExtractElementInst: @@ -146,11 +156,14 @@ class ICmpInst: class BranchInst: pass - @IndirectBrInst class IndirectBrInst: pass +@InvokeInst +class InvokeInst: + pass + @ResumeInst class ResumeInst: pass @@ -228,3 +241,12 @@ class FPToUIInst: @FPTruncInst class FPTruncInst: pass + +AtomicOrdering = llvm.Enum('AtomicOrdering', + 'NotAtomic', 'Unordered', 'Monotonic', 'Acquire', + 'Release', 'AcquireRelease', + 'SequentiallyConsistent') + +SynchronizationScope = llvm.Enum('SynchronizationScope', + 'SingleThread', 'CrossThread') + diff --git a/newbinding/src/JITMemoryManager.py b/newbinding/src/JITMemoryManager.py new file mode 100644 index 0000000..f134735 --- /dev/null +++ b/newbinding/src/JITMemoryManager.py @@ -0,0 +1,7 @@ +from binding import * +from namespace import llvm + +@llvm.Class() +class JITMemoryManager: + pass + diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py new file mode 100644 index 0000000..78dbe15 --- /dev/null +++ b/newbinding/src/Metadata.py @@ -0,0 +1,7 @@ +from binding import * +from namespace import llvm +from Value import MDNode + +@MDNode +class MDNode: + pass diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 730b757..6cd6e2e 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -36,7 +36,8 @@ class Module: appendModuleInlineAsm = Method(Void, cast(str, StringRef)) # Function Accessors - getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) + getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), + ptr(FunctionType)) # Utilities dump = Method(Void) diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index 594faf8..5b48aba 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -11,3 +11,7 @@ class SmallVector_Value: _realname_ = 'SmallVector' delete = Destructor() +@llvm.Class() +class SmallVector_Unsigned: + _realname_ = 'SmallVector' + delete = Destructor() diff --git a/newbinding/src/TargetSelect.py b/newbinding/src/TargetSelect.py new file mode 100644 index 0000000..cb2eb96 --- /dev/null +++ b/newbinding/src/TargetSelect.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm + +llvm.includes.add('llvm/Support/TargetSelect.h') + +llvm.Function('InitializeNativeTarget') +#llvm.Function('InitializeAllTargets') + diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 45f9444..15b5e31 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -6,6 +6,7 @@ from raw_ostream import raw_ostream Type = llvm.Class() IntegerType = llvm.Class(Type) CompositeType = llvm.Class(Type) +StructType = llvm.Class(CompositeType) SequentialType = llvm.Class(CompositeType) PointerType = llvm.Class(SequentialType) @@ -113,3 +114,6 @@ class SequentialType: class PointerType: pass +@StructType +class StructType: + pass diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5b907bd..7460c90 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -9,6 +9,7 @@ from StringRef import StringRef Value = llvm.Class() # forward declarations Argument = llvm.Class(Value) +MDNode = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) diff --git a/newbinding/test2.py b/newbinding/test2.py index a7a4ddd..9492bb6 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,7 +1,11 @@ import api import extra import _capsule +from StringIO import StringIO api.capsule.set_debug(True) + + +api.InitializeNativeTarget() context = api.getGlobalContext() @@ -71,3 +75,13 @@ builder.CreateRet(ret) print fn +errio = StringIO() +ee = api.ExecutionEngine.createJIT(m) +print ee, errio.getvalue() +print ee.getDataLayout().getStringRepresentation() + +datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' + +assert datalayout_str == str(api.DataLayout.new(datalayout_str)) +assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) + From 25b498c8fae73fa621179b76398c733b13200871 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 30 Jan 2013 14:44:17 -0600 Subject: [PATCH 058/338] Improve refct and management of capsules --- newbinding/capsule.py | 187 +++++++++++++++++++++++++++--------------- newbinding/extra.py | 18 ---- 2 files changed, 121 insertions(+), 84 deletions(-) diff --git a/newbinding/capsule.py b/newbinding/capsule.py index f489c7f..907fa15 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -1,5 +1,5 @@ -import _capsule -from weakref import WeakValueDictionary, ref +from weakref import WeakKeyDictionary, WeakValueDictionary, ref +from collections import defaultdict import logging logger = logging.getLogger(__name__) @@ -17,81 +17,106 @@ def set_debug(enabled): else: logger.setLevel(logging.WARNING) +def _capsule_weakref_dtor(item): + addr = item.pointer + _addr2refct[addr] -= 1 + refct = _addr2refct[addr] + assert refct >= 0, "RefCt drop below 0" + if refct == 0: + dtor = _addr2dtor.pop(addr, None) + if dtor is not None: + logger.debug('Destroy %s %s', item.name, hex(item.pointer)) + dtor(item.capsule) + +class Capsule(object): + "Wraps PyCapsule so that we can build weakref of it." + + from _capsule import check, getClassName, getName, getPointer + + def __init__(self, capsule): + assert Capsule.valid(capsule) + self.capsule = capsule + + weak = WeakRef(self, _capsule_weakref_dtor) + weak.pointer = self.pointer + weak.capsule = capsule + weak.name = self.name + _capsule2weak[self] = weak + _addr2refct[self.pointer] += 1 + + @property + def classname(self): + return Capsule.getClassName(self.capsule) + + @property + def name(self): + return Capsule.getName(self.capsule) + + @property + def pointer(self): + return Capsule.getPointer(self.capsule) + + @staticmethod + def valid(capsule): + return Capsule.check(capsule) + + def get_class(self): + return _pyclasses[self.classname] + + def instantiate(self): + cls = self.get_class() + return cls(self) + + def __eq__(self, other): + if self.pointer == other.pointer: + assert self.name == other.name + return True + else: + return False + + def __ne__(self, other): + return not (self == other) class WeakRef(ref): - __slots__ = 'capsule', 'dtor', 'owning' + pass +_addr2refct = defaultdict(lambda: 0) +_capsule2weak = WeakKeyDictionary() +_addr2dtor = {} _pyclasses = {} -_addr2obj = WeakValueDictionary() -_owners = {} # address to weak reference -def _sentry(ptr): - if not _capsule.check(ptr): - raise ValueError('Must provide a PyCapsule object.') - -def classof(cap): - cls = _capsule.getClassName(cap) - return _pyclasses[cls] - -def _capsule_destructor(weak): - if weak.owning: - cap = weak.capsule - addr = _capsule.getPointer(cap) - cls = _capsule.getClassName(cap) - logger.debug("destroy pointer 0x%08X to %s", addr, cls) -# weak.dtor(cap) - del _owners[addr] +# Cache {cls: {addr: obj}} +# NOTE: The same 'addr' may appear in multiple class bins. +_cache = defaultdict(WeakValueDictionary) def release_ownership(old): - addr = _capsule.getPointer(old) - oldweak = _owners[addr] - oldweak.owning = False # dis-own - del _owners[addr] + logger.debug('Release %s', old) + _addr2dtor[Capsule.getPointer(old)] = None + +def has_ownership(cap): + addr = Capsule.getPointer(cap) + return _addr2dtor.get(addr) is not None def wrap(cap, owned=False): '''Wrap a PyCapsule with the corresponding Wrapper class. If `cap` is not a PyCapsule, returns `cap` ''' - if not _capsule.check(cap): + if not Capsule.valid(cap): if isinstance(cap, list): return map(wrap, cap) return cap # bypass if cap is not a PyCapsule and not a list - addr = _capsule.getPointer(cap) - try: - # find cached object by pointer address - obj = _addr2obj[addr] - except KeyError: - # create new object and cache it - cls = classof(cap) - obj = cls(cap) - _addr2obj[addr] = obj # cache object by address - # set ownership if *cls* defines *_delete_* - if not owned and hasattr(cls, '_delete_'): - assert addr not in _owners, "has existing owner" - weak = WeakRef(obj, _capsule_destructor) - _owners[addr] = weak - weak.capsule = cap - weak.owning = True - weak.dtor = cls._delete_ - else: - oldcls = classof(obj._ptr) - newcls = classof(cap) - if issubclass(oldcls, newcls): - # do auto downcast - pass - else: - assert oldcls is newcls, (cap, obj, oldcls, newcls) - return obj -def downcast(old, new): - assert old is not new - assert _capsule.getPointer(old) not in _owners - oldcls = classof(old) - newcls = classof(new) - assert issubclass(newcls, oldcls) - # release_ownership(old) - del _addr2obj[_capsule.getPointer(old)] # clear cache - return wrap(new) + cap = Capsule(cap) + cls = cap.get_class() + addr = cap.pointer + try: # lookup cached object + return _cache[cls][addr] + except KeyError: + if not owned and hasattr(cls, '_delete_'): + _addr2dtor[addr] = cls._delete_ + obj = cap.instantiate() + _cache[cls][addr] = obj # cache it + return obj def unwrap(obj): '''Unwrap a Wrapper instance into the underlying PyCapsule. @@ -112,13 +137,43 @@ def register_class(clsname): class Wrapper(object): - __slots__ = '__ptr' + __slots__ = '__capsule' - def __init__(self, ptr): - _sentry(ptr) - self.__ptr = ptr + def __init__(self, capsule): + self.__capsule = capsule + + @property + def _capsule(self): + return self.__capsule @property def _ptr(self): - return self.__ptr + return self._capsule.capsule + def __eq__(self, other): + return self._capsule == other._capsule + + def __ne__(self, other): + return self._capsule != other._capsule + + def _downcast(self, newcls): + return downcast(self, newcls) + +def downcast(obj, cls): + import _api + if type(obj) is cls: + return obj + fromty = obj._llvm_type_ + toty = cls._llvm_type_ + logger.debug("Downcast %s to %s" , fromty, toty) + fname = 'downcast_%s_to_%s' % (fromty, toty) + fname = fname.replace('::', '_') + try: + caster = getattr(_api, fname) + except AttributeError: + fmt = "Downcast from %s to %s is not supported" + raise TypeError(fmt % (fromty, toty)) + old = unwrap(obj) + new = caster(old) + used_to_own = has_ownership(old) + return wrap(new, owned=not used_to_own) diff --git a/newbinding/extra.py b/newbinding/extra.py index a613296..d65f84c 100644 --- a/newbinding/extra.py +++ b/newbinding/extra.py @@ -22,22 +22,4 @@ def _init(glob): _init(globals()) -# -# Downcasts -# -def downcast(obj, cls): - if type(obj) is cls: - return obj - fromty = obj._llvm_type_ - toty = cls._llvm_type_ - fname = 'downcast_%s_to_%s' % (fromty, toty) - fname = fname.replace('::', '_') - try: - caster = getattr(_api, fname) - except AttributeError: - fmt = "Downcast from %s to %s is not supported" - raise TypeError(fmt % (fromty, toty)) - old = capsule.unwrap(obj) - new = caster(old) - return capsule.downcast(old, new) \ No newline at end of file From 78f9c9a61087f73e805d32b0a9bbb48ec5026827 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 30 Jan 2013 18:09:22 -0600 Subject: [PATCH 059/338] Completed binding for most of ExecutionEngine --- newbinding/binding.py | 8 ++ newbinding/include/llvm_binding/conversion.h | 117 ++++++++++++++++++- newbinding/include/llvm_binding/extra.h | 106 +++++++++++++++++ newbinding/src/ExecutionEngine.py | 60 ++++++++++ newbinding/src/GenericValue.py | 34 ++++++ newbinding/src/MachineCodeInfo.py | 13 +++ newbinding/src/Module.py | 7 ++ newbinding/src/Type.py | 14 +++ newbinding/test2.py | 41 +++++-- 9 files changed, 391 insertions(+), 9 deletions(-) create mode 100644 newbinding/src/GenericValue.py create mode 100644 newbinding/src/MachineCodeInfo.py diff --git a/newbinding/binding.py b/newbinding/binding.py index f7d5ac4..9ddedf3 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -59,9 +59,17 @@ class BuiltinTypes(_Type): Void = BuiltinTypes('void') Unsigned = BuiltinTypes('unsigned') +UnsignedLongLong = BuiltinTypes('unsigned long long') # used in llvm-3.2 +LongLong = BuiltinTypes('long long') +Float = BuiltinTypes('float') +Double = BuiltinTypes('double') Uint64 = BuiltinTypes('uint64_t') +Size_t = BuiltinTypes('size_t') +VoidPtr = BuiltinTypes('void*') Bool = BuiltinTypes('bool') +StdString = BuiltinTypes('std::string') ConstStdString = BuiltinTypes('const std::string') +ConstCharPtr = BuiltinTypes('const char*') PyObjectPtr = BuiltinTypes('PyObject*') PyObjectPtr.format='O' diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h index 0e30c60..a1fc87c 100644 --- a/newbinding/include/llvm_binding/conversion.h +++ b/newbinding/include/llvm_binding/conversion.h @@ -25,6 +25,45 @@ int py_str_to(PyObject *strobj, llvm::StringRef &strref){ return 1; } +static +int py_str_to(PyObject *strobj, std::string &strref){ + // type check + if (!PyString_Check(strobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get len and buffer + const char * buf = PyString_AsString(strobj); + if (!buf) { + // raises TypeError + return 0; + } + // set output + strref = std::string(buf); + // success + return 1; +} + + +static +int py_str_to(PyObject *strobj, const char* &strref){ + // type check + if (!PyString_Check(strobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get buffer + strref = PyString_AsString(strobj); + if (!strref) { + // raises TypeError + return 0; + } + // success + return 1; +} + static int py_int_to(PyObject *intobj, unsigned & val){ if (!PyInt_Check(intobj)) { @@ -37,6 +76,70 @@ int py_int_to(PyObject *intobj, unsigned & val){ return 1; } +static +int py_int_to(PyObject *intobj, unsigned long long & val){ + if (!PyInt_Check(intobj)) { + // raise TypeError + puts(PyString_AsString(PyObject_Str(PyObject_Type(intobj)))); + PyErr_SetString(PyExc_TypeError, "Expecting an int 2"); + return 0; + } + val = PyInt_AsUnsignedLongLongMask(intobj); + // success + return 1; + +} + +static +int py_int_to(PyObject *intobj, size_t & val){ + unsigned long long ull; + if (py_int_to(intobj, ull)) { + val = (size_t)ull; + return 1; + } else { + return 0; + } +} + + +static +int py_int_to(PyObject *intobj, void* & val){ + if (!PyLong_Check(intobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting an int"); + return 0; + } + val = PyLong_FromVoidPtr(intobj); + // success + return 1; +} + +static +int py_float_to(PyObject *floatobj, double & val){ + if (!PyFloat_Check(floatobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a float"); + return 0; + } + val = PyFloat_AsDouble(floatobj); + if (PyErr_Occurred()){ + return 0; + } + // success + return 1; +} + + +static +int py_float_to(PyObject *floatobj, float & val){ + double db; + int status = py_float_to(floatobj, db); + if (status) + val = db; + return status; +} + + static int py_bool_to(PyObject *boolobj, bool & val){ if (!PyBool_Check(boolobj)) { @@ -78,8 +181,18 @@ PyObject* py_bool_from(bool val){ } static -PyObject* py_int_from(int val){ - return PyInt_FromLong(val); +PyObject* py_int_from(const long long & val){ + return PyLong_FromLongLong(val); +} + +static +PyObject* py_int_from(void * addr){ + return PyLong_FromVoidPtr(addr); +} + +static +PyObject* py_float_from(const double& val) { + return PyFloat_FromDouble(val); } // casting diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index b5edd2c..7aacfde 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace extra{ using namespace llvm; @@ -234,3 +235,108 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT( PyFile_WriteString(ErrorStr.c_str(), errout); return ee; } + +static +llvm::GenericValue* GenericValue_CreateInt(llvm::Type* Ty, unsigned long long N, + bool IsSigned) +{ + // Shamelessly copied from LLVM + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->IntVal = llvm::APInt(Ty->getIntegerBitWidth(), N, IsSigned); + return GenVal; +} + +static +llvm::GenericValue* GenericValue_CreateFloat(float Val) +{ + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->FloatVal = Val; + return GenVal; +} + +static +llvm::GenericValue* GenericValue_CreateDouble(double Val) +{ + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->DoubleVal = Val; + return GenVal; +} + +static +llvm::GenericValue* GenericValue_CreatePointer(void * Ptr) +{ + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->PointerVal = Ptr; + return GenVal; +} + +static +unsigned GenericValue_ValueIntWidth(llvm::GenericValue *GenValRef) +{ + return GenValRef->IntVal.getBitWidth(); +} + +static +unsigned long long GenericValue_ToUnsignedInt(llvm::GenericValue* GenVal) +{ + return GenVal->IntVal.getZExtValue(); +} + + +static +long long GenericValue_ToSignedInt(llvm::GenericValue* GenVal) +{ + return GenVal->IntVal.getSExtValue(); +} + +static +void* GenericValue_ToPointer(llvm::GenericValue* GenVal) +{ + return GenVal->PointerVal; +} + +static +double GenericValue_ToFloat(llvm::GenericValue* GenVal, llvm::Type* Ty) +{ + switch (Ty->getTypeID()) { + case llvm::Type::FloatTyID: + return GenVal->FloatVal; + default: + // Behavior undefined if type is not a float or a double + return GenVal->DoubleVal; + } +} + +static +PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, + llvm::Function* Fn, PyObject* Args) +{ + using namespace llvm; + const char * GVN = "llvm::GenericValue"; + if (!PyTuple_Check(Args)) { + PyErr_SetString(PyExc_TypeError, "Expect a tuple of args."); + return NULL; + } + std::vector vec_args; + Py_ssize_t nargs = PyTuple_Size(Args); + vec_args.reserve(nargs); + for (Py_ssize_t i = 0; i < nargs; ++i) { + PyObject* obj = PyTuple_GetItem(Args, i); + if (!obj) { + PyErr_SetString(PyExc_RuntimeError, "Failed to index into args?"); + return NULL; + } + + GenericValue* gv = static_cast( + PyCapsule_GetPointer(obj, GVN)); + + if (!gv) { + return NULL; + } + vec_args.push_back(*gv); + } + + GenericValue ret = EE->runFunction(Fn, vec_args); + return pycapsule_new(new GenericValue(ret), GVN); +} + diff --git a/newbinding/src/ExecutionEngine.py b/newbinding/src/ExecutionEngine.py index 0fbe387..5a95a16 100644 --- a/newbinding/src/ExecutionEngine.py +++ b/newbinding/src/ExecutionEngine.py @@ -4,6 +4,11 @@ from Module import Module from JITMemoryManager import JITMemoryManager from CodeGen import CodeGenOpt, Reloc, CodeModel from DataLayout import DataLayout +from Value import Function, GlobalValue, BasicBlock, Constant +from GlobalVariable import GlobalVariable +from MachineCodeInfo import MachineCodeInfo +from GenericValue import GenericValue +from Type import Type ExecutionEngine = llvm.Class() @@ -32,3 +37,58 @@ class ExecutionEngine: addModule = Method(Void, ptr(Module)) getDataLayout = Method(const(ownedptr(DataLayout))) removeModule = Method(cast(Bool, bool), ptr(Module)) + + FindFunctionNamed = Method(ptr(Function), cast(str, ConstCharPtr)) + getPointerToNamedFunction = Method(cast(VoidPtr, int), + cast(str, StdString), + cast(bool, Bool)).require_only(1) + + runStaticConstructorsDestructors = Method(Void, cast(Bool, bool)) + runStaticConstructorsDestructors |= Method(Void, ptr(Module), + cast(Bool, bool)) + + addGlobalMapping = Method(Void, ptr(GlobalValue), cast(int, VoidPtr)) + clearAllGlobalMappings = Method() + clearGlobalMappingsFromModule = Method(Void, ptr(Module)) + updateGlobalMapping = Method(cast(VoidPtr, int), + ptr(GlobalValue), cast(int, VoidPtr)) + + getPointerToGlobalIfAvailable = Method(cast(VoidPtr, int), ptr(GlobalValue)) + getPointerToGlobal = Method(cast(VoidPtr, int), ptr(GlobalValue)) + getPointerToFunction = Method(cast(VoidPtr, int), ptr(Function)) + getPointerToBasicBlock = Method(cast(VoidPtr, int), ptr(BasicBlock)) + getPointerToFunctionOrStub = Method(cast(VoidPtr, int), ptr(Function)) + + runJITOnFunction = Method(Void, ptr(Function), ptr(MachineCodeInfo)) + runJITOnFunction.require_only(1) + + getGlobalValueAtAddress = Method(const(ptr(GlobalValue)), cast(int, VoidPtr)) + + StoreValueToMemory = Method(Void, ref(GenericValue), ptr(GenericValue), + ptr(Type)) + + InitializeMemory = Method(Void, ptr(Constant), cast(int, VoidPtr)) + + recompileAndRelinkFunction = Method(cast(int, VoidPtr), ptr(Function)) + + freeMachineCodeForFunction = Method(Void, ptr(Function)) + getOrEmitGlobalVariable = Method(cast(int, VoidPtr), ptr(GlobalVariable)) + + DisableLazyCompilation = Method(Void, cast(bool, Bool)) + isCompilingLazily = Method(cast(Bool, bool)) + isLazyCompilationDisabled = Method(cast(Bool, bool)) + DisableGVCompilation = Method(Void, cast(bool, Bool)) + isSymbolSearchingDisabled = Method(cast(Bool, bool)) + RegisterTable = Method(Void, ptr(Function), cast(int, VoidPtr)) + DeregisterTable = Method(Void, ptr(Function)) + DeregisterAllTables = Method() + + _runFunction = CustomMethod('ExecutionEngine_RunFunction', + PyObjectPtr, ptr(Function), PyObjectPtr) + + @CustomPythonMethod + def runFunction(self, fn, args): + import capsule + unwrapped = map(capsule.unwrap, args) + return self._runFunction(fn, tuple(unwrapped)) + diff --git a/newbinding/src/GenericValue.py b/newbinding/src/GenericValue.py new file mode 100644 index 0000000..74587ba --- /dev/null +++ b/newbinding/src/GenericValue.py @@ -0,0 +1,34 @@ +from binding import * +from namespace import llvm +from Type import Type + +GenericValue = llvm.Class() + +@GenericValue +class GenericValue: + delete = Destructor() + + def _factory(name, *argtys): + return CustomStaticMethod('GenericValue_' + name, + ptr(GenericValue), *argtys) + + CreateFloat = _factory('CreateFloat', cast(float, Float)) + + CreateDouble = _factory('CreateDouble', cast(float, Float)) + + CreateInt = _factory('CreateInt', ptr(Type), + cast(int, UnsignedLongLong), cast(bool, Bool)) + + CreatePointer = _factory('CreatePointer', cast(int, VoidPtr)) + + def _accessor(name, *argtys): + return CustomMethod('GenericValue_' + name, *argtys) + + valueIntWidth = _accessor('ValueIntWidth', cast(Unsigned, int)) + + toSignedInt = _accessor('ToSignedInt', cast(UnsignedLongLong, int)) + toUnsignedInt = _accessor('ToUnsignedInt', cast(LongLong, int)) + + toFloat = _accessor('ToFloat', cast(Double, float), ptr(Type)) + + toPointer = _accessor('ToPointer', cast(VoidPtr, int)) \ No newline at end of file diff --git a/newbinding/src/MachineCodeInfo.py b/newbinding/src/MachineCodeInfo.py new file mode 100644 index 0000000..5d91e3a --- /dev/null +++ b/newbinding/src/MachineCodeInfo.py @@ -0,0 +1,13 @@ +from binding import * +from namespace import llvm + +MachineCodeInfo = llvm.Class() + +@MachineCodeInfo +class MachineCodeInfo: + _include_ = 'llvm/CodeGen/MachineCodeInfo.h' + setSize = Method(Void, cast(int, Size_t)) + setAddress = Method(Void, cast(int, VoidPtr)) + size = Method(cast(Size_t, int)) + address = Method(cast(VoidPtr, int)) + diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 6cd6e2e..9b392ca 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -44,4 +44,11 @@ class Module: print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) print_.realname = 'print' + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() + dropAllReferences = Method() diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 15b5e31..bf51b9d 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -2,6 +2,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from raw_ostream import raw_ostream +from StringRef import StringRef Type = llvm.Class() IntegerType = llvm.Class(Type) @@ -52,6 +53,19 @@ class Type: isIntegerTy = Method(cast(Bool, bool)) isIntegerTy |= Method(cast(Bool, bool), cast(int, Unsigned)) + getIntegerBitWidth = Method(cast(Unsigned, int)) + getFunctionParamType = Method(ptr(Type), cast(int, Unsigned)) + getFunctionNumParams = Method(cast(int, Unsigned)) + + isFunctionVarArg = type_checker() + + getStructName = Method(cast(StringRef, str)) + getStructNumElements = Method(cast(Unsigned, int)) + getStructElementType = Method(ptr(Type), cast(int, Unsigned)) + getSequentialElementType = Method(ptr(Type)) + + # Factories + def type_factory(): return StaticMethod(ptr(Type), ref(LLVMContext)) diff --git a/newbinding/test2.py b/newbinding/test2.py index 9492bb6..7902df4 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -28,25 +28,25 @@ print os.str() int1ty = api.Type.getInt1Ty(context) int1ty.dump() -print int1ty.isIntegerTy(1) +assert int1ty.isIntegerTy(1) fnty = api.FunctionType.get(int1ty, False) fnty.dump() -types = [int1ty, api.Type.getIntNTy(context, 21)] -fnty = api.FunctionType.get(int1ty, types, False) +types = [api.Type.getIntNTy(context, 8), api.Type.getIntNTy(context, 32)] +fnty = api.FunctionType.get(api.Type.getIntNTy(context, 8), types, False) print fnty const = m.getOrInsertFunction("foo", fnty) -fn = extra.downcast(const, api.Function) +fn = const._downcast(api.Function) print fn assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') assert 'bar' == fn.getName() -assert fn.getReturnType() is int1ty +assert fn.getReturnType().isIntegerTy(8) assert fnty is fn.getFunctionType() @@ -70,13 +70,19 @@ assert bb.getTerminator() is None arg0, arg1 = fn.getArgumentList() print arg0, arg1 -ret = builder.CreateCall(fn, [arg0, arg1], '') +extended = builder.CreateZExt(arg0, arg1.getType()) +result = builder.CreateAdd(extended, arg1) +ret = builder.CreateTrunc(result, fn.getReturnType()) builder.CreateRet(ret) +print arg0.list_use() + print fn errio = StringIO() -ee = api.ExecutionEngine.createJIT(m) +print m + +ee = api.ExecutionEngine.createJIT(m, errio) print ee, errio.getvalue() print ee.getDataLayout().getStringRepresentation() @@ -85,3 +91,24 @@ datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64- assert datalayout_str == str(api.DataLayout.new(datalayout_str)) assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) +fn2 = ee.FindFunctionNamed(fn.getName()) +assert fn2 is fn + +assert ee.getPointerToFunction(fn) +assert ee.getPointerToNamedFunction('printf') + +gv0 = api.GenericValue.CreateInt(arg0.getType(), 12, False) +gv1 = api.GenericValue.CreateInt(arg1.getType(), -32, True) + +assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() +assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() + +assert gv0.toUnsignedInt() == 12 +assert gv1.toSignedInt() == -32 + +gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) + +gvR = ee.runFunction(fn, (gv0, gv1)) + +assert 44 == gvR.toUnsignedInt() + From ca0a2b9fddd9e8224b5a919de6fbccc80492a04c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 11:45:19 -0600 Subject: [PATCH 060/338] binding for EngineBuilder --- newbinding/binding.py | 3 +- newbinding/capsule.py | 7 +- newbinding/include/llvm_binding/extra.h | 41 ++++++ newbinding/src/EngineBuilder.py | 49 +++++++ newbinding/src/TargetMachine.py | 11 ++ newbinding/test2.py | 170 ++++++++++++++---------- 6 files changed, 206 insertions(+), 75 deletions(-) create mode 100644 newbinding/src/EngineBuilder.py create mode 100644 newbinding/src/TargetMachine.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 9ddedf3..1f980d1 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -358,7 +358,8 @@ class Method(object): argtys = self.signatures[0][1:] for i, ty in enumerate(argtys): if isinstance(ty, ownedptr): - writer.release_ownership('%s[%d]' % (unwrapped, i)) + with writer.block('if len(%s) > %d:' % (unwrapped, i)): + writer.release_ownership('%s[%d]' % (unwrapped, i)) class CustomMethod(Method): def __init__(self, methodname, retty, *argtys): diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 907fa15..8c2f10e 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -91,7 +91,12 @@ _cache = defaultdict(WeakValueDictionary) def release_ownership(old): logger.debug('Release %s', old) - _addr2dtor[Capsule.getPointer(old)] = None + addr = Capsule.getPointer(old) + if _addr2dtor[addr] is None: + # Guard deduplicated release + raise Exception("Already released") + _addr2dtor[addr] = None + def has_ownership(cap): addr = Capsule.getPointer(cap) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 7aacfde..10a4361 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -340,3 +340,44 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, return pycapsule_new(new GenericValue(ret), GVN); } +static +PyObject* EngineBuilder_setErrorStr(llvm::EngineBuilder* eb, PyObject* fileobj) +{ + + if (!PyFile_Check(fileobj)) { + PyErr_SetString(PyExc_TypeError, "Expecting a file object."); + return NULL; + } + + std::string buffer; + eb->setErrorStr(&buffer); + + if (-1 == PyFile_WriteString(buffer.c_str(), fileobj)) { + return NULL; + } + + return pycapsule_new(eb, "llvm::EngineBuilder"); +} + +static +PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, + PyObject* strlist) +{ + if (!PyList_Check(strlist)) { + PyErr_SetString(PyExc_TypeError, "Expecting a list of string."); + return NULL; + } + std::vector tmp; + const int N = PyList_Size(strlist); + tmp.reserve(N); + for (int i = 0; i < N; ++i) { + const char * elem = PyString_AsString(PyList_GetItem(strlist, i)); + if (!elem) { + return NULL; + } + tmp.push_back(elem); + } + eb->setMAttrs(tmp); + return pycapsule_new(eb, "llvm::EngineBuilder"); +} + diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py new file mode 100644 index 0000000..0e8388e --- /dev/null +++ b/newbinding/src/EngineBuilder.py @@ -0,0 +1,49 @@ +from binding import * +from namespace import llvm +from Module import Module +from JITMemoryManager import JITMemoryManager +from CodeGen import CodeGenOpt, Reloc, CodeModel +from StringRef import StringRef +from ExecutionEngine import ExecutionEngine +from TargetMachine import TargetMachine + +EngineBuilder = llvm.Class() + +@llvm.Class() # a fake class (actually a namespace) +class EngineKind: + Kind = Enum('JIT', 'Interpreter') + +@EngineBuilder +class EngineBuilder: + new = Constructor(ownedptr(Module)) + delete = Destructor() + + def _setter(*args): + return Method(ref(EngineBuilder), *args) + + setEngineKind = _setter(EngineKind.Kind) + setJITMemoryManager = _setter(ptr(JITMemoryManager)) + + setErrorStr = CustomMethod('EngineBuilder_setErrorStr', + PyObjectPtr, PyObjectPtr) + + setOptLevel = _setter(CodeGenOpt.Level) + #setTargetOptions = + setRelocationModel = _setter(Reloc.Model) + setCodeModel = _setter(CodeModel.Model) + setAllocateGVsWithCode = _setter(cast(bool, Bool)) + setMArch = _setter(cast(str, StringRef)) + setMCPU = _setter(cast(str, StringRef)) + setUseMCJIT = _setter(cast(bool, Bool)) + _setMAttrs = CustomMethod('EngineBuilder_setMAttrs', + PyObjectPtr, PyObjectPtr) + @CustomPythonMethod + def setMAttrs(self, attrs): + attrlist = list(str(a) for a in attrs) + return self._setMAttrs(attrlist) + + create = Method(ptr(ExecutionEngine), + ownedptr(TargetMachine)).require_only(0) + + selectTarget = Method(ptr(TargetMachine)) + diff --git a/newbinding/src/TargetMachine.py b/newbinding/src/TargetMachine.py new file mode 100644 index 0000000..e53cd33 --- /dev/null +++ b/newbinding/src/TargetMachine.py @@ -0,0 +1,11 @@ +from binding import * +from namespace import llvm + +TargetMachine = llvm.Class() + +@TargetMachine +class TargetMachine: + _include_ = 'llvm/Target/TargetMachine.h' + delete = Destructor() + + diff --git a/newbinding/test2.py b/newbinding/test2.py index 7902df4..a304426 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -4,111 +4,135 @@ import _capsule from StringIO import StringIO api.capsule.set_debug(True) - -api.InitializeNativeTarget() -context = api.getGlobalContext() +def test_basic_jit_use(): + api.InitializeNativeTarget() + context = api.getGlobalContext() -m = api.Module.new("modname", context) -print m.getModuleIdentifier() -m.setModuleIdentifier('modname2') -print m.getModuleIdentifier() -print 'endianness', m.getEndianness() -assert m.getEndianness() == api.Module.Endianness.AnyEndianness -print 'pointer-size', m.getPointerSize() -assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize -m.dump() + m = api.Module.new("modname", context) + print m.getModuleIdentifier() + m.setModuleIdentifier('modname2') + print m.getModuleIdentifier() + print 'endianness', m.getEndianness() + assert m.getEndianness() == api.Module.Endianness.AnyEndianness + print 'pointer-size', m.getPointerSize() + assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize + m.dump() -os = extra.make_raw_ostream_for_printing() -m.print_(os, None) -print os.str() + os = extra.make_raw_ostream_for_printing() + m.print_(os, None) + print os.str() -int1ty = api.Type.getInt1Ty(context) -int1ty.dump() + int1ty = api.Type.getInt1Ty(context) + int1ty.dump() -assert int1ty.isIntegerTy(1) + assert int1ty.isIntegerTy(1) -fnty = api.FunctionType.get(int1ty, False) -fnty.dump() + fnty = api.FunctionType.get(int1ty, False) + fnty.dump() -types = [api.Type.getIntNTy(context, 8), api.Type.getIntNTy(context, 32)] -fnty = api.FunctionType.get(api.Type.getIntNTy(context, 8), types, False) + types = [api.Type.getIntNTy(context, 8), api.Type.getIntNTy(context, 32)] + fnty = api.FunctionType.get(api.Type.getIntNTy(context, 8), types, False) -print fnty + print fnty -const = m.getOrInsertFunction("foo", fnty) -fn = const._downcast(api.Function) -print fn -assert fn.hasName() -assert 'foo' == fn.getName() -fn.setName('bar') -assert 'bar' == fn.getName() + const = m.getOrInsertFunction("foo", fnty) + fn = const._downcast(api.Function) + print fn + assert fn.hasName() + assert 'foo' == fn.getName() + fn.setName('bar') + assert 'bar' == fn.getName() -assert fn.getReturnType().isIntegerTy(8) + assert fn.getReturnType().isIntegerTy(8) -assert fnty is fn.getFunctionType() + assert fnty is fn.getFunctionType() -assert fn.isVarArg() == False -assert fn.getIntrinsicID() == 0 -assert not fn.isIntrinsic() + assert fn.isVarArg() == False + assert fn.getIntrinsicID() == 0 + assert not fn.isIntrinsic() -fn_uselist = fn.list_use() -assert isinstance(fn_uselist, list) -assert len(fn_uselist) == 0 + fn_uselist = fn.list_use() + assert isinstance(fn_uselist, list) + assert len(fn_uselist) == 0 -builder = api.IRBuilder.new(context) -print builder + builder = api.IRBuilder.new(context) + print builder -bb = api.BasicBlock.Create(context, "entry", fn, None) -assert bb.empty() -builder.SetInsertPoint(bb) + bb = api.BasicBlock.Create(context, "entry", fn, None) + assert bb.empty() + builder.SetInsertPoint(bb) -assert bb.getTerminator() is None + assert bb.getTerminator() is None -arg0, arg1 = fn.getArgumentList() -print arg0, arg1 + arg0, arg1 = fn.getArgumentList() + print arg0, arg1 -extended = builder.CreateZExt(arg0, arg1.getType()) -result = builder.CreateAdd(extended, arg1) -ret = builder.CreateTrunc(result, fn.getReturnType()) -builder.CreateRet(ret) + extended = builder.CreateZExt(arg0, arg1.getType()) + result = builder.CreateAdd(extended, arg1) + ret = builder.CreateTrunc(result, fn.getReturnType()) + builder.CreateRet(ret) -print arg0.list_use() + print arg0.list_use() -print fn + print fn -errio = StringIO() -print m + errio = StringIO() + print m -ee = api.ExecutionEngine.createJIT(m, errio) -print ee, errio.getvalue() -print ee.getDataLayout().getStringRepresentation() + ee = api.ExecutionEngine.createJIT(m, errio) + print ee, errio.getvalue() + print ee.getDataLayout().getStringRepresentation() -datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' + datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' -assert datalayout_str == str(api.DataLayout.new(datalayout_str)) -assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) + assert datalayout_str == str(api.DataLayout.new(datalayout_str)) + assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) -fn2 = ee.FindFunctionNamed(fn.getName()) -assert fn2 is fn + fn2 = ee.FindFunctionNamed(fn.getName()) + assert fn2 is fn -assert ee.getPointerToFunction(fn) -assert ee.getPointerToNamedFunction('printf') + assert ee.getPointerToFunction(fn) + assert ee.getPointerToNamedFunction('printf') -gv0 = api.GenericValue.CreateInt(arg0.getType(), 12, False) -gv1 = api.GenericValue.CreateInt(arg1.getType(), -32, True) + gv0 = api.GenericValue.CreateInt(arg0.getType(), 12, False) + gv1 = api.GenericValue.CreateInt(arg1.getType(), -32, True) -assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() -assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() + assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() + assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() -assert gv0.toUnsignedInt() == 12 -assert gv1.toSignedInt() == -32 + assert gv0.toUnsignedInt() == 12 + assert gv1.toSignedInt() == -32 -gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) + gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) -gvR = ee.runFunction(fn, (gv0, gv1)) + gvR = ee.runFunction(fn, (gv0, gv1)) -assert 44 == gvR.toUnsignedInt() + assert 44 == gvR.toUnsignedInt() + +def test_engine_builder(): + api.InitializeNativeTarget() + context = api.getGlobalContext() + + m = api.Module.new("modname", context) + + eb = api.EngineBuilder.new(m) + eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) + assert eb is eb2 + eb.setOptLevel(api.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) + + tm = eb.selectTarget() + ee = eb.create(tm) + + +def main(): + for name, value in globals().items(): + if name.startswith('test_') and callable(value): + print name.center(80, '-') + value() + +if __name__ == '__main__': + main() From 9485d03e18a226303b36bae577da37f994f61776 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 14:19:22 -0600 Subject: [PATCH 061/338] binding for Target, Triple, TargetMachine --- newbinding/binding.py | 19 ++++++--- newbinding/include/llvm_binding/extra.h | 28 ++++++++++++- newbinding/src/CodeGen.py | 1 + newbinding/src/EngineBuilder.py | 15 ++++++- newbinding/src/Target.py | 27 ++++++++++++ newbinding/src/TargetMachine.py | 25 +++++++++++ newbinding/src/TargetTransformInfo.py | 14 +++++++ newbinding/src/Triple.py | 55 +++++++++++++++++++++++++ newbinding/test2.py | 23 +++++++++++ 9 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 newbinding/src/Target.py create mode 100644 newbinding/src/TargetTransformInfo.py create mode 100644 newbinding/src/Triple.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 1f980d1..69267dc 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -185,6 +185,11 @@ class Class(_Type): writer.die_if_false(casted) return casted + def wrap(self, writer, val): + copy = 'new %s(%s)' % (self.fullname, val) + return writer.pycapsule_new(copy, self.capsule_name, self.fullname) + + class Enum(object): format = 'O' @@ -466,13 +471,17 @@ class ref(_Type): def __init__(self, element): assert isinstance(element, Class), type(element) self.element = element + self.const = False def __str__(self): return self.fullname @property def fullname(self): - return '%s&' % self.element.fullname + if self.const: + return 'const %s&' % self.element.fullname + else: + return '%s&' % self.element.fullname @property def capsule_name(self): @@ -483,7 +492,7 @@ class ref(_Type): return self.element.format def wrap(self, writer, val): - p = writer.declare(ptr(self.element).fullname, '&%s' % val) + p = writer.declare(const(ptr(self.element)).fullname, '&%s' % val) return writer.pycapsule_new(p, self.capsule_name, self.element.fullname) def unwrap(self, writer, val): @@ -522,9 +531,9 @@ class ptr(_Type): class ownedptr(ptr): pass -def const(ptr): - ptr.const = True - return ptr +def const(ptr_or_ref): + ptr_or_ref.const = True + return ptr_or_ref class cast(_Type): format = 'O' diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 10a4361..46dd42a 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -368,9 +368,9 @@ PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, return NULL; } std::vector tmp; - const int N = PyList_Size(strlist); + const Py_ssize_t N = PyList_Size(strlist); tmp.reserve(N); - for (int i = 0; i < N; ++i) { + for (Py_ssize_t i = 0; i < N; ++i) { const char * elem = PyString_AsString(PyList_GetItem(strlist, i)); if (!elem) { return NULL; @@ -381,3 +381,27 @@ PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, return pycapsule_new(eb, "llvm::EngineBuilder"); } +static +PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb, + const llvm::Triple& TargetTriple, + llvm::StringRef MArch, + llvm::StringRef MCPU, + PyObject* strlist) +{ + const Py_ssize_t N = PySequence_Size(strlist); + llvm::SmallVector MAttrs; + MAttrs.reserve(N); + for (Py_ssize_t i = 0; i < N; ++i) { + PyObject* str = PySequence_GetItem(strlist, i); + const char * cp = PyString_AsString(str); + if (!cp) { + Py_DECREF(str); + return NULL; + } + MAttrs.push_back(cp); + Py_DECREF(str); + } + eb->selectTarget(TargetTriple, MArch, MCPU, MAttrs); + return pycapsule_new(eb, "llvm::EngineBuilder"); +} + diff --git a/newbinding/src/CodeGen.py b/newbinding/src/CodeGen.py index 06821aa..7afcd49 100644 --- a/newbinding/src/CodeGen.py +++ b/newbinding/src/CodeGen.py @@ -17,3 +17,4 @@ class TLSModel: class CodeGenOpt: 'Actually a namespace' Level = Enum('None', 'Less', 'Default', 'Aggressive') + diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index 0e8388e..07ffcc0 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -6,6 +6,7 @@ from CodeGen import CodeGenOpt, Reloc, CodeModel from StringRef import StringRef from ExecutionEngine import ExecutionEngine from TargetMachine import TargetMachine +from Triple import Triple EngineBuilder = llvm.Class() @@ -45,5 +46,17 @@ class EngineBuilder: create = Method(ptr(ExecutionEngine), ownedptr(TargetMachine)).require_only(0) - selectTarget = Method(ptr(TargetMachine)) + _selectTarget0 = Method(ptr(TargetMachine)) + _selectTarget0.realname = 'selectTarget' + + _selectTarget1 = CustomMethod('EngineBuilder_selectTarget', + const(ref(Triple)), cast(str, StringRef), + cast(str, StringRef), PyObjectPtr), + + @CustomPythonMethod + def selectTarget(self, *args): + if not args: + return self._selectTarget0() + else: + return self._selectTarget1(*args) diff --git a/newbinding/src/Target.py b/newbinding/src/Target.py new file mode 100644 index 0000000..3c2a0e1 --- /dev/null +++ b/newbinding/src/Target.py @@ -0,0 +1,27 @@ +from binding import * +from namespace import llvm +from StringRef import StringRef +Target = llvm.Class() + +@Target +class Target: + _include_ = 'llvm/Support/TargetRegistry.h' + + getNext = Method(const(ptr(Target))) + + getName = Method(cast(StringRef, str)) + getShortDescription = Method(cast(StringRef, str)) + + def _has(): + return Method(cast(Bool, bool)) + + hasJIT = _has() + hasTargetMachine = _has() + hasMCAsmBackend = _has() + hasMCAsmParser = _has() + hasAsmPrinter = _has() + hasMCDisassembler = _has() + hasMCInstPrinter = _has() + hasMCCodeEmitter = _has() + hasMCObjectStreamer = _has() + hasAsmStreamer = _has() diff --git a/newbinding/src/TargetMachine.py b/newbinding/src/TargetMachine.py index e53cd33..5910585 100644 --- a/newbinding/src/TargetMachine.py +++ b/newbinding/src/TargetMachine.py @@ -1,5 +1,12 @@ from binding import * from namespace import llvm +from StringRef import StringRef +from CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc +from GlobalValue import GlobalValue +from Target import Target +from DataLayout import DataLayout +from TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) TargetMachine = llvm.Class() @@ -8,4 +15,22 @@ class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' delete = Destructor() + getTarget = Method(const(ref(Target))) + getTargetTriple = Method(cast(StringRef, str)) + getTargetCPU = Method(cast(StringRef, str)) + getTargetFeatureString = Method(cast(StringRef, str)) + + getRelocationModel = Method(Reloc.Model) + getCodeModel = Method(CodeModel.Model) + getTLSModel = Method(TLSModel.Model, ptr(GlobalValue)) + getOptLevel = Method(CodeGenOpt.Level) + + hasMCUseDwarfDirectory = Method(cast(Bool, bool)) + setMCUseDwarfDirectory = Method(Void, cast(bool, Bool)) + + getDataLayout = Method(const(ownedptr(DataLayout))) + getScalarTargetTransformInfo = Method(const( + ownedptr(ScalarTargetTransformInfo))) + getVectorTargetTransformInfo = Method(const( + ownedptr(VectorTargetTransformInfo))) diff --git a/newbinding/src/TargetTransformInfo.py b/newbinding/src/TargetTransformInfo.py new file mode 100644 index 0000000..8e3c17e --- /dev/null +++ b/newbinding/src/TargetTransformInfo.py @@ -0,0 +1,14 @@ +from binding import * +from namespace import llvm + +ScalarTargetTransformInfo = llvm.Class() +VectorTargetTransformInfo = llvm.Class() + +@ScalarTargetTransformInfo +class ScalarTargetTransformInfo: + delete = Destructor() + +@VectorTargetTransformInfo +class VectorTargetTransformInfo: + delete = Destructor() + diff --git a/newbinding/src/Triple.py b/newbinding/src/Triple.py new file mode 100644 index 0000000..0fd894e --- /dev/null +++ b/newbinding/src/Triple.py @@ -0,0 +1,55 @@ +from binding import * +from namespace import llvm +from StringRef import StringRef + +Triple = llvm.Class() + +@Triple +class Triple: + _include_ = 'llvm/ADT/Triple.h' + + new = Constructor() + new |= Constructor(cast(str, StringRef)) + new |= Constructor(cast(str, StringRef), + cast(str, StringRef), cast(str, StringRef)) + + def _return_str(): + return Method(cast(StringRef, str)) + + getTriple = _return_str() + getArchName = _return_str() + getVendorName = _return_str() + getOSName = _return_str() + getEnvironmentName = _return_str() + getOSAndEnvironmentName = _return_str() + + @CustomPythonMethod + def __str__(self): + return self.getTriple() + + def _return_bool(*args): + return Method(cast(bool, Bool), *args) + + isArch64Bit = _return_bool() + isArch32Bit = _return_bool() + isArch16Bit = _return_bool() + isOSVersionLT = _return_bool(cast(int, Unsigned), + cast(int, Unsigned), + cast(int, Unsigned)).require_only(1) + + isMacOSXVersionLT = _return_bool(cast(int, Unsigned), + cast(int, Unsigned), + cast(int, Unsigned)).require_only(1) + + isMacOSX = _return_bool() + isOSDarwin = _return_bool() + isOSCygMing = _return_bool() + isOSWindows = _return_bool() + # isOSNaCl = _return_bool() + isOSBinFormatELF = _return_bool() + isOSBinFormatCOFF = _return_bool() + isEnvironmentMachO = _return_bool() + + get32BitArchVariant = Method(Triple) + get64BitArchVariant = Method(Triple) + diff --git a/newbinding/test2.py b/newbinding/test2.py index a304426..93fccb8 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -124,8 +124,31 @@ def test_engine_builder(): eb.setOptLevel(api.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) tm = eb.selectTarget() + + print 'target triple:', tm.getTargetTriple() + print 'target cpu:', tm.getTargetCPU() + print 'target feature string:', tm.getTargetFeatureString() + + target = tm.getTarget() + print 'target name:', target.getName() + print 'target short description:', target.getShortDescription() + + assert target.hasJIT() + assert target.hasTargetMachine() + ee = eb.create(tm) + triple = api.Triple.new('x86_64-unknown-linux') + assert triple.getArchName() == 'x86_64' + assert triple.getVendorName() == 'unknown' + assert triple.getOSName() == 'linux' + assert triple.isArch64Bit() + assert not triple.isArch32Bit() + triple_32variant = triple.get32BitArchVariant() + assert triple_32variant.isArch32Bit() + + print tm.getDataLayout() + def main(): for name, value in globals().items(): From 372d6804e4ba2b38cd10172323413b2d48417133 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 17:02:09 -0600 Subject: [PATCH 062/338] Add bindings for Pass, PassManagers, PassManagerBuilder and TargetLibraryInfo. --- newbinding/binding.py | 2 + newbinding/src/DataLayout.py | 5 +- newbinding/src/Pass.py | 35 +++++++++++++ newbinding/src/PassManager.py | 34 +++++++++++++ newbinding/src/PassManagerBuilder.py | 19 +++++++ newbinding/src/TargetLibraryInfo.py | 76 ++++++++++++++++++++++++++++ newbinding/test2.py | 25 ++++++++- 7 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 newbinding/src/Pass.py create mode 100644 newbinding/src/PassManager.py create mode 100644 newbinding/src/PassManagerBuilder.py create mode 100644 newbinding/src/TargetLibraryInfo.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 69267dc..cb40d1e 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -195,6 +195,8 @@ class Enum(object): def __init__(self, *value_names): self.parent = None + if len(value_names) == 1: + value_names = filter(bool, value_names[0].replace(',', ' ').split()) self.value_names = value_names self.includes = set() diff --git a/newbinding/src/DataLayout.py b/newbinding/src/DataLayout.py index a1ef8bc..74d1ad0 100644 --- a/newbinding/src/DataLayout.py +++ b/newbinding/src/DataLayout.py @@ -6,8 +6,9 @@ from Module import Module from Type import Type, IntegerType, StructType from SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable +from Pass import ImmutablePass -DataLayout = llvm.Class() +DataLayout = llvm.Class(ImmutablePass) StructLayout = llvm.Class() @DataLayout @@ -24,8 +25,6 @@ class DataLayout: else: return DataLayout._new_string(arg) - delete = Destructor() - isLittleEndian = Method(cast(Bool, bool)) isBigEndian = Method(cast(Bool, bool)) diff --git a/newbinding/src/Pass.py b/newbinding/src/Pass.py new file mode 100644 index 0000000..5842232 --- /dev/null +++ b/newbinding/src/Pass.py @@ -0,0 +1,35 @@ +from binding import * +from namespace import llvm +from StringRef import StringRef +from Module import Module +from Function import Function + +Pass = llvm.Class() +ModulePass = llvm.Class(Pass) +FunctionPass = llvm.Class(Pass) +ImmutablePass = llvm.Class(ModulePass) + + +@Pass +class Pass: + _include_ = 'llvm/Pass.h' + + delete = Destructor() + getPassName = Method(cast(StringRef, str)) + + +@ModulePass +class ModulePass: + runOnModule = Method(cast(Bool, bool), ref(Module)) + + +@FunctionPass +class FunctionPass: + doInitialization = Method(cast(Bool, bool), ref(Module)) + doFinalization = Method(cast(Bool, bool), ref(Module)) + + +@ImmutablePass +class ImmutablePass: + pass + diff --git a/newbinding/src/PassManager.py b/newbinding/src/PassManager.py new file mode 100644 index 0000000..f969192 --- /dev/null +++ b/newbinding/src/PassManager.py @@ -0,0 +1,34 @@ +from binding import * +from namespace import llvm +from Pass import Pass +from Module import Module +from Function import Function + +PassManagerBase = llvm.Class() +PassManager = llvm.Class(PassManagerBase) +FunctionPassManager = llvm.Class(PassManagerBase) + +@PassManagerBase +class PassManagerBase: + _include_ = 'llvm/PassManager.h' + + delete = Destructor() + + add = Method(Void, ownedptr(Pass)) + +@PassManager +class PassManager: + new = Constructor() + + run = Method(cast(Bool, bool), ref(Module)) + + +@FunctionPassManager +class FunctionPassManager: + new = Constructor(ptr(Module)) + + run = Method(cast(Bool, bool), ref(Function)) + + doInitialization = Method(cast(Bool, bool)) + doFinalization = Method(cast(Bool, bool)) + diff --git a/newbinding/src/PassManagerBuilder.py b/newbinding/src/PassManagerBuilder.py new file mode 100644 index 0000000..2e2ea5e --- /dev/null +++ b/newbinding/src/PassManagerBuilder.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm +from PassManager import PassManagerBase, FunctionPassManager + +@llvm.Class() +class PassManagerBuilder: + _include_ = 'llvm/Transforms/IPO/PassManagerBuilder.h' + + new = Constructor() + delete = Destructor() + + populateFunctionPassManager = Method(Void, ref(FunctionPassManager)) + populateModulePassManager = Method(Void, ref(PassManagerBase)) + populateLTOPassManager = Method(Void, + ref(PassManagerBase), + cast(bool, Bool), + cast(bool, Bool), + cast(bool, Bool)).require_only(3) + diff --git a/newbinding/src/TargetLibraryInfo.py b/newbinding/src/TargetLibraryInfo.py new file mode 100644 index 0000000..a5ba28d --- /dev/null +++ b/newbinding/src/TargetLibraryInfo.py @@ -0,0 +1,76 @@ +from binding import * +from namespace import llvm +from Triple import Triple +from Pass import ImmutablePass +from StringRef import StringRef + +TargetLibraryInfo = llvm.Class(ImmutablePass) + +@llvm.Class() +class LibFunc: + Func = Enum(''' + ZdaPv, ZdlPv, Znaj, ZnajRKSt9nothrow_t, + Znam, ZnamRKSt9nothrow_t, Znwj, ZnwjRKSt9nothrow_t, + Znwm, ZnwmRKSt9nothrow_t, cxa_atexit, cxa_guard_abort, + cxa_guard_acquire, cxa_guard_release, memcpy_chk, + acos, acosf, acosh, acoshf, + acoshl, acosl, asin, asinf, + asinh, asinhf, asinhl, asinl, + atan, atan2, atan2f, atan2l, + atanf, atanh, atanhf, atanhl, + atanl, calloc, cbrt, cbrtf, + cbrtl, ceil, ceilf, ceill, + copysign, copysignf, copysignl, cos, + cosf, cosh, coshf, coshl, + cosl, exp, exp10, exp10f, + exp10l, exp2, exp2f, exp2l, + expf, expl, expm1, expm1f, + expm1l, fabs, fabsf, fabsl, + fiprintf, + floor, floorf, floorl, fmod, + fmodf, fmodl, fputc, + fputs, free, fwrite, iprintf, + log, log10, log10f, log10l, + log1p, log1pf, log1pl, log2, + log2f, log2l, logb, logbf, + logbl, logf, logl, malloc, + memchr, memcmp, memcpy, memmove, + memset, memset_pattern16, nearbyint, nearbyintf, + nearbyintl, posix_memalign, pow, powf, + powl, putchar, puts, + realloc, reallocf, rint, rintf, + rintl, round, roundf, roundl, + sin, sinf, sinh, sinhf, + sinhl, sinl, siprintf, + sqrt, sqrtf, sqrtl, stpcpy, + strcat, strchr, strcmp, strcpy, + strcspn, strdup, strlen, strncat, + strncmp, strncpy, strndup, strnlen, + strpbrk, strrchr, strspn, strstr, + strtod, strtof, strtol, strtold, + strtoll, strtoul, strtoull, tan, + tanf, tanh, tanhf, tanhl, + tanl, trunc, truncf, + truncl, valloc, NumLibFuncs''') + # not in llvm-3.2 abs, ffs, ffsl, ffsll, fprintf, isascii, + # isdigit, labs, llabs, printf, sprintf, toascii + +@TargetLibraryInfo +class TargetLibraryInfo: + _include_ = 'llvm/Target/TargetLibraryInfo.h' + + new = Constructor() + new |= Constructor(ref(Triple)) + + delete = Destructor() + + has = Method(cast(bool, Bool), LibFunc.Func) + hasOptimizedCodeGen = Method(cast(bool, Bool), LibFunc.Func) + + getName = Method(cast(str, StringRef), LibFunc.Func) + + setUnavailable = Method(Void, LibFunc.Func) + setAvailable = Method(Void, LibFunc.Func) + setAvailableWithName = Method(Void, LibFunc.Func, cast(str, StringRef)) + disableAllFunctions = Method() + diff --git a/newbinding/test2.py b/newbinding/test2.py index 93fccb8..e2f8dd2 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -8,7 +8,6 @@ def test_basic_jit_use(): api.InitializeNativeTarget() context = api.getGlobalContext() - m = api.Module.new("modname", context) print m.getModuleIdentifier() m.setModuleIdentifier('modname2') @@ -82,6 +81,26 @@ def test_basic_jit_use(): errio = StringIO() print m + # build pass manager + + pmb = api.PassManagerBuilder.new() + + fpm = api.FunctionPassManager.new(m) + pm = api.PassManager.new() + + pmb.populateFunctionPassManager(fpm) + pmb.populateModulePassManager(pm) + + fpm.doInitialization() + fpm.run(fn) + fpm.doFinalization() + + pm.run(m) + + print m + + # build engine + ee = api.ExecutionEngine.createJIT(m, errio) print ee, errio.getvalue() print ee.getDataLayout().getStringRepresentation() @@ -149,6 +168,10 @@ def test_engine_builder(): print tm.getDataLayout() + pm = api.PassManager.new() + pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + pm.add(api.TargetLibraryInfo.new()) + def main(): for name, value in globals().items(): From 7788346152a461142f5256f832d66d2d9347981e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 17:32:30 -0600 Subject: [PATCH 063/338] Improve enum implementation --- newbinding/binding.py | 48 +++++++++++++++++++------------------------ newbinding/gen.py | 7 +++++++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index cb40d1e..4205c64 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -125,6 +125,8 @@ class Class(_Type): # generate methods for meth in self.methods: meth.compile_cpp(writer) + for enum in self.enums: + enum.compile_cpp(writer) # generate method table writer.println('static') @@ -135,6 +137,11 @@ class Class(_Type): name = meth.name func = meth.c_name writer.println(fmt % locals()) + for enumkind in self.enums: + for enum in enumkind.value_names: + name = enum + func = enumkind.c_name(enum) + writer.println(fmt % locals()) writer.println('{ NULL },') writer.println('};') writer.println() @@ -212,38 +219,22 @@ class Enum(object): return self.fullname def wrap(self, writer, val): - ret = writer.declare('PyObject*', 'NULL') - with writer.block('switch(%s) ' % val): - for v in self.value_names: - writer.println('case %s::%s:' % (self.parent, v)) - with writer.indent(): - fmt = '%(ret)s = PyString_FromString("%(v)s");' - writer.println(fmt % locals()) - writer.println('break;') - else: - writer.println('default:') - with writer.indent(): - writer.raises(ValueError, 'Invalid enum %s' % v) + ret = writer.declare('PyObject*', 'PyInt_FromLong(%s)' % val) return ret def unwrap(self, writer, val): - tostring = 'PyString_AsString(%(val)s)' % locals() - string = writer.declare('const char*', tostring) - ret = writer.declare('%s::%s' % (self.parent, self.name)) - parent = self.parent - iffmt = 'if (string_equal(%(string)s, "%(v)s"))' - for i, v in enumerate(self.value_names): - with writer.block(iffmt % locals()): - fmt = '%(ret)s = %(parent)s::%(v)s;' - writer.println(fmt % locals()) - if i == 0: - iffmt = 'else ' + iffmt - with writer.block('else'): - writer.raises(ValueError, 'Invalid enum.') + convert_long_to_enum = '(%s)PyInt_AsLong(%s)' % (self.fullname, val) + ret = writer.declare(self.fullname, convert_long_to_enum) return ret + def c_name(self, enum): + return cg.mangle("%s_%s_%s" % (self.parent, self.name, enum)) + def compile_cpp(self, writer): - pass + for enum in self.value_names: + with writer.py_function(self.c_name(enum)): + ret = self.wrap(writer, '::'.join([self.parent.fullname, enum])) + writer.return_value(ret) def compile_py(self, writer): with writer.block('class %s:' % self.name): @@ -251,9 +242,12 @@ class Enum(object): for v in self.value_names: if v in RESERVED: k = '%s_' % v + fmt = '%(k)s = getattr(%(p)s, "%(v)s")()' else: k = v - writer.println('%(k)s = "%(v)s"' % locals()) + fmt = '%(k)s = %(p)s.%(v)s()' + p = '.'.join(['_api'] + self.parent.fullname.split('::')[1:]) + writer.println(fmt % locals()) writer.println() class Method(object): diff --git a/newbinding/gen.py b/newbinding/gen.py index 47f5655..7c56452 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -136,6 +136,13 @@ static name = u.name func = u.c_name writer.println(fmt % locals()) + for u in units: + if isinstance(u, Enum): + for enum in u.value_names: + name = enum + func = u.c_name(enum) + writer.println(fmt % locals()) + writer.println('{ NULL },') writer.println('};') writer.println() From 1f49bb6d7c7e1fcfeb0ab47c3770ec35e65917dc Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 3 Feb 2013 12:57:13 -0600 Subject: [PATCH 064/338] Binding for PassManagerBuilder --- newbinding/binding.py | 92 +++++++++++++++++++++++++ newbinding/include/llvm_binding/extra.h | 14 ++-- newbinding/{src => }/namespace.py | 0 newbinding/src/EngineBuilder.py | 3 +- newbinding/src/PassManagerBuilder.py | 24 +++++++ newbinding/src/Transforms/IPO.py | 9 +++ newbinding/src/Transforms/__init__.py | 10 +++ newbinding/src/__init__.py | 5 +- newbinding/test2.py | 4 ++ 9 files changed, 151 insertions(+), 10 deletions(-) rename newbinding/{src => }/namespace.py (100%) create mode 100644 newbinding/src/Transforms/IPO.py create mode 100644 newbinding/src/Transforms/__init__.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 4205c64..142c8ef 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -83,6 +83,7 @@ class Class(_Type): self.methods = [] self.pymethods = [] self.enums = [] + self.attrs = [] self.includes = set() self.downcastables = set() @@ -103,6 +104,10 @@ class Class(_Type): v.name = k v.parent = self setattr(self, k, v) + elif isinstance(v, Attr): + self.attrs.append(v) + v.name = k + v.parent = self elif isinstance(v, CustomPythonMethod): self.pymethods.append(v) elif k == '_include_': @@ -127,6 +132,8 @@ class Class(_Type): meth.compile_cpp(writer) for enum in self.enums: enum.compile_cpp(writer) + for attr in self.attrs: + attr.compile_cpp(writer) # generate method table writer.println('static') @@ -142,6 +149,16 @@ class Class(_Type): name = enum func = enumkind.c_name(enum) writer.println(fmt % locals()) + for attr in self.attrs: + # getter + name = attr.getter_name + func = attr.getter_c_name + writer.println(fmt % locals()) + # setter + name = attr.setter_name + func = attr.setter_c_name + writer.println(fmt % locals()) + writer.println('{ NULL },') writer.println('};') writer.println() @@ -160,6 +177,8 @@ class Class(_Type): meth.compile_py(writer) for meth in self.pymethods: meth.compile_py(writer) + for attr in self.attrs: + attr.compile_py(writer) writer.println() @property @@ -587,3 +606,76 @@ class CustomPythonStaticMethod(CustomPythonMethod): writer.println('@staticmethod') super(CustomPythonStaticMethod, self).compile_py(writer) + +class Attr(object): + def __init__(self, getter, setter): + self.getter = getter + self.setter = setter + + @property + def fullname(self): + try: + name = self.realname + except AttributeError: + name = self.name + return '::'.join([self.parent.fullname, name]) + + def __str__(self): + return self.fullname + + @property + def getter_name(self): + return '%s_get' % self.name + + @property + def setter_name(self): + return '%s_set' % self.name + + @property + def getter_c_name(self): + return cg.mangle('%s_get' % self.fullname) + + @property + def setter_c_name(self): + return cg.mangle('%s_set' % self.fullname) + + def compile_cpp(self, writer): + # getter + with writer.py_function(self.getter_c_name): + (this,) = writer.parse_arguments('args', ptr(self.parent)) + attr = self.name + ret = writer.declare(self.getter.fullname, + '%(this)s->%(attr)s' % locals()) + writer.return_value(self.getter.wrap(writer, ret)) + # setter + with writer.py_function(self.setter_c_name): + (this, value) = writer.parse_arguments('args', ptr(self.parent), + self.setter) + attr = self.name + writer.println('%(this)s->%(attr)s = %(value)s;' % locals()) + writer.return_value(None) + + def compile_py(self, writer): + name = self.name + parent = '.'.join(self.parent.fullname.split('::')[1:]) + getter = '.'.join([parent, self.getter_name]) + setter = '.'.join([parent, self.setter_name]) + writer.println('@property') + with writer.block('def %(name)s(self):' % locals()): + unself = writer.unwrap('self') + ret = writer.new_symbol('ret') + writer.println('%(ret)s = _api.%(getter)s(%(unself)s)' % locals()) + is_ownedptr = isinstance(self.getter, ownedptr) + writer.return_value(writer.wrap(ret, is_ownedptr)) + writer.println() + writer.println('@%(name)s.setter' % locals()) + with writer.block('def %(name)s(self, value):' % locals()): + unself = writer.unwrap('self') + unvalue = writer.unwrap('value') + if isinstance(self.setter, ownedptr): + writer.release_ownership(unvalue) + writer.println('return _api.%(setter)s(%(unself)s, %(unvalue)s)' % + locals()) + writer.println() + + diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 46dd42a..c69f177 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -163,13 +163,13 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, className); } -static -bool string_equal(const char *A, const char *B){ - for (; *A and *B; ++A, ++B) { - if (*A != *B) return false; - } - return true; -} +//static +//bool string_equal(const char *A, const char *B){ +// for (; *A and *B; ++A, ++B) { +// if (*A != *B) return false; +// } +// return true; +//} //////////// static diff --git a/newbinding/src/namespace.py b/newbinding/namespace.py similarity index 100% rename from newbinding/src/namespace.py rename to newbinding/namespace.py diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index 07ffcc0..d9594f0 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -50,8 +50,9 @@ class EngineBuilder: _selectTarget0.realname = 'selectTarget' _selectTarget1 = CustomMethod('EngineBuilder_selectTarget', + PyObjectPtr, const(ref(Triple)), cast(str, StringRef), - cast(str, StringRef), PyObjectPtr), + cast(str, StringRef), PyObjectPtr) @CustomPythonMethod def selectTarget(self, *args): diff --git a/newbinding/src/PassManagerBuilder.py b/newbinding/src/PassManagerBuilder.py index 2e2ea5e..11fedfb 100644 --- a/newbinding/src/PassManagerBuilder.py +++ b/newbinding/src/PassManagerBuilder.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm from PassManager import PassManagerBase, FunctionPassManager +from TargetLibraryInfo import TargetLibraryInfo +from Pass import Pass @llvm.Class() class PassManagerBuilder: @@ -17,3 +19,25 @@ class PassManagerBuilder: cast(bool, Bool), cast(bool, Bool)).require_only(3) + def _attr_int(): + return Attr(getter=cast(Unsigned, int), + setter=cast(int, Unsigned)) + + OptLevel = _attr_int() + SizeLevel = _attr_int() + + def _attr_bool(): + return Attr(getter=cast(Bool, bool), + setter=cast(bool, Bool)) + + DisableSimplifyLibCalls = _attr_bool() + DisableUnitAtATime = _attr_bool() + DisableUnrollLoops = _attr_bool() + Vectorize = _attr_bool() + LoopVectorize = _attr_bool() + + LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo), + setter=ownedptr(TargetLibraryInfo)) + + Inliner = Attr(getter=ownedptr(Pass), + setter=ownedptr(Pass)) diff --git a/newbinding/src/Transforms/IPO.py b/newbinding/src/Transforms/IPO.py new file mode 100644 index 0000000..6c2fc26 --- /dev/null +++ b/newbinding/src/Transforms/IPO.py @@ -0,0 +1,9 @@ +from binding import * +from namespace import llvm +from ..Pass import Pass + +llvm.includes.add('llvm/Transforms/IPO.h') + +createFunctionInliningPass = llvm.Function('createFunctionInliningPass', + ptr(Pass), + cast(int, Unsigned)).require_only(0) diff --git a/newbinding/src/Transforms/__init__.py b/newbinding/src/Transforms/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Transforms/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index 1042826..f67a3c4 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -5,7 +5,8 @@ def _init(): if ((fname.endswith('.py') or fname.endswith('.pyc')) and not fname.startswith('__init__')): modname = os.path.basename(fname).rsplit('.', 1)[0] - topname = __name__.rsplit('.', 1)[0] - importlib.import_module('.' + modname, topname) + importlib.import_module('.' + modname, __name__) _init() + +import Transforms \ No newline at end of file diff --git a/newbinding/test2.py b/newbinding/test2.py index e2f8dd2..248e32a 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -84,6 +84,10 @@ def test_basic_jit_use(): # build pass manager pmb = api.PassManagerBuilder.new() + pmb.OptLevel = 3 + assert pmb.OptLevel == 3 + pmb.LibraryInfo = api.TargetLibraryInfo.new() + pmb.Inliner = api.createFunctionInliningPass() fpm = api.FunctionPassManager.new(m) pm = api.PassManager.new() From c085bef46e4bd03ca60abff0ba46928ce7f81ad7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 3 Feb 2013 15:01:57 -0600 Subject: [PATCH 065/338] Rename the tests --- newbinding/Makefile | 4 +-- newbinding/test.py | 32 ------------------------ newbinding/{test2.py => test_binding.py} | 0 3 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 newbinding/test.py rename newbinding/{test2.py => test_binding.py} (100%) diff --git a/newbinding/Makefile b/newbinding/Makefile index 735d4ff..8573235 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -13,10 +13,10 @@ clean: cleantemp cleantemp: rm -f api.cpp api.py - rm -f src/*.pyc + rm -f src/*.pyc src/Transforms/*.pyc check: _api.so api.py - $(PYTHON) test2.py + $(PYTHON) test_binding.py @PHONY: all clean check diff --git a/newbinding/test.py b/newbinding/test.py deleted file mode 100644 index bed9e1a..0000000 --- a/newbinding/test.py +++ /dev/null @@ -1,32 +0,0 @@ -import _api - -context = _api.getGlobalContext() -modname = "modname" -module = _api.Module.new(modname, context) -assert modname == _api.Module.getModuleIdentifier(module) -modname2 = "newmodname" -_api.Module.setModuleIdentifier(module, modname2) -assert modname2 == _api.Module.getModuleIdentifier(module) - -_api.Module.dump(module) - -_api.Module.delete(module) - -voidty = _api.Type.getVoidTy(context) -assert _api.Type.isVoidTy(voidty) -assert not _api.Type.isLabelTy(voidty) - -int21ty = _api.Type.getIntNTy(context, 21) -assert _api.Type.isIntegerTy(int21ty) -assert _api.Type.isIntegerTy(int21ty, 21) -_api.Type.dump(int21ty) - -halfty = _api.Type.getHalfTy(context) -assert _api.Type.isHalfTy(halfty) -_api.Type.dump(halfty) - -fnty = _api.FunctionType.get(halfty, False) -_api.Type.dump(fnty) - - - diff --git a/newbinding/test2.py b/newbinding/test_binding.py similarity index 100% rename from newbinding/test2.py rename to newbinding/test_binding.py From 961c5e99e1191f44fb192d226119877f695a84ce Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 3 Feb 2013 15:09:07 -0600 Subject: [PATCH 066/338] Re-organize --- newbinding/Makefile | 6 +++--- newbinding/{ => gen}/binding.py | 0 newbinding/{ => gen}/codegen.py | 0 newbinding/{ => gen}/gen.py | 4 ++-- newbinding/src/{ => ADT}/SmallVector.py | 2 +- newbinding/src/{ => ADT}/StringRef.py | 2 +- newbinding/src/{ => ADT}/Triple.py | 2 +- newbinding/src/ADT/__init__.py | 10 ++++++++++ .../AssemblyAnnotationWriter.py | 2 +- newbinding/src/Assembly/__init__.py | 10 ++++++++++ newbinding/src/BasicBlock.py | 2 +- .../src/{ => CodeGen}/MachineCodeInfo.py | 2 +- newbinding/src/CodeGen/__init__.py | 10 ++++++++++ newbinding/src/DataLayout.py | 4 ++-- newbinding/src/DerivedTypes.py | 2 +- newbinding/src/EngineBuilder.py | 10 +++++----- .../{ => ExecutionEngine}/ExecutionEngine.py | 20 +++++++++---------- newbinding/src/ExecutionEngine/__init__.py | 10 ++++++++++ newbinding/src/IRBuilder.py | 4 ++-- newbinding/src/Module.py | 6 +++--- newbinding/src/Pass.py | 2 +- newbinding/src/{ => Support}/CodeGen.py | 2 +- newbinding/src/Support/MemoryBuffer.py | 9 +++++++++ newbinding/src/{ => Support}/Target.py | 4 ++-- newbinding/src/{ => Support}/TargetSelect.py | 4 ++-- newbinding/src/Support/__init__.py | 10 ++++++++++ newbinding/src/{ => Support}/raw_ostream.py | 6 +++--- .../src/{ => Target}/TargetLibraryInfo.py | 8 ++++---- newbinding/src/{ => Target}/TargetMachine.py | 16 +++++++-------- newbinding/src/Target/__init__.py | 10 ++++++++++ newbinding/src/TargetTransformInfo.py | 2 ++ newbinding/src/Transforms/IPO.py | 2 +- .../{ => Transforms}/PassManagerBuilder.py | 8 ++++---- newbinding/src/Type.py | 4 ++-- newbinding/src/Value.py | 6 +++--- newbinding/src/__init__.py | 2 +- newbinding/{ => src}/namespace.py | 0 37 files changed, 137 insertions(+), 66 deletions(-) rename newbinding/{ => gen}/binding.py (100%) rename newbinding/{ => gen}/codegen.py (100%) rename newbinding/{ => gen}/gen.py (98%) rename newbinding/src/{ => ADT}/SmallVector.py (92%) rename newbinding/src/{ => ADT}/StringRef.py (76%) rename newbinding/src/{ => ADT}/Triple.py (98%) create mode 100644 newbinding/src/ADT/__init__.py rename newbinding/src/{ => Assembly}/AssemblyAnnotationWriter.py (81%) create mode 100644 newbinding/src/Assembly/__init__.py rename newbinding/src/{ => CodeGen}/MachineCodeInfo.py (91%) create mode 100644 newbinding/src/CodeGen/__init__.py rename newbinding/src/{ => ExecutionEngine}/ExecutionEngine.py (89%) create mode 100644 newbinding/src/ExecutionEngine/__init__.py rename newbinding/src/{ => Support}/CodeGen.py (93%) create mode 100644 newbinding/src/Support/MemoryBuffer.py rename newbinding/src/{ => Support}/Target.py (89%) rename newbinding/src/{ => Support}/TargetSelect.py (54%) create mode 100644 newbinding/src/Support/__init__.py rename newbinding/src/{ => Support}/raw_ostream.py (73%) rename newbinding/src/{ => Target}/TargetLibraryInfo.py (95%) rename newbinding/src/{ => Target}/TargetMachine.py (72%) create mode 100644 newbinding/src/Target/__init__.py rename newbinding/src/{ => Transforms}/PassManagerBuilder.py (88%) rename newbinding/{ => src}/namespace.py (100%) diff --git a/newbinding/Makefile b/newbinding/Makefile index 8573235..0e7924f 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -5,15 +5,15 @@ all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp $(PYTHON) setup.py build_ext --inplace -api.cpp api.py: src/*.py include/llvm_binding/*.h gen.py binding.py - $(PYTHON) gen.py api src +api.cpp api.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/binding.py + $(PYTHON) gen/gen.py api src clean: cleantemp rm -f _api.so _capsule.so cleantemp: rm -f api.cpp api.py - rm -f src/*.pyc src/Transforms/*.pyc + rm -f src/*.pyc src/Transforms/*.pyc src/ADT/*.pyc src/Assembly/*.pyc src/CodeGen/*.pyc src/ExecutionEngine/*.pyc src/Target/*.pyc src/Transforms/*.pyc check: _api.so api.py diff --git a/newbinding/binding.py b/newbinding/gen/binding.py similarity index 100% rename from newbinding/binding.py rename to newbinding/gen/binding.py diff --git a/newbinding/codegen.py b/newbinding/gen/codegen.py similarity index 100% rename from newbinding/codegen.py rename to newbinding/gen/codegen.py diff --git a/newbinding/gen.py b/newbinding/gen/gen.py similarity index 98% rename from newbinding/gen.py rename to newbinding/gen/gen.py index 7c56452..89399f3 100644 --- a/newbinding/gen.py +++ b/newbinding/gen/gen.py @@ -1,4 +1,4 @@ -import sys +import sys, os from binding import * import codegen @@ -59,7 +59,7 @@ def wrap_println_from_file(file): def main(): outputfilename = sys.argv[1] entry_modname = sys.argv[2] - + sys.path += [os.path.dirname(os.curdir)] entry_module = __import__(entry_modname) units = [] diff --git a/newbinding/src/SmallVector.py b/newbinding/src/ADT/SmallVector.py similarity index 92% rename from newbinding/src/SmallVector.py rename to newbinding/src/ADT/SmallVector.py index 5b48aba..f52ff60 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/ADT/SmallVector.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class SmallVector_Type: diff --git a/newbinding/src/StringRef.py b/newbinding/src/ADT/StringRef.py similarity index 76% rename from newbinding/src/StringRef.py rename to newbinding/src/ADT/StringRef.py index fb3b896..e6fc8f2 100644 --- a/newbinding/src/StringRef.py +++ b/newbinding/src/ADT/StringRef.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class StringRef: diff --git a/newbinding/src/Triple.py b/newbinding/src/ADT/Triple.py similarity index 98% rename from newbinding/src/Triple.py rename to newbinding/src/ADT/Triple.py index 0fd894e..82de57e 100644 --- a/newbinding/src/Triple.py +++ b/newbinding/src/ADT/Triple.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm from StringRef import StringRef Triple = llvm.Class() diff --git a/newbinding/src/ADT/__init__.py b/newbinding/src/ADT/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/ADT/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/AssemblyAnnotationWriter.py b/newbinding/src/Assembly/AssemblyAnnotationWriter.py similarity index 81% rename from newbinding/src/AssemblyAnnotationWriter.py rename to newbinding/src/Assembly/AssemblyAnnotationWriter.py index d2b5a5d..6b4d694 100644 --- a/newbinding/src/AssemblyAnnotationWriter.py +++ b/newbinding/src/Assembly/AssemblyAnnotationWriter.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class AssemblyAnnotationWriter: diff --git a/newbinding/src/Assembly/__init__.py b/newbinding/src/Assembly/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Assembly/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py index b0716cd..61a09d7 100644 --- a/newbinding/src/BasicBlock.py +++ b/newbinding/src/BasicBlock.py @@ -3,7 +3,7 @@ from namespace import llvm from Value import Function, BasicBlock from Instruction import Instruction, TerminatorInst from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef @BasicBlock class BasicBlock: diff --git a/newbinding/src/MachineCodeInfo.py b/newbinding/src/CodeGen/MachineCodeInfo.py similarity index 91% rename from newbinding/src/MachineCodeInfo.py rename to newbinding/src/CodeGen/MachineCodeInfo.py index 5d91e3a..fc3a1b6 100644 --- a/newbinding/src/MachineCodeInfo.py +++ b/newbinding/src/CodeGen/MachineCodeInfo.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm MachineCodeInfo = llvm.Class() diff --git a/newbinding/src/CodeGen/__init__.py b/newbinding/src/CodeGen/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/CodeGen/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/DataLayout.py b/newbinding/src/DataLayout.py index 74d1ad0..704c4b1 100644 --- a/newbinding/src/DataLayout.py +++ b/newbinding/src/DataLayout.py @@ -1,10 +1,10 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef from Module import Module from Type import Type, IntegerType, StructType -from SmallVector import SmallVector_Value +from ADT.SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable from Pass import ImmutablePass diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index efce8b8..af9e757 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -2,7 +2,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from Type import Type -from SmallVector import SmallVector_Type +from ADT.SmallVector import SmallVector_Type FunctionType = llvm.Class(Type) diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index d9594f0..4b68a25 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -2,11 +2,11 @@ from binding import * from namespace import llvm from Module import Module from JITMemoryManager import JITMemoryManager -from CodeGen import CodeGenOpt, Reloc, CodeModel -from StringRef import StringRef -from ExecutionEngine import ExecutionEngine -from TargetMachine import TargetMachine -from Triple import Triple +from Support.CodeGen import CodeGenOpt, Reloc, CodeModel +from ADT.StringRef import StringRef +from ExecutionEngine.ExecutionEngine import ExecutionEngine +from Target.TargetMachine import TargetMachine +from ADT.Triple import Triple EngineBuilder = llvm.Class() diff --git a/newbinding/src/ExecutionEngine.py b/newbinding/src/ExecutionEngine/ExecutionEngine.py similarity index 89% rename from newbinding/src/ExecutionEngine.py rename to newbinding/src/ExecutionEngine/ExecutionEngine.py index 5a95a16..f4bdb14 100644 --- a/newbinding/src/ExecutionEngine.py +++ b/newbinding/src/ExecutionEngine/ExecutionEngine.py @@ -1,14 +1,14 @@ from binding import * -from namespace import llvm -from Module import Module -from JITMemoryManager import JITMemoryManager -from CodeGen import CodeGenOpt, Reloc, CodeModel -from DataLayout import DataLayout -from Value import Function, GlobalValue, BasicBlock, Constant -from GlobalVariable import GlobalVariable -from MachineCodeInfo import MachineCodeInfo -from GenericValue import GenericValue -from Type import Type +from ..namespace import llvm +from ..Module import Module +from ..JITMemoryManager import JITMemoryManager +from ..Support.CodeGen import CodeGenOpt, Reloc, CodeModel +from ..DataLayout import DataLayout +from ..Value import Function, GlobalValue, BasicBlock, Constant +from ..GlobalVariable import GlobalVariable +from ..CodeGen.MachineCodeInfo import MachineCodeInfo +from ..GenericValue import GenericValue +from ..Type import Type ExecutionEngine = llvm.Class() diff --git a/newbinding/src/ExecutionEngine/__init__.py b/newbinding/src/ExecutionEngine/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/ExecutionEngine/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index cea94ce..61dd99b 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -8,8 +8,8 @@ from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst from Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst from Instruction import LandingPadInst, VAArgInst from Instruction import AtomicOrdering, SynchronizationScope -from SmallVector import SmallVector_Value, SmallVector_Unsigned -from StringRef import StringRef +from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from ADT.StringRef import StringRef from Value import Value, MDNode from Type import Type, IntegerType diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 9b392ca..539c486 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -1,12 +1,12 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef from Constant import Constant from Function import Function from DerivedTypes import FunctionType -from raw_ostream import raw_ostream -from AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @llvm.Class() class Module: diff --git a/newbinding/src/Pass.py b/newbinding/src/Pass.py index 5842232..39e894b 100644 --- a/newbinding/src/Pass.py +++ b/newbinding/src/Pass.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from StringRef import StringRef +from ADT.StringRef import StringRef from Module import Module from Function import Function diff --git a/newbinding/src/CodeGen.py b/newbinding/src/Support/CodeGen.py similarity index 93% rename from newbinding/src/CodeGen.py rename to newbinding/src/Support/CodeGen.py index 7afcd49..013caa1 100644 --- a/newbinding/src/CodeGen.py +++ b/newbinding/src/Support/CodeGen.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class Reloc: diff --git a/newbinding/src/Support/MemoryBuffer.py b/newbinding/src/Support/MemoryBuffer.py new file mode 100644 index 0000000..b960fe6 --- /dev/null +++ b/newbinding/src/Support/MemoryBuffer.py @@ -0,0 +1,9 @@ +from binding import * +from ..namespace import llvm + +MemoryBuffer = llvm.Class() + +@MemoryBuffer +class MemoryBuffer: + _include_ = 'llvm/Support/MemoryBuffer.h' + diff --git a/newbinding/src/Target.py b/newbinding/src/Support/Target.py similarity index 89% rename from newbinding/src/Target.py rename to newbinding/src/Support/Target.py index 3c2a0e1..bdaeff5 100644 --- a/newbinding/src/Target.py +++ b/newbinding/src/Support/Target.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from StringRef import StringRef +from ..namespace import llvm +from ..ADT.StringRef import StringRef Target = llvm.Class() @Target diff --git a/newbinding/src/TargetSelect.py b/newbinding/src/Support/TargetSelect.py similarity index 54% rename from newbinding/src/TargetSelect.py rename to newbinding/src/Support/TargetSelect.py index cb2eb96..4a2b171 100644 --- a/newbinding/src/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm +from ..namespace import llvm llvm.includes.add('llvm/Support/TargetSelect.h') -llvm.Function('InitializeNativeTarget') +InitializeNativeTarget = llvm.Function('InitializeNativeTarget') #llvm.Function('InitializeAllTargets') diff --git a/newbinding/src/Support/__init__.py b/newbinding/src/Support/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Support/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/raw_ostream.py b/newbinding/src/Support/raw_ostream.py similarity index 73% rename from newbinding/src/raw_ostream.py rename to newbinding/src/Support/raw_ostream.py index 2f5a6f5..ecf3614 100644 --- a/newbinding/src/raw_ostream.py +++ b/newbinding/src/Support/raw_ostream.py @@ -1,7 +1,7 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from StringRef import StringRef +from ..namespace import llvm +from ..LLVMContext import LLVMContext +from ..ADT.StringRef import StringRef @llvm.Class() class raw_ostream: diff --git a/newbinding/src/TargetLibraryInfo.py b/newbinding/src/Target/TargetLibraryInfo.py similarity index 95% rename from newbinding/src/TargetLibraryInfo.py rename to newbinding/src/Target/TargetLibraryInfo.py index a5ba28d..b90c619 100644 --- a/newbinding/src/TargetLibraryInfo.py +++ b/newbinding/src/Target/TargetLibraryInfo.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Triple import Triple -from Pass import ImmutablePass -from StringRef import StringRef +from ..namespace import llvm +from ..ADT.Triple import Triple +from ..Pass import ImmutablePass +from ..ADT.StringRef import StringRef TargetLibraryInfo = llvm.Class(ImmutablePass) diff --git a/newbinding/src/TargetMachine.py b/newbinding/src/Target/TargetMachine.py similarity index 72% rename from newbinding/src/TargetMachine.py rename to newbinding/src/Target/TargetMachine.py index 5910585..3fc16e2 100644 --- a/newbinding/src/TargetMachine.py +++ b/newbinding/src/Target/TargetMachine.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from StringRef import StringRef -from CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc -from GlobalValue import GlobalValue -from Target import Target -from DataLayout import DataLayout -from TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) +from ..namespace import llvm +from ..ADT.StringRef import StringRef +from ..Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc +from ..GlobalValue import GlobalValue +from ..Support.Target import Target +from ..DataLayout import DataLayout +from ..TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) TargetMachine = llvm.Class() diff --git a/newbinding/src/Target/__init__.py b/newbinding/src/Target/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Target/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/TargetTransformInfo.py b/newbinding/src/TargetTransformInfo.py index 8e3c17e..5761281 100644 --- a/newbinding/src/TargetTransformInfo.py +++ b/newbinding/src/TargetTransformInfo.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm +llvm.includes.add('llvm/TargetTransformInfo.h') + ScalarTargetTransformInfo = llvm.Class() VectorTargetTransformInfo = llvm.Class() diff --git a/newbinding/src/Transforms/IPO.py b/newbinding/src/Transforms/IPO.py index 6c2fc26..48b34f9 100644 --- a/newbinding/src/Transforms/IPO.py +++ b/newbinding/src/Transforms/IPO.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm from ..Pass import Pass llvm.includes.add('llvm/Transforms/IPO.h') diff --git a/newbinding/src/PassManagerBuilder.py b/newbinding/src/Transforms/PassManagerBuilder.py similarity index 88% rename from newbinding/src/PassManagerBuilder.py rename to newbinding/src/Transforms/PassManagerBuilder.py index 11fedfb..a95b6df 100644 --- a/newbinding/src/PassManagerBuilder.py +++ b/newbinding/src/Transforms/PassManagerBuilder.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from PassManager import PassManagerBase, FunctionPassManager -from TargetLibraryInfo import TargetLibraryInfo -from Pass import Pass +from ..namespace import llvm +from ..PassManager import PassManagerBase, FunctionPassManager +from ..Target.TargetLibraryInfo import TargetLibraryInfo +from ..Pass import Pass @llvm.Class() class PassManagerBuilder: diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index bf51b9d..8e6b381 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -1,8 +1,8 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from raw_ostream import raw_ostream -from StringRef import StringRef +from Support.raw_ostream import raw_ostream +from ADT.StringRef import StringRef Type = llvm.Class() IntegerType = llvm.Class(Type) diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 7460c90..5841746 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -1,10 +1,10 @@ from binding import * from namespace import llvm -from raw_ostream import raw_ostream -from AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter from Type import Type from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef Value = llvm.Class() # forward declarations diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index f67a3c4..8a1b356 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -9,4 +9,4 @@ def _init(): _init() -import Transforms \ No newline at end of file +import Transforms, ADT, Support, Assembly, ExecutionEngine, CodeGen, Target diff --git a/newbinding/namespace.py b/newbinding/src/namespace.py similarity index 100% rename from newbinding/namespace.py rename to newbinding/src/namespace.py From 168510222fc4d0975635d6b76befaff2ed14dd55 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 4 Feb 2013 16:45:49 -0600 Subject: [PATCH 067/338] Add Module bitcode writer/parser --- newbinding/gen/binding.py | 16 ++++++- newbinding/include/llvm_binding/extra.h | 60 +++++++++++++++++++++++++ newbinding/src/Bitcode/ReaderWriter.py | 30 +++++++++++++ newbinding/src/Bitcode/__init__.py | 10 +++++ newbinding/src/Support/MemoryBuffer.py | 9 ---- newbinding/src/__init__.py | 11 +++-- newbinding/test_binding.py | 16 +++++++ 7 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 newbinding/src/Bitcode/ReaderWriter.py create mode 100644 newbinding/src/Bitcode/__init__.py delete mode 100644 newbinding/src/Support/MemoryBuffer.py diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 142c8ef..d9b44af 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -26,6 +26,11 @@ class Namespace(object): self.functions.append(fn) return fn + def CustomFunction(self, *args): + fn = CustomFunction(self, *args) + self.functions.append(fn) + return fn + def Enum(self, name, *value_names): enum = Enum(*value_names) enum.parent = self @@ -444,13 +449,22 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = self.fullname.split('::', 1)[1].replace('::', '.') + func = self.name ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() +class CustomFunction(Function): + def __init__(self, parent, name, realname, return_type=Void, *args): + super(CustomFunction, self).__init__(parent, name, return_type, *args) + self.realname = realname + + @property + def fullname(self): + return self.realname + class Destructor(Method): _kind_ = 'dtor' diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index c69f177..e8f39cb 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include @@ -405,3 +407,61 @@ PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb, return pycapsule_new(eb, "llvm::EngineBuilder"); } + +static +PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx, + PyObject* FObj=NULL) +{ + using namespace llvm; + MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf); + Module* M; + if (FObj) { + std::string ErrStr; + M = ParseBitcodeFile(MB, Ctx, &ErrStr); + if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + return NULL; + } + } else { + M = ParseBitcodeFile(MB, Ctx); + } + delete MB; + return pycapsule_new(M, "llvm::Module"); +} + + +static +PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) +{ + using namespace llvm; + llvm::SmallVector sv; + llvm::raw_svector_ostream rso(sv); + llvm::WriteBitcodeToFile(M, rso); + rso.flush(); + StringRef ref = rso.str(); + PyObject* buf = PyString_FromStringAndSize(ref.data(), ref.size()); + if (-1 == PyFile_WriteObject(buf, FObj, Py_PRINT_RAW)){ + return NULL; + } + Py_RETURN_NONE; +} + +static +PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, + llvm::LLVMContext& Ctx, + PyObject* FObj = NULL) +{ + using namespace llvm; + MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf); + std::string Triple; + if (FObj) { + std::string ErrStr; + Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr); + if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + return NULL; + } + } else { + Triple = getBitcodeTargetTriple(MB, Ctx); + } + delete MB; + return PyString_FromString(Triple.c_str()); +} diff --git a/newbinding/src/Bitcode/ReaderWriter.py b/newbinding/src/Bitcode/ReaderWriter.py new file mode 100644 index 0000000..a8e8c43 --- /dev/null +++ b/newbinding/src/Bitcode/ReaderWriter.py @@ -0,0 +1,30 @@ +from binding import * +from ..namespace import llvm +from ..ADT.StringRef import StringRef +from ..Module import Module +from ..LLVMContext import LLVMContext + +llvm.includes.add('llvm/Bitcode/ReaderWriter.h') + +ParseBitCodeFile = llvm.CustomFunction('ParseBitCodeFile', + 'llvm_ParseBitCodeFile', + PyObjectPtr, # returns Module* + cast(str, StringRef), + ref(LLVMContext), + PyObjectPtr, # file-like object + ).require_only(2) + +WriteBitcodeToFile = llvm.CustomFunction('WriteBitcodeToFile', + 'llvm_WriteBitcodeToFile', + PyObjectPtr, # return None + ptr(Module), + PyObjectPtr, # file-like object + ) + +getBitcodeTargetTriple = llvm.CustomFunction('getBitcodeTargetTriple', + 'llvm_getBitcodeTargetTriple', + PyObjectPtr, # return str + cast(str, StringRef), + ref(LLVMContext), + PyObjectPtr, # file-like object + ).require_only(2) diff --git a/newbinding/src/Bitcode/__init__.py b/newbinding/src/Bitcode/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Bitcode/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/Support/MemoryBuffer.py b/newbinding/src/Support/MemoryBuffer.py deleted file mode 100644 index b960fe6..0000000 --- a/newbinding/src/Support/MemoryBuffer.py +++ /dev/null @@ -1,9 +0,0 @@ -from binding import * -from ..namespace import llvm - -MemoryBuffer = llvm.Class() - -@MemoryBuffer -class MemoryBuffer: - _include_ = 'llvm/Support/MemoryBuffer.h' - diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index 8a1b356..98c06fc 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -1,12 +1,15 @@ import os.path, importlib def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): + base = os.path.dirname(__file__) + for fname in os.listdir(base): + print fname + is_python_script = fname.endswith('.py') or fname.endswith('.pyc') + is_init_script = fname.startswith('__init__') + is_directory = os.path.isdir(os.path.join(base, fname)) + if (is_directory or is_python_script) and not is_init_script : modname = os.path.basename(fname).rsplit('.', 1)[0] importlib.import_module('.' + modname, __name__) _init() -import Transforms, ADT, Support, Assembly, ExecutionEngine, CodeGen, Target diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 248e32a..8a72aef 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -135,6 +135,22 @@ def test_basic_jit_use(): assert 44 == gvR.toUnsignedInt() + # write bitcode + bc_buffer = StringIO() + api.WriteBitcodeToFile(m, bc_buffer) + bc = bc_buffer.getvalue() + bc_buffer.close() + + # read bitcode + errbuf = StringIO() + m2 = api.ParseBitCodeFile(bc, context, errbuf) + if not m2: + raise Exception(errbuf.getvalue()) + else: + m2.setModuleIdentifier(m.getModuleIdentifier()) + assert str(m2) == str(m) + + def test_engine_builder(): api.InitializeNativeTarget() context = api.getGlobalContext() From da85049eb9efbb6174dc73e07914e2060fc50f15 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 13:44:59 -0600 Subject: [PATCH 068/338] Add support to emit assembly. --- newbinding/include/llvm_binding/extra.h | 31 ++++++++++++++++++++ newbinding/src/Support/FormattedStream.py | 9 ++++++ newbinding/src/Support/TargetSelect.py | 9 ++++++ newbinding/src/Support/raw_ostream.py | 1 + newbinding/src/Target/TargetMachine.py | 17 +++++++++++ newbinding/test_binding.py | 35 +++++++++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 newbinding/src/Support/FormattedStream.py diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index e8f39cb..77b399d 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -465,3 +466,33 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, delete MB; return PyString_FromString(Triple.c_str()); } + +static +PyObject* TargetMachine_addPassesToEmitFile( + llvm::TargetMachine *TM, + llvm::PassManagerBase & PM, + PyObject* Out, + llvm::TargetMachine::CodeGenFileType FTy, + bool disableVerify=true) +{ + using namespace llvm; + llvm::SmallVector sv; + raw_svector_ostream rso(sv); + formatted_raw_ostream fso(rso); + fso.flush(); + bool status = TM->addPassesToEmitFile(PM, fso, FTy, disableVerify); + if (status) { + StringRef sr = rso.str(); + PyObject* buf = PyString_FromStringAndSize(sr.data(), sr.size()); + if (!buf) { + return NULL; + } + if ( -1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW) ){ + return NULL; + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/newbinding/src/Support/FormattedStream.py b/newbinding/src/Support/FormattedStream.py new file mode 100644 index 0000000..17c259b --- /dev/null +++ b/newbinding/src/Support/FormattedStream.py @@ -0,0 +1,9 @@ +from binding import * +from ..namespace import llvm +from raw_ostream import raw_ostream + +@llvm.Class(raw_ostream) +class formatted_raw_ostream: + _include_ = 'llvm/Support/FormattedStream.h' + new = Constructor(ref(raw_ostream), cast(bool, Bool)) + diff --git a/newbinding/src/Support/TargetSelect.py b/newbinding/src/Support/TargetSelect.py index 4a2b171..208ef4b 100644 --- a/newbinding/src/Support/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -6,3 +6,12 @@ llvm.includes.add('llvm/Support/TargetSelect.h') InitializeNativeTarget = llvm.Function('InitializeNativeTarget') #llvm.Function('InitializeAllTargets') +InitializeNativeTargetAsmPrinter = llvm.Function( + 'InitializeNativeTargetAsmPrinter', cast(Bool, bool)) + +InitializeNativeTargetAsmParser = llvm.Function( + 'InitializeNativeTargetAsmParser', cast(Bool, bool)) + +InitializeNativeTargetDisassembler = llvm.Function( + 'InitializeNativeTargetDisassembler', cast(Bool, bool)) + diff --git a/newbinding/src/Support/raw_ostream.py b/newbinding/src/Support/raw_ostream.py index ecf3614..dcce73f 100644 --- a/newbinding/src/Support/raw_ostream.py +++ b/newbinding/src/Support/raw_ostream.py @@ -7,6 +7,7 @@ from ..ADT.StringRef import StringRef class raw_ostream: _include_ = "llvm/Support/raw_ostream.h" delete = Destructor() + flush = Method() @llvm.Class(raw_ostream) class raw_svector_ostream: diff --git a/newbinding/src/Target/TargetMachine.py b/newbinding/src/Target/TargetMachine.py index 3fc16e2..e60ed5c 100644 --- a/newbinding/src/Target/TargetMachine.py +++ b/newbinding/src/Target/TargetMachine.py @@ -7,12 +7,20 @@ from ..Support.Target import Target from ..DataLayout import DataLayout from ..TargetTransformInfo import (ScalarTargetTransformInfo, VectorTargetTransformInfo) +from ..PassManager import PassManagerBase +from ..Support.FormattedStream import formatted_raw_ostream TargetMachine = llvm.Class() @TargetMachine class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' + + CodeGenFileType = Enum(''' + CGFT_AssemblyFile + CGFT_ObjectFile + CGFT_Null''') + delete = Destructor() getTarget = Method(const(ref(Target))) @@ -34,3 +42,12 @@ class TargetMachine: ownedptr(ScalarTargetTransformInfo))) getVectorTargetTransformInfo = Method(const( ownedptr(VectorTargetTransformInfo))) + + addPassesToEmitFile = Method(cast(bool, Bool), + ref(PassManagerBase), + ref(formatted_raw_ostream), + CodeGenFileType, + cast(bool, Bool) + ).require_only(3) + + diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 8a72aef..1321eb6 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -6,6 +6,7 @@ api.capsule.set_debug(True) def test_basic_jit_use(): api.InitializeNativeTarget() + api.InitializeNativeTargetAsmPrinter() context = api.getGlobalContext() m = api.Module.new("modname", context) @@ -157,6 +158,16 @@ def test_engine_builder(): m = api.Module.new("modname", context) + int32ty = api.Type.getIntNTy(context, 32) + fnty = api.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction("foo", fnty)._downcast(api.Function) + bb = api.BasicBlock.Create(context, "entry", fn, None) + builder = api.IRBuilder.new(context) + builder.SetInsertPoint(bb) + builder.CreateRet(fn.getArgumentList()[0]) + + print fn + eb = api.EngineBuilder.new(m) eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) assert eb is eb2 @@ -192,6 +203,30 @@ def test_engine_builder(): pm.add(api.DataLayout.new(str(tm.getDataLayout()))) pm.add(api.TargetLibraryInfo.new()) + # write assembly + pm = api.PassManager.new() + pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + + raw = extra.make_raw_ostream_for_printing() + formatted = api.formatted_raw_ostream.new(raw, False) + + cgft = api.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + assert not failed + + pm.run(m) + + formatted.flush() + raw.flush() + asm = raw.str() + print asm + assert 'foo' in asm + + + + + + def main(): for name, value in globals().items(): From 450c29e0523fbae1b0772147d2490de33affa754 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 15:30:43 -0600 Subject: [PATCH 069/338] Swap out old llvm code --- llvm/2.9_update.diff | 2117 ------------------------------------- llvm/__init__.py | 154 --- llvm/_core.cpp | 2212 --------------------------------------- llvm/_dwarf.cpp | 86 -- llvm/_dwarf.h | 101 -- llvm/_util.py | 108 -- llvm/_version.py | 193 ---- llvm/capsulethunk.h | 134 --- llvm/core.py | 2158 +------------------------------------- llvm/debuginfo.py | 398 ------- llvm/ee.py | 392 ------- llvm/extra.cpp | 1361 ------------------------ llvm/extra.h | 676 ------------ llvm/llvm_c_extra.h | 31 - llvm/passes.py | 417 -------- llvm/py3k_update.diff | 973 ----------------- llvm/py3k_update.output | 62 -- llvm/tbaa.py | 51 - llvm/test_llvmpy.py | 1249 ---------------------- llvm/wrap.cpp | 70 -- llvm/wrap.h | 1277 ---------------------- 21 files changed, 20 insertions(+), 14200 deletions(-) delete mode 100644 llvm/2.9_update.diff delete mode 100644 llvm/_core.cpp delete mode 100644 llvm/_dwarf.cpp delete mode 100644 llvm/_dwarf.h delete mode 100644 llvm/_util.py delete mode 100644 llvm/_version.py delete mode 100644 llvm/capsulethunk.h delete mode 100644 llvm/debuginfo.py delete mode 100644 llvm/extra.cpp delete mode 100644 llvm/extra.h delete mode 100644 llvm/llvm_c_extra.h delete mode 100644 llvm/py3k_update.diff delete mode 100644 llvm/py3k_update.output delete mode 100644 llvm/tbaa.py delete mode 100644 llvm/test_llvmpy.py delete mode 100644 llvm/wrap.cpp delete mode 100644 llvm/wrap.h diff --git a/llvm/2.9_update.diff b/llvm/2.9_update.diff deleted file mode 100644 index 5572286..0000000 --- a/llvm/2.9_update.diff +++ /dev/null @@ -1,2117 +0,0 @@ -Index: core.py -=================================================================== ---- core.py (revision 105) -+++ core.py (working copy) -@@ -51,14 +51,15 @@ - TYPE_FP128 = 4 - TYPE_PPC_FP128 = 5 - TYPE_LABEL = 6 --TYPE_INTEGER = 7 --TYPE_FUNCTION = 8 --TYPE_STRUCT = 9 --TYPE_ARRAY = 10 --TYPE_POINTER = 11 --TYPE_OPAQUE = 12 --TYPE_VECTOR = 13 --TYPE_METADATA = 14 -+TYPE_METADATA = 7 -+TYPE_X86_MMX = 8 -+TYPE_INTEGER = 9 -+TYPE_FUNCTION = 10 -+TYPE_STRUCT = 11 -+TYPE_ARRAY = 12 -+TYPE_POINTER = 13 -+TYPE_OPAQUE = 14 -+TYPE_VECTOR = 15 - - # value IDs (llvm::Value::ValueTy enum) - VALUE_ARGUMENT = 0 -@@ -140,11 +141,21 @@ - OPCODE_INSERTVALUE = 54 - - # calling conventions --CC_C = 0 --CC_FASTCALL = 8 --CC_COLDCALL = 9 --CC_X86_STDCALL = 64 --CC_X86_FASTCALL = 65 -+CC_C = 0 -+CC_FASTCALL = 8 -+CC_COLDCALL = 9 -+CC_GHC = 10 -+CC_X86_STDCALL = 64 -+CC_X86_FASTCALL = 65 -+CC_ARM_APCS = 66 -+CC_ARM_AAPCS = 67 -+CC_ARM_AAPCS_VFP = 68 -+CC_MSP430_INTR = 69 -+CC_X86_THISCALL = 70 -+CC_PTX_KERNEL = 71 -+CC_PTX_DEVICE = 72 -+CC_MBLAZE_INTR = 73 -+CC_MBLAZE_SVOL = 74 - - # int predicates - ICMP_EQ = 32 -@@ -248,11 +259,14 @@ - ATTR_OPTIMIZE_FOR_SIZE = 1<<13 - ATTR_STACK_PROTECT = 1<<14 - ATTR_STACK_PROTECT_REQ = 1<<15 -+ATTR_ALIGNMENT = 1<<16 - ATTR_NO_CAPTURE = 1<<21 - ATTR_NO_REDZONE = 1<<22 - ATTR_NO_IMPLICIT_FLOAT = 1<<23 - ATTR_NAKED = 1<<24 - ATTR_INLINE_HINT = 1<<25 -+ATTR_STACK_ALIGNMENT = 7<<26 -+ATTR_HOTPATCH = 1<<29 - - # intrinsic IDs - from llvm._intrinsic_ids import * -Index: extra.cpp -=================================================================== ---- extra.cpp (revision 105) -+++ extra.cpp (working copy) -@@ -54,7 +54,7 @@ - #include "llvm/IntrinsicInst.h" - #include "llvm/Analysis/Verifier.h" - #include "llvm/Assembly/Parser.h" --#include "llvm/System/DynamicLibrary.h" -+#include "llvm/Support/DynamicLibrary.h" - #include "llvm/PassManager.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/Analysis/LoopPass.h" -@@ -452,12 +452,19 @@ - return eep->getPointerToFunction(fnp); - } - -+ - int LLVMInlineFunction(LLVMValueRef call) - { - llvm::Value *callp = llvm::unwrap(call); - assert(callp); - -- llvm::CallSite cs = llvm::CallSite::get(callp); -+// llvm::CallSite cs = llvm::CallSite::get(callp); -+ llvm::CallSite cs; -+ llvm::Instruction *II = llvm::dyn_cast(callp); -+ if (II->getOpcode() == llvm::Instruction::Call) -+ cs = llvm::CallSite(static_cast(II)); -+ else if (II->getOpcode() == llvm::Instruction::Invoke) -+ cs = llvm::CallSite(static_cast(II)); - - llvm::InlineFunctionInfo unused; - return llvm::InlineFunction(cs, unused); -@@ -501,13 +508,13 @@ - define_pass( DomPrinter ) - define_pass( DomViewer ) - define_pass( EdgeProfiler ) --define_pass( GEPSplitter ) -+//define_pass( GEPSplitter ) - define_pass( GlobalsModRef ) - define_pass( InstCount ) - define_pass( InstructionNamer ) - define_pass( LazyValueInfo ) - define_pass( LCSSA ) --define_pass( LiveValues ) -+//define_pass( LiveValues ) - define_pass( LoopDependenceAnalysis ) - define_pass( LoopExtractor ) - define_pass( LoopSimplify ) -@@ -519,7 +526,7 @@ - define_pass( NoProfileInfo ) - define_pass( OptimalEdgeProfiler ) - define_pass( PartialInlining ) --define_pass( PartialSpecialization ) -+//define_pass( PartialSpecialization ) - define_pass( PostDomOnlyPrinter ) - define_pass( PostDomOnlyViewer ) - define_pass( PostDomPrinter ) -@@ -528,7 +535,7 @@ - define_pass( ProfileLoader ) - define_pass( ProfileVerifier ) - define_pass( ScalarEvolutionAliasAnalysis ) --define_pass( SimplifyHalfPowrLibCalls ) -+//define_pass( SimplifyHalfPowrLibCalls ) - define_pass( SingleLoopExtractor ) - define_pass( StripNonDebugSymbols ) - define_pass( StructRetPromotion ) -Index: passes.py -=================================================================== ---- passes.py (revision 105) -+++ passes.py (working copy) -@@ -68,7 +68,7 @@ - PASS_EDGE_PROFILER = 25 - PASS_FUNCTION_ATTRS = 26 - PASS_FUNCTION_INLINING = 27 --PASS_GEP_SPLITTER = 28 -+#PASS_GEP_SPLITTER = 28 - PASS_GLOBAL_DCE = 29 - PASS_GLOBAL_OPTIMIZER = 30 - PASS_GLOBALS_MOD_REF = 31 -@@ -83,11 +83,11 @@ - PASS_LAZY_VALUE_INFO = 40 - PASS_LCSSA = 41 - PASS_LICM = 42 --PASS_LIVE_VALUES = 43 -+#PASS_LIVE_VALUES = 43 - PASS_LOOP_DELETION = 44 - PASS_LOOP_DEPENDENCE_ANALYSIS = 45 - PASS_LOOP_EXTRACTOR = 46 --PASS_LOOP_INDEX_SPLIT = 47 -+#PASS_LOOP_INDEX_SPLIT = 47 - PASS_LOOP_ROTATE = 48 - PASS_LOOP_SIMPLIFY = 49 - PASS_LOOP_STRENGTH_REDUCE = 50 -@@ -102,11 +102,11 @@ - PASS_NO_PROFILE_INFO = 59 - PASS_OPTIMAL_EDGE_PROFILER = 60 - PASS_PARTIAL_INLINING = 61 --PASS_PARTIAL_SPECIALIZATION = 62 --PASS_POST_DOM_ONLY_PRINTER = 63 --PASS_POST_DOM_ONLY_VIEWER = 64 --PASS_POST_DOM_PRINTER = 65 --PASS_POST_DOM_VIEWER = 66 -+#PASS_PARTIAL_SPECIALIZATION = 62 -+#PASS_POST_DOM_ONLY_PRINTER = 63 -+#PASS_POST_DOM_ONLY_VIEWER = 64 -+#PASS_POST_DOM_PRINTER = 65 -+#PASS_POST_DOM_VIEWER = 66 - PASS_PROFILE_ESTIMATOR = 67 - PASS_PROFILE_LOADER = 68 - PASS_PROFILE_VERIFIER = 69 -@@ -116,7 +116,7 @@ - PASS_SCALAR_EVOLUTION_ALIAS_ANALYSIS = 73 - PASS_SCALAR_REPL_AGGREGATES = 74 - PASS_SCCP = 76 --PASS_SIMPLIFY_HALF_POWR_LIB_CALLS = 77 -+#PASS_SIMPLIFY_HALF_POWR_LIB_CALLS = 77 - PASS_SIMPLIFY_LIB_CALLS = 78 - PASS_SINGLE_LOOP_EXTRACTOR = 79 - PASS_STRIP_DEAD_PROTOTYPES = 82 -@@ -161,7 +161,7 @@ - PASS_EDGE_PROFILER : _core.LLVMAddEdgeProfilerPass, - PASS_FUNCTION_ATTRS : _core.LLVMAddFunctionAttrsPass, - PASS_FUNCTION_INLINING : _core.LLVMAddFunctionInliningPass, -- PASS_GEP_SPLITTER : _core.LLVMAddGEPSplitterPass, -+ #PASS_GEP_SPLITTER : _core.LLVMAddGEPSplitterPass, - PASS_GLOBAL_DCE : _core.LLVMAddGlobalDCEPass, - PASS_GLOBAL_OPTIMIZER : _core.LLVMAddGlobalOptimizerPass, - PASS_GLOBALS_MOD_REF : _core.LLVMAddGlobalsModRefPass, -@@ -176,11 +176,11 @@ - PASS_LAZY_VALUE_INFO : _core.LLVMAddLazyValueInfoPass, - PASS_LCSSA : _core.LLVMAddLCSSAPass, - PASS_LICM : _core.LLVMAddLICMPass, -- PASS_LIVE_VALUES : _core.LLVMAddLiveValuesPass, -+ #PASS_LIVE_VALUES : _core.LLVMAddLiveValuesPass, - PASS_LOOP_DELETION : _core.LLVMAddLoopDeletionPass, - PASS_LOOP_DEPENDENCE_ANALYSIS : _core.LLVMAddLoopDependenceAnalysisPass, - PASS_LOOP_EXTRACTOR : _core.LLVMAddLoopExtractorPass, -- PASS_LOOP_INDEX_SPLIT : _core.LLVMAddLoopIndexSplitPass, -+ #PASS_LOOP_INDEX_SPLIT : _core.LLVMAddLoopIndexSplitPass, - PASS_LOOP_ROTATE : _core.LLVMAddLoopRotatePass, - PASS_LOOP_SIMPLIFY : _core.LLVMAddLoopSimplifyPass, - PASS_LOOP_STRENGTH_REDUCE : _core.LLVMAddLoopStrengthReducePass, -@@ -195,11 +195,11 @@ - PASS_NO_PROFILE_INFO : _core.LLVMAddNoProfileInfoPass, - PASS_OPTIMAL_EDGE_PROFILER : _core.LLVMAddOptimalEdgeProfilerPass, - PASS_PARTIAL_INLINING : _core.LLVMAddPartialInliningPass, -- PASS_PARTIAL_SPECIALIZATION : _core.LLVMAddPartialSpecializationPass, -- PASS_POST_DOM_ONLY_PRINTER : _core.LLVMAddPostDomOnlyPrinterPass, -- PASS_POST_DOM_ONLY_VIEWER : _core.LLVMAddPostDomOnlyViewerPass, -- PASS_POST_DOM_PRINTER : _core.LLVMAddPostDomPrinterPass, -- PASS_POST_DOM_VIEWER : _core.LLVMAddPostDomViewerPass, -+ #PASS_PARTIAL_SPECIALIZATION : _core.LLVMAddPartialSpecializationPass, -+ #PASS_POST_DOM_ONLY_PRINTER : _core.LLVMAddPostDomOnlyPrinterPass, -+ #PASS_POST_DOM_ONLY_VIEWER : _core.LLVMAddPostDomOnlyViewerPass, -+ #PASS_POST_DOM_PRINTER : _core.LLVMAddPostDomPrinterPass, -+ #PASS_POST_DOM_VIEWER : _core.LLVMAddPostDomViewerPass, - PASS_PROFILE_ESTIMATOR : _core.LLVMAddProfileEstimatorPass, - PASS_PROFILE_LOADER : _core.LLVMAddProfileLoaderPass, - PASS_PROFILE_VERIFIER : _core.LLVMAddProfileVerifierPass, -@@ -209,7 +209,7 @@ - PASS_SCALAR_EVOLUTION_ALIAS_ANALYSIS : _core.LLVMAddScalarEvolutionAliasAnalysisPass, - PASS_SCALAR_REPL_AGGREGATES : _core.LLVMAddScalarReplAggregatesPass, - PASS_SCCP : _core.LLVMAddSCCPPass, -- PASS_SIMPLIFY_HALF_POWR_LIB_CALLS : _core.LLVMAddSimplifyHalfPowrLibCallsPass, -+ #PASS_SIMPLIFY_HALF_POWR_LIB_CALLS : _core.LLVMAddSimplifyHalfPowrLibCallsPass, - PASS_SIMPLIFY_LIB_CALLS : _core.LLVMAddSimplifyLibCallsPass, - PASS_SINGLE_LOOP_EXTRACTOR : _core.LLVMAddSingleLoopExtractorPass, - PASS_STRIP_DEAD_PROTOTYPES : _core.LLVMAddStripDeadPrototypesPass, -Index: _intrinsic_ids.py -=================================================================== ---- _intrinsic_ids.py (revision 105) -+++ _intrinsic_ids.py (working copy) -@@ -49,854 +49,879 @@ - INTR_ARM_NEON_VCNT = 14 - INTR_ARM_NEON_VCVTFP2FXS = 15 - INTR_ARM_NEON_VCVTFP2FXU = 16 --INTR_ARM_NEON_VCVTFXS2FP = 17 --INTR_ARM_NEON_VCVTFXU2FP = 18 --INTR_ARM_NEON_VHADDS = 19 --INTR_ARM_NEON_VHADDU = 20 --INTR_ARM_NEON_VHSUBS = 21 --INTR_ARM_NEON_VHSUBU = 22 --INTR_ARM_NEON_VLD1 = 23 --INTR_ARM_NEON_VLD2 = 24 --INTR_ARM_NEON_VLD2LANE = 25 --INTR_ARM_NEON_VLD3 = 26 --INTR_ARM_NEON_VLD3LANE = 27 --INTR_ARM_NEON_VLD4 = 28 --INTR_ARM_NEON_VLD4LANE = 29 --INTR_ARM_NEON_VMAXS = 30 --INTR_ARM_NEON_VMAXU = 31 --INTR_ARM_NEON_VMINS = 32 --INTR_ARM_NEON_VMINU = 33 --INTR_ARM_NEON_VMULLP = 34 --INTR_ARM_NEON_VMULP = 35 --INTR_ARM_NEON_VPADALS = 36 --INTR_ARM_NEON_VPADALU = 37 --INTR_ARM_NEON_VPADD = 38 --INTR_ARM_NEON_VPADDLS = 39 --INTR_ARM_NEON_VPADDLU = 40 --INTR_ARM_NEON_VPMAXS = 41 --INTR_ARM_NEON_VPMAXU = 42 --INTR_ARM_NEON_VPMINS = 43 --INTR_ARM_NEON_VPMINU = 44 --INTR_ARM_NEON_VQABS = 45 --INTR_ARM_NEON_VQADDS = 46 --INTR_ARM_NEON_VQADDU = 47 --INTR_ARM_NEON_VQDMLAL = 48 --INTR_ARM_NEON_VQDMLSL = 49 --INTR_ARM_NEON_VQDMULH = 50 --INTR_ARM_NEON_VQDMULL = 51 --INTR_ARM_NEON_VQMOVNS = 52 --INTR_ARM_NEON_VQMOVNSU = 53 --INTR_ARM_NEON_VQMOVNU = 54 --INTR_ARM_NEON_VQNEG = 55 --INTR_ARM_NEON_VQRDMULH = 56 --INTR_ARM_NEON_VQRSHIFTNS = 57 --INTR_ARM_NEON_VQRSHIFTNSU = 58 --INTR_ARM_NEON_VQRSHIFTNU = 59 --INTR_ARM_NEON_VQRSHIFTS = 60 --INTR_ARM_NEON_VQRSHIFTU = 61 --INTR_ARM_NEON_VQSHIFTNS = 62 --INTR_ARM_NEON_VQSHIFTNSU = 63 --INTR_ARM_NEON_VQSHIFTNU = 64 --INTR_ARM_NEON_VQSHIFTS = 65 --INTR_ARM_NEON_VQSHIFTSU = 66 --INTR_ARM_NEON_VQSHIFTU = 67 --INTR_ARM_NEON_VQSUBS = 68 --INTR_ARM_NEON_VQSUBU = 69 --INTR_ARM_NEON_VRADDHN = 70 --INTR_ARM_NEON_VRECPE = 71 --INTR_ARM_NEON_VRECPS = 72 --INTR_ARM_NEON_VRHADDS = 73 --INTR_ARM_NEON_VRHADDU = 74 --INTR_ARM_NEON_VRSHIFTN = 75 --INTR_ARM_NEON_VRSHIFTS = 76 --INTR_ARM_NEON_VRSHIFTU = 77 --INTR_ARM_NEON_VRSQRTE = 78 --INTR_ARM_NEON_VRSQRTS = 79 --INTR_ARM_NEON_VRSUBHN = 80 --INTR_ARM_NEON_VSHIFTINS = 81 --INTR_ARM_NEON_VSHIFTLS = 82 --INTR_ARM_NEON_VSHIFTLU = 83 --INTR_ARM_NEON_VSHIFTN = 84 --INTR_ARM_NEON_VSHIFTS = 85 --INTR_ARM_NEON_VSHIFTU = 86 --INTR_ARM_NEON_VST1 = 87 --INTR_ARM_NEON_VST2 = 88 --INTR_ARM_NEON_VST2LANE = 89 --INTR_ARM_NEON_VST3 = 90 --INTR_ARM_NEON_VST3LANE = 91 --INTR_ARM_NEON_VST4 = 92 --INTR_ARM_NEON_VST4LANE = 93 --INTR_ARM_NEON_VSUBHN = 94 --INTR_ARM_NEON_VTBL1 = 95 --INTR_ARM_NEON_VTBL2 = 96 --INTR_ARM_NEON_VTBL3 = 97 --INTR_ARM_NEON_VTBL4 = 98 --INTR_ARM_NEON_VTBX1 = 99 --INTR_ARM_NEON_VTBX2 = 100 --INTR_ARM_NEON_VTBX3 = 101 --INTR_ARM_NEON_VTBX4 = 102 --INTR_ARM_QADD = 103 --INTR_ARM_QSUB = 104 --INTR_ARM_SET_FPSCR = 105 --INTR_ARM_SSAT = 106 --INTR_ARM_THREAD_POINTER = 107 --INTR_ARM_USAT = 108 --INTR_ARM_VCVTR = 109 --INTR_ARM_VCVTRU = 110 --INTR_ATOMIC_CMP_SWAP = 111 --INTR_ATOMIC_LOAD_ADD = 112 --INTR_ATOMIC_LOAD_AND = 113 --INTR_ATOMIC_LOAD_MAX = 114 --INTR_ATOMIC_LOAD_MIN = 115 --INTR_ATOMIC_LOAD_NAND = 116 --INTR_ATOMIC_LOAD_OR = 117 --INTR_ATOMIC_LOAD_SUB = 118 --INTR_ATOMIC_LOAD_UMAX = 119 --INTR_ATOMIC_LOAD_UMIN = 120 --INTR_ATOMIC_LOAD_XOR = 121 --INTR_ATOMIC_SWAP = 122 --INTR_BSWAP = 123 --INTR_CONVERT_FROM_FP16 = 124 --INTR_CONVERT_TO_FP16 = 125 --INTR_CONVERTFF = 126 --INTR_CONVERTFSI = 127 --INTR_CONVERTFUI = 128 --INTR_CONVERTSIF = 129 --INTR_CONVERTSS = 130 --INTR_CONVERTSU = 131 --INTR_CONVERTUIF = 132 --INTR_CONVERTUS = 133 --INTR_CONVERTUU = 134 --INTR_COS = 135 --INTR_CTLZ = 136 --INTR_CTPOP = 137 --INTR_CTTZ = 138 --INTR_DBG_DECLARE = 139 --INTR_DBG_VALUE = 140 --INTR_EH_DWARF_CFA = 141 --INTR_EH_EXCEPTION = 142 --INTR_EH_RETURN_I32 = 143 --INTR_EH_RETURN_I64 = 144 --INTR_EH_SELECTOR = 145 --INTR_EH_SJLJ_CALLSITE = 146 --INTR_EH_SJLJ_LONGJMP = 147 --INTR_EH_SJLJ_LSDA = 148 --INTR_EH_SJLJ_SETJMP = 149 --INTR_EH_TYPEID_FOR = 150 --INTR_EH_UNWIND_INIT = 151 --INTR_EXP = 152 --INTR_EXP2 = 153 --INTR_FLT_ROUNDS = 154 --INTR_FRAMEADDRESS = 155 --INTR_GCREAD = 156 --INTR_GCROOT = 157 --INTR_GCWRITE = 158 --INTR_INIT_TRAMPOLINE = 159 --INTR_INVARIANT_END = 160 --INTR_INVARIANT_START = 161 --INTR_LIFETIME_END = 162 --INTR_LIFETIME_START = 163 --INTR_LOG = 164 --INTR_LOG10 = 165 --INTR_LOG2 = 166 --INTR_LONGJMP = 167 --INTR_MEMCPY = 168 --INTR_MEMMOVE = 169 --INTR_MEMORY_BARRIER = 170 --INTR_MEMSET = 171 --INTR_OBJECTSIZE = 172 --INTR_PCMARKER = 173 --INTR_POW = 174 --INTR_POWI = 175 --INTR_PPC_ALTIVEC_DSS = 176 --INTR_PPC_ALTIVEC_DSSALL = 177 --INTR_PPC_ALTIVEC_DST = 178 --INTR_PPC_ALTIVEC_DSTST = 179 --INTR_PPC_ALTIVEC_DSTSTT = 180 --INTR_PPC_ALTIVEC_DSTT = 181 --INTR_PPC_ALTIVEC_LVEBX = 182 --INTR_PPC_ALTIVEC_LVEHX = 183 --INTR_PPC_ALTIVEC_LVEWX = 184 --INTR_PPC_ALTIVEC_LVSL = 185 --INTR_PPC_ALTIVEC_LVSR = 186 --INTR_PPC_ALTIVEC_LVX = 187 --INTR_PPC_ALTIVEC_LVXL = 188 --INTR_PPC_ALTIVEC_MFVSCR = 189 --INTR_PPC_ALTIVEC_MTVSCR = 190 --INTR_PPC_ALTIVEC_STVEBX = 191 --INTR_PPC_ALTIVEC_STVEHX = 192 --INTR_PPC_ALTIVEC_STVEWX = 193 --INTR_PPC_ALTIVEC_STVX = 194 --INTR_PPC_ALTIVEC_STVXL = 195 --INTR_PPC_ALTIVEC_VADDCUW = 196 --INTR_PPC_ALTIVEC_VADDSBS = 197 --INTR_PPC_ALTIVEC_VADDSHS = 198 --INTR_PPC_ALTIVEC_VADDSWS = 199 --INTR_PPC_ALTIVEC_VADDUBS = 200 --INTR_PPC_ALTIVEC_VADDUHS = 201 --INTR_PPC_ALTIVEC_VADDUWS = 202 --INTR_PPC_ALTIVEC_VAVGSB = 203 --INTR_PPC_ALTIVEC_VAVGSH = 204 --INTR_PPC_ALTIVEC_VAVGSW = 205 --INTR_PPC_ALTIVEC_VAVGUB = 206 --INTR_PPC_ALTIVEC_VAVGUH = 207 --INTR_PPC_ALTIVEC_VAVGUW = 208 --INTR_PPC_ALTIVEC_VCFSX = 209 --INTR_PPC_ALTIVEC_VCFUX = 210 --INTR_PPC_ALTIVEC_VCMPBFP = 211 --INTR_PPC_ALTIVEC_VCMPBFP_P = 212 --INTR_PPC_ALTIVEC_VCMPEQFP = 213 --INTR_PPC_ALTIVEC_VCMPEQFP_P = 214 --INTR_PPC_ALTIVEC_VCMPEQUB = 215 --INTR_PPC_ALTIVEC_VCMPEQUB_P = 216 --INTR_PPC_ALTIVEC_VCMPEQUH = 217 --INTR_PPC_ALTIVEC_VCMPEQUH_P = 218 --INTR_PPC_ALTIVEC_VCMPEQUW = 219 --INTR_PPC_ALTIVEC_VCMPEQUW_P = 220 --INTR_PPC_ALTIVEC_VCMPGEFP = 221 --INTR_PPC_ALTIVEC_VCMPGEFP_P = 222 --INTR_PPC_ALTIVEC_VCMPGTFP = 223 --INTR_PPC_ALTIVEC_VCMPGTFP_P = 224 --INTR_PPC_ALTIVEC_VCMPGTSB = 225 --INTR_PPC_ALTIVEC_VCMPGTSB_P = 226 --INTR_PPC_ALTIVEC_VCMPGTSH = 227 --INTR_PPC_ALTIVEC_VCMPGTSH_P = 228 --INTR_PPC_ALTIVEC_VCMPGTSW = 229 --INTR_PPC_ALTIVEC_VCMPGTSW_P = 230 --INTR_PPC_ALTIVEC_VCMPGTUB = 231 --INTR_PPC_ALTIVEC_VCMPGTUB_P = 232 --INTR_PPC_ALTIVEC_VCMPGTUH = 233 --INTR_PPC_ALTIVEC_VCMPGTUH_P = 234 --INTR_PPC_ALTIVEC_VCMPGTUW = 235 --INTR_PPC_ALTIVEC_VCMPGTUW_P = 236 --INTR_PPC_ALTIVEC_VCTSXS = 237 --INTR_PPC_ALTIVEC_VCTUXS = 238 --INTR_PPC_ALTIVEC_VEXPTEFP = 239 --INTR_PPC_ALTIVEC_VLOGEFP = 240 --INTR_PPC_ALTIVEC_VMADDFP = 241 --INTR_PPC_ALTIVEC_VMAXFP = 242 --INTR_PPC_ALTIVEC_VMAXSB = 243 --INTR_PPC_ALTIVEC_VMAXSH = 244 --INTR_PPC_ALTIVEC_VMAXSW = 245 --INTR_PPC_ALTIVEC_VMAXUB = 246 --INTR_PPC_ALTIVEC_VMAXUH = 247 --INTR_PPC_ALTIVEC_VMAXUW = 248 --INTR_PPC_ALTIVEC_VMHADDSHS = 249 --INTR_PPC_ALTIVEC_VMHRADDSHS = 250 --INTR_PPC_ALTIVEC_VMINFP = 251 --INTR_PPC_ALTIVEC_VMINSB = 252 --INTR_PPC_ALTIVEC_VMINSH = 253 --INTR_PPC_ALTIVEC_VMINSW = 254 --INTR_PPC_ALTIVEC_VMINUB = 255 --INTR_PPC_ALTIVEC_VMINUH = 256 --INTR_PPC_ALTIVEC_VMINUW = 257 --INTR_PPC_ALTIVEC_VMLADDUHM = 258 --INTR_PPC_ALTIVEC_VMSUMMBM = 259 --INTR_PPC_ALTIVEC_VMSUMSHM = 260 --INTR_PPC_ALTIVEC_VMSUMSHS = 261 --INTR_PPC_ALTIVEC_VMSUMUBM = 262 --INTR_PPC_ALTIVEC_VMSUMUHM = 263 --INTR_PPC_ALTIVEC_VMSUMUHS = 264 --INTR_PPC_ALTIVEC_VMULESB = 265 --INTR_PPC_ALTIVEC_VMULESH = 266 --INTR_PPC_ALTIVEC_VMULEUB = 267 --INTR_PPC_ALTIVEC_VMULEUH = 268 --INTR_PPC_ALTIVEC_VMULOSB = 269 --INTR_PPC_ALTIVEC_VMULOSH = 270 --INTR_PPC_ALTIVEC_VMULOUB = 271 --INTR_PPC_ALTIVEC_VMULOUH = 272 --INTR_PPC_ALTIVEC_VNMSUBFP = 273 --INTR_PPC_ALTIVEC_VPERM = 274 --INTR_PPC_ALTIVEC_VPKPX = 275 --INTR_PPC_ALTIVEC_VPKSHSS = 276 --INTR_PPC_ALTIVEC_VPKSHUS = 277 --INTR_PPC_ALTIVEC_VPKSWSS = 278 --INTR_PPC_ALTIVEC_VPKSWUS = 279 --INTR_PPC_ALTIVEC_VPKUHUS = 280 --INTR_PPC_ALTIVEC_VPKUWUS = 281 --INTR_PPC_ALTIVEC_VREFP = 282 --INTR_PPC_ALTIVEC_VRFIM = 283 --INTR_PPC_ALTIVEC_VRFIN = 284 --INTR_PPC_ALTIVEC_VRFIP = 285 --INTR_PPC_ALTIVEC_VRFIZ = 286 --INTR_PPC_ALTIVEC_VRLB = 287 --INTR_PPC_ALTIVEC_VRLH = 288 --INTR_PPC_ALTIVEC_VRLW = 289 --INTR_PPC_ALTIVEC_VRSQRTEFP = 290 --INTR_PPC_ALTIVEC_VSEL = 291 --INTR_PPC_ALTIVEC_VSL = 292 --INTR_PPC_ALTIVEC_VSLB = 293 --INTR_PPC_ALTIVEC_VSLH = 294 --INTR_PPC_ALTIVEC_VSLO = 295 --INTR_PPC_ALTIVEC_VSLW = 296 --INTR_PPC_ALTIVEC_VSR = 297 --INTR_PPC_ALTIVEC_VSRAB = 298 --INTR_PPC_ALTIVEC_VSRAH = 299 --INTR_PPC_ALTIVEC_VSRAW = 300 --INTR_PPC_ALTIVEC_VSRB = 301 --INTR_PPC_ALTIVEC_VSRH = 302 --INTR_PPC_ALTIVEC_VSRO = 303 --INTR_PPC_ALTIVEC_VSRW = 304 --INTR_PPC_ALTIVEC_VSUBCUW = 305 --INTR_PPC_ALTIVEC_VSUBSBS = 306 --INTR_PPC_ALTIVEC_VSUBSHS = 307 --INTR_PPC_ALTIVEC_VSUBSWS = 308 --INTR_PPC_ALTIVEC_VSUBUBS = 309 --INTR_PPC_ALTIVEC_VSUBUHS = 310 --INTR_PPC_ALTIVEC_VSUBUWS = 311 --INTR_PPC_ALTIVEC_VSUM2SWS = 312 --INTR_PPC_ALTIVEC_VSUM4SBS = 313 --INTR_PPC_ALTIVEC_VSUM4SHS = 314 --INTR_PPC_ALTIVEC_VSUM4UBS = 315 --INTR_PPC_ALTIVEC_VSUMSWS = 316 --INTR_PPC_ALTIVEC_VUPKHPX = 317 --INTR_PPC_ALTIVEC_VUPKHSB = 318 --INTR_PPC_ALTIVEC_VUPKHSH = 319 --INTR_PPC_ALTIVEC_VUPKLPX = 320 --INTR_PPC_ALTIVEC_VUPKLSB = 321 --INTR_PPC_ALTIVEC_VUPKLSH = 322 --INTR_PPC_DCBA = 323 --INTR_PPC_DCBF = 324 --INTR_PPC_DCBI = 325 --INTR_PPC_DCBST = 326 --INTR_PPC_DCBT = 327 --INTR_PPC_DCBTST = 328 --INTR_PPC_DCBZ = 329 --INTR_PPC_DCBZL = 330 --INTR_PPC_SYNC = 331 --INTR_PREFETCH = 332 --INTR_PTR_ANNOTATION = 333 --INTR_READCYCLECOUNTER = 334 --INTR_RETURNADDRESS = 335 --INTR_SADD_WITH_OVERFLOW = 336 --INTR_SETJMP = 337 --INTR_SIGLONGJMP = 338 --INTR_SIGSETJMP = 339 --INTR_SIN = 340 --INTR_SMUL_WITH_OVERFLOW = 341 --INTR_SPU_SI_A = 342 --INTR_SPU_SI_ADDX = 343 --INTR_SPU_SI_AH = 344 --INTR_SPU_SI_AHI = 345 --INTR_SPU_SI_AI = 346 --INTR_SPU_SI_AND = 347 --INTR_SPU_SI_ANDBI = 348 --INTR_SPU_SI_ANDC = 349 --INTR_SPU_SI_ANDHI = 350 --INTR_SPU_SI_ANDI = 351 --INTR_SPU_SI_BG = 352 --INTR_SPU_SI_BGX = 353 --INTR_SPU_SI_CEQ = 354 --INTR_SPU_SI_CEQB = 355 --INTR_SPU_SI_CEQBI = 356 --INTR_SPU_SI_CEQH = 357 --INTR_SPU_SI_CEQHI = 358 --INTR_SPU_SI_CEQI = 359 --INTR_SPU_SI_CG = 360 --INTR_SPU_SI_CGT = 361 --INTR_SPU_SI_CGTB = 362 --INTR_SPU_SI_CGTBI = 363 --INTR_SPU_SI_CGTH = 364 --INTR_SPU_SI_CGTHI = 365 --INTR_SPU_SI_CGTI = 366 --INTR_SPU_SI_CGX = 367 --INTR_SPU_SI_CLGT = 368 --INTR_SPU_SI_CLGTB = 369 --INTR_SPU_SI_CLGTBI = 370 --INTR_SPU_SI_CLGTH = 371 --INTR_SPU_SI_CLGTHI = 372 --INTR_SPU_SI_CLGTI = 373 --INTR_SPU_SI_DFA = 374 --INTR_SPU_SI_DFM = 375 --INTR_SPU_SI_DFMA = 376 --INTR_SPU_SI_DFMS = 377 --INTR_SPU_SI_DFNMA = 378 --INTR_SPU_SI_DFNMS = 379 --INTR_SPU_SI_DFS = 380 --INTR_SPU_SI_FA = 381 --INTR_SPU_SI_FCEQ = 382 --INTR_SPU_SI_FCGT = 383 --INTR_SPU_SI_FCMEQ = 384 --INTR_SPU_SI_FCMGT = 385 --INTR_SPU_SI_FM = 386 --INTR_SPU_SI_FMA = 387 --INTR_SPU_SI_FMS = 388 --INTR_SPU_SI_FNMS = 389 --INTR_SPU_SI_FS = 390 --INTR_SPU_SI_FSMBI = 391 --INTR_SPU_SI_MPY = 392 --INTR_SPU_SI_MPYA = 393 --INTR_SPU_SI_MPYH = 394 --INTR_SPU_SI_MPYHH = 395 --INTR_SPU_SI_MPYHHA = 396 --INTR_SPU_SI_MPYHHAU = 397 --INTR_SPU_SI_MPYHHU = 398 --INTR_SPU_SI_MPYI = 399 --INTR_SPU_SI_MPYS = 400 --INTR_SPU_SI_MPYU = 401 --INTR_SPU_SI_MPYUI = 402 --INTR_SPU_SI_NAND = 403 --INTR_SPU_SI_NOR = 404 --INTR_SPU_SI_OR = 405 --INTR_SPU_SI_ORBI = 406 --INTR_SPU_SI_ORC = 407 --INTR_SPU_SI_ORHI = 408 --INTR_SPU_SI_ORI = 409 --INTR_SPU_SI_SF = 410 --INTR_SPU_SI_SFH = 411 --INTR_SPU_SI_SFHI = 412 --INTR_SPU_SI_SFI = 413 --INTR_SPU_SI_SFX = 414 --INTR_SPU_SI_SHLI = 415 --INTR_SPU_SI_SHLQBI = 416 --INTR_SPU_SI_SHLQBII = 417 --INTR_SPU_SI_SHLQBY = 418 --INTR_SPU_SI_SHLQBYI = 419 --INTR_SPU_SI_XOR = 420 --INTR_SPU_SI_XORBI = 421 --INTR_SPU_SI_XORHI = 422 --INTR_SPU_SI_XORI = 423 --INTR_SQRT = 424 --INTR_SSUB_WITH_OVERFLOW = 425 --INTR_STACKPROTECTOR = 426 --INTR_STACKRESTORE = 427 --INTR_STACKSAVE = 428 --INTR_TRAP = 429 --INTR_UADD_WITH_OVERFLOW = 430 --INTR_UMUL_WITH_OVERFLOW = 431 --INTR_USUB_WITH_OVERFLOW = 432 --INTR_VACOPY = 433 --INTR_VAEND = 434 --INTR_VAR_ANNOTATION = 435 --INTR_VASTART = 436 --INTR_X86_AESNI_AESDEC = 437 --INTR_X86_AESNI_AESDECLAST = 438 --INTR_X86_AESNI_AESENC = 439 --INTR_X86_AESNI_AESENCLAST = 440 --INTR_X86_AESNI_AESIMC = 441 --INTR_X86_AESNI_AESKEYGENASSIST = 442 --INTR_X86_AVX_ADDSUB_PD_256 = 443 --INTR_X86_AVX_ADDSUB_PS_256 = 444 --INTR_X86_AVX_BLEND_PD_256 = 445 --INTR_X86_AVX_BLEND_PS_256 = 446 --INTR_X86_AVX_BLENDV_PD_256 = 447 --INTR_X86_AVX_BLENDV_PS_256 = 448 --INTR_X86_AVX_CMP_PD_256 = 449 --INTR_X86_AVX_CMP_PS_256 = 450 --INTR_X86_AVX_CVT_PD2_PS_256 = 451 --INTR_X86_AVX_CVT_PD2DQ_256 = 452 --INTR_X86_AVX_CVT_PS2_PD_256 = 453 --INTR_X86_AVX_CVT_PS2DQ_256 = 454 --INTR_X86_AVX_CVTDQ2_PD_256 = 455 --INTR_X86_AVX_CVTDQ2_PS_256 = 456 --INTR_X86_AVX_CVTT_PD2DQ_256 = 457 --INTR_X86_AVX_CVTT_PS2DQ_256 = 458 --INTR_X86_AVX_DP_PS_256 = 459 --INTR_X86_AVX_HADD_PD_256 = 460 --INTR_X86_AVX_HADD_PS_256 = 461 --INTR_X86_AVX_HSUB_PD_256 = 462 --INTR_X86_AVX_HSUB_PS_256 = 463 --INTR_X86_AVX_LDU_DQ_256 = 464 --INTR_X86_AVX_LOADU_DQ_256 = 465 --INTR_X86_AVX_LOADU_PD_256 = 466 --INTR_X86_AVX_LOADU_PS_256 = 467 --INTR_X86_AVX_MASKLOAD_PD = 468 --INTR_X86_AVX_MASKLOAD_PD_256 = 469 --INTR_X86_AVX_MASKLOAD_PS = 470 --INTR_X86_AVX_MASKLOAD_PS_256 = 471 --INTR_X86_AVX_MASKSTORE_PD = 472 --INTR_X86_AVX_MASKSTORE_PD_256 = 473 --INTR_X86_AVX_MASKSTORE_PS = 474 --INTR_X86_AVX_MASKSTORE_PS_256 = 475 --INTR_X86_AVX_MAX_PD_256 = 476 --INTR_X86_AVX_MAX_PS_256 = 477 --INTR_X86_AVX_MIN_PD_256 = 478 --INTR_X86_AVX_MIN_PS_256 = 479 --INTR_X86_AVX_MOVMSK_PD_256 = 480 --INTR_X86_AVX_MOVMSK_PS_256 = 481 --INTR_X86_AVX_MOVNT_DQ_256 = 482 --INTR_X86_AVX_MOVNT_PD_256 = 483 --INTR_X86_AVX_MOVNT_PS_256 = 484 --INTR_X86_AVX_PTESTC_256 = 485 --INTR_X86_AVX_PTESTNZC_256 = 486 --INTR_X86_AVX_PTESTZ_256 = 487 --INTR_X86_AVX_RCP_PS_256 = 488 --INTR_X86_AVX_ROUND_PD_256 = 489 --INTR_X86_AVX_ROUND_PS_256 = 490 --INTR_X86_AVX_RSQRT_PS_256 = 491 --INTR_X86_AVX_SQRT_PD_256 = 492 --INTR_X86_AVX_SQRT_PS_256 = 493 --INTR_X86_AVX_STOREU_DQ_256 = 494 --INTR_X86_AVX_STOREU_PD_256 = 495 --INTR_X86_AVX_STOREU_PS_256 = 496 --INTR_X86_AVX_VBROADCAST_SD_256 = 497 --INTR_X86_AVX_VBROADCASTF128_PD_256 = 498 --INTR_X86_AVX_VBROADCASTF128_PS_256 = 499 --INTR_X86_AVX_VBROADCASTSS = 500 --INTR_X86_AVX_VBROADCASTSS_256 = 501 --INTR_X86_AVX_VEXTRACTF128_PD_256 = 502 --INTR_X86_AVX_VEXTRACTF128_PS_256 = 503 --INTR_X86_AVX_VEXTRACTF128_SI_256 = 504 --INTR_X86_AVX_VINSERTF128_PD_256 = 505 --INTR_X86_AVX_VINSERTF128_PS_256 = 506 --INTR_X86_AVX_VINSERTF128_SI_256 = 507 --INTR_X86_AVX_VPERM2F128_PD_256 = 508 --INTR_X86_AVX_VPERM2F128_PS_256 = 509 --INTR_X86_AVX_VPERM2F128_SI_256 = 510 --INTR_X86_AVX_VPERMIL_PD = 511 --INTR_X86_AVX_VPERMIL_PD_256 = 512 --INTR_X86_AVX_VPERMIL_PS = 513 --INTR_X86_AVX_VPERMIL_PS_256 = 514 --INTR_X86_AVX_VPERMILVAR_PD = 515 --INTR_X86_AVX_VPERMILVAR_PD_256 = 516 --INTR_X86_AVX_VPERMILVAR_PS = 517 --INTR_X86_AVX_VPERMILVAR_PS_256 = 518 --INTR_X86_AVX_VTESTC_PD = 519 --INTR_X86_AVX_VTESTC_PD_256 = 520 --INTR_X86_AVX_VTESTC_PS = 521 --INTR_X86_AVX_VTESTC_PS_256 = 522 --INTR_X86_AVX_VTESTNZC_PD = 523 --INTR_X86_AVX_VTESTNZC_PD_256 = 524 --INTR_X86_AVX_VTESTNZC_PS = 525 --INTR_X86_AVX_VTESTNZC_PS_256 = 526 --INTR_X86_AVX_VTESTZ_PD = 527 --INTR_X86_AVX_VTESTZ_PD_256 = 528 --INTR_X86_AVX_VTESTZ_PS = 529 --INTR_X86_AVX_VTESTZ_PS_256 = 530 --INTR_X86_AVX_VZEROALL = 531 --INTR_X86_AVX_VZEROUPPER = 532 --INTR_X86_INT = 533 --INTR_X86_MMX_CVTSI32_SI64 = 534 --INTR_X86_MMX_CVTSI64_SI32 = 535 --INTR_X86_MMX_EMMS = 536 --INTR_X86_MMX_FEMMS = 537 --INTR_X86_MMX_MASKMOVQ = 538 --INTR_X86_MMX_MOVNT_DQ = 539 --INTR_X86_MMX_PACKSSDW = 540 --INTR_X86_MMX_PACKSSWB = 541 --INTR_X86_MMX_PACKUSWB = 542 --INTR_X86_MMX_PADD_B = 543 --INTR_X86_MMX_PADD_D = 544 --INTR_X86_MMX_PADD_Q = 545 --INTR_X86_MMX_PADD_W = 546 --INTR_X86_MMX_PADDS_B = 547 --INTR_X86_MMX_PADDS_W = 548 --INTR_X86_MMX_PADDUS_B = 549 --INTR_X86_MMX_PADDUS_W = 550 --INTR_X86_MMX_PAND = 551 --INTR_X86_MMX_PANDN = 552 --INTR_X86_MMX_PAVG_B = 553 --INTR_X86_MMX_PAVG_W = 554 --INTR_X86_MMX_PCMPEQ_B = 555 --INTR_X86_MMX_PCMPEQ_D = 556 --INTR_X86_MMX_PCMPEQ_W = 557 --INTR_X86_MMX_PCMPGT_B = 558 --INTR_X86_MMX_PCMPGT_D = 559 --INTR_X86_MMX_PCMPGT_W = 560 --INTR_X86_MMX_PEXTR_W = 561 --INTR_X86_MMX_PINSR_W = 562 --INTR_X86_MMX_PMADD_WD = 563 --INTR_X86_MMX_PMAXS_W = 564 --INTR_X86_MMX_PMAXU_B = 565 --INTR_X86_MMX_PMINS_W = 566 --INTR_X86_MMX_PMINU_B = 567 --INTR_X86_MMX_PMOVMSKB = 568 --INTR_X86_MMX_PMULH_W = 569 --INTR_X86_MMX_PMULHU_W = 570 --INTR_X86_MMX_PMULL_W = 571 --INTR_X86_MMX_PMULU_DQ = 572 --INTR_X86_MMX_POR = 573 --INTR_X86_MMX_PSAD_BW = 574 --INTR_X86_MMX_PSLL_D = 575 --INTR_X86_MMX_PSLL_Q = 576 --INTR_X86_MMX_PSLL_W = 577 --INTR_X86_MMX_PSLLI_D = 578 --INTR_X86_MMX_PSLLI_Q = 579 --INTR_X86_MMX_PSLLI_W = 580 --INTR_X86_MMX_PSRA_D = 581 --INTR_X86_MMX_PSRA_W = 582 --INTR_X86_MMX_PSRAI_D = 583 --INTR_X86_MMX_PSRAI_W = 584 --INTR_X86_MMX_PSRL_D = 585 --INTR_X86_MMX_PSRL_Q = 586 --INTR_X86_MMX_PSRL_W = 587 --INTR_X86_MMX_PSRLI_D = 588 --INTR_X86_MMX_PSRLI_Q = 589 --INTR_X86_MMX_PSRLI_W = 590 --INTR_X86_MMX_PSUB_B = 591 --INTR_X86_MMX_PSUB_D = 592 --INTR_X86_MMX_PSUB_Q = 593 --INTR_X86_MMX_PSUB_W = 594 --INTR_X86_MMX_PSUBS_B = 595 --INTR_X86_MMX_PSUBS_W = 596 --INTR_X86_MMX_PSUBUS_B = 597 --INTR_X86_MMX_PSUBUS_W = 598 --INTR_X86_MMX_PUNPCKHBW = 599 --INTR_X86_MMX_PUNPCKHDQ = 600 --INTR_X86_MMX_PUNPCKHWD = 601 --INTR_X86_MMX_PUNPCKLBW = 602 --INTR_X86_MMX_PUNPCKLDQ = 603 --INTR_X86_MMX_PUNPCKLWD = 604 --INTR_X86_MMX_PXOR = 605 --INTR_X86_MMX_VEC_EXT_D = 606 --INTR_X86_MMX_VEC_INIT_B = 607 --INTR_X86_MMX_VEC_INIT_D = 608 --INTR_X86_MMX_VEC_INIT_W = 609 --INTR_X86_SSE2_ADD_SD = 610 --INTR_X86_SSE2_CLFLUSH = 611 --INTR_X86_SSE2_CMP_PD = 612 --INTR_X86_SSE2_CMP_SD = 613 --INTR_X86_SSE2_COMIEQ_SD = 614 --INTR_X86_SSE2_COMIGE_SD = 615 --INTR_X86_SSE2_COMIGT_SD = 616 --INTR_X86_SSE2_COMILE_SD = 617 --INTR_X86_SSE2_COMILT_SD = 618 --INTR_X86_SSE2_COMINEQ_SD = 619 --INTR_X86_SSE2_CVTDQ2PD = 620 --INTR_X86_SSE2_CVTDQ2PS = 621 --INTR_X86_SSE2_CVTPD2DQ = 622 --INTR_X86_SSE2_CVTPD2PS = 623 --INTR_X86_SSE2_CVTPS2DQ = 624 --INTR_X86_SSE2_CVTPS2PD = 625 --INTR_X86_SSE2_CVTSD2SI = 626 --INTR_X86_SSE2_CVTSD2SI64 = 627 --INTR_X86_SSE2_CVTSD2SS = 628 --INTR_X86_SSE2_CVTSI2SD = 629 --INTR_X86_SSE2_CVTSI642SD = 630 --INTR_X86_SSE2_CVTSS2SD = 631 --INTR_X86_SSE2_CVTTPD2DQ = 632 --INTR_X86_SSE2_CVTTPS2DQ = 633 --INTR_X86_SSE2_CVTTSD2SI = 634 --INTR_X86_SSE2_CVTTSD2SI64 = 635 --INTR_X86_SSE2_DIV_SD = 636 --INTR_X86_SSE2_LFENCE = 637 --INTR_X86_SSE2_LOADU_DQ = 638 --INTR_X86_SSE2_LOADU_PD = 639 --INTR_X86_SSE2_MASKMOV_DQU = 640 --INTR_X86_SSE2_MAX_PD = 641 --INTR_X86_SSE2_MAX_SD = 642 --INTR_X86_SSE2_MFENCE = 643 --INTR_X86_SSE2_MIN_PD = 644 --INTR_X86_SSE2_MIN_SD = 645 --INTR_X86_SSE2_MOVMSK_PD = 646 --INTR_X86_SSE2_MOVNT_DQ = 647 --INTR_X86_SSE2_MOVNT_I = 648 --INTR_X86_SSE2_MOVNT_PD = 649 --INTR_X86_SSE2_MUL_SD = 650 --INTR_X86_SSE2_PACKSSDW_128 = 651 --INTR_X86_SSE2_PACKSSWB_128 = 652 --INTR_X86_SSE2_PACKUSWB_128 = 653 --INTR_X86_SSE2_PADDS_B = 654 --INTR_X86_SSE2_PADDS_W = 655 --INTR_X86_SSE2_PADDUS_B = 656 --INTR_X86_SSE2_PADDUS_W = 657 --INTR_X86_SSE2_PAVG_B = 658 --INTR_X86_SSE2_PAVG_W = 659 --INTR_X86_SSE2_PCMPEQ_B = 660 --INTR_X86_SSE2_PCMPEQ_D = 661 --INTR_X86_SSE2_PCMPEQ_W = 662 --INTR_X86_SSE2_PCMPGT_B = 663 --INTR_X86_SSE2_PCMPGT_D = 664 --INTR_X86_SSE2_PCMPGT_W = 665 --INTR_X86_SSE2_PMADD_WD = 666 --INTR_X86_SSE2_PMAXS_W = 667 --INTR_X86_SSE2_PMAXU_B = 668 --INTR_X86_SSE2_PMINS_W = 669 --INTR_X86_SSE2_PMINU_B = 670 --INTR_X86_SSE2_PMOVMSKB_128 = 671 --INTR_X86_SSE2_PMULH_W = 672 --INTR_X86_SSE2_PMULHU_W = 673 --INTR_X86_SSE2_PMULU_DQ = 674 --INTR_X86_SSE2_PSAD_BW = 675 --INTR_X86_SSE2_PSLL_D = 676 --INTR_X86_SSE2_PSLL_DQ = 677 --INTR_X86_SSE2_PSLL_DQ_BS = 678 --INTR_X86_SSE2_PSLL_Q = 679 --INTR_X86_SSE2_PSLL_W = 680 --INTR_X86_SSE2_PSLLI_D = 681 --INTR_X86_SSE2_PSLLI_Q = 682 --INTR_X86_SSE2_PSLLI_W = 683 --INTR_X86_SSE2_PSRA_D = 684 --INTR_X86_SSE2_PSRA_W = 685 --INTR_X86_SSE2_PSRAI_D = 686 --INTR_X86_SSE2_PSRAI_W = 687 --INTR_X86_SSE2_PSRL_D = 688 --INTR_X86_SSE2_PSRL_DQ = 689 --INTR_X86_SSE2_PSRL_DQ_BS = 690 --INTR_X86_SSE2_PSRL_Q = 691 --INTR_X86_SSE2_PSRL_W = 692 --INTR_X86_SSE2_PSRLI_D = 693 --INTR_X86_SSE2_PSRLI_Q = 694 --INTR_X86_SSE2_PSRLI_W = 695 --INTR_X86_SSE2_PSUBS_B = 696 --INTR_X86_SSE2_PSUBS_W = 697 --INTR_X86_SSE2_PSUBUS_B = 698 --INTR_X86_SSE2_PSUBUS_W = 699 --INTR_X86_SSE2_SQRT_PD = 700 --INTR_X86_SSE2_SQRT_SD = 701 --INTR_X86_SSE2_STOREL_DQ = 702 --INTR_X86_SSE2_STOREU_DQ = 703 --INTR_X86_SSE2_STOREU_PD = 704 --INTR_X86_SSE2_SUB_SD = 705 --INTR_X86_SSE2_UCOMIEQ_SD = 706 --INTR_X86_SSE2_UCOMIGE_SD = 707 --INTR_X86_SSE2_UCOMIGT_SD = 708 --INTR_X86_SSE2_UCOMILE_SD = 709 --INTR_X86_SSE2_UCOMILT_SD = 710 --INTR_X86_SSE2_UCOMINEQ_SD = 711 --INTR_X86_SSE3_ADDSUB_PD = 712 --INTR_X86_SSE3_ADDSUB_PS = 713 --INTR_X86_SSE3_HADD_PD = 714 --INTR_X86_SSE3_HADD_PS = 715 --INTR_X86_SSE3_HSUB_PD = 716 --INTR_X86_SSE3_HSUB_PS = 717 --INTR_X86_SSE3_LDU_DQ = 718 --INTR_X86_SSE3_MONITOR = 719 --INTR_X86_SSE3_MWAIT = 720 --INTR_X86_SSE41_BLENDPD = 721 --INTR_X86_SSE41_BLENDPS = 722 --INTR_X86_SSE41_BLENDVPD = 723 --INTR_X86_SSE41_BLENDVPS = 724 --INTR_X86_SSE41_DPPD = 725 --INTR_X86_SSE41_DPPS = 726 --INTR_X86_SSE41_EXTRACTPS = 727 --INTR_X86_SSE41_INSERTPS = 728 --INTR_X86_SSE41_MOVNTDQA = 729 --INTR_X86_SSE41_MPSADBW = 730 --INTR_X86_SSE41_PACKUSDW = 731 --INTR_X86_SSE41_PBLENDVB = 732 --INTR_X86_SSE41_PBLENDW = 733 --INTR_X86_SSE41_PCMPEQQ = 734 --INTR_X86_SSE41_PEXTRB = 735 --INTR_X86_SSE41_PEXTRD = 736 --INTR_X86_SSE41_PEXTRQ = 737 --INTR_X86_SSE41_PHMINPOSUW = 738 --INTR_X86_SSE41_PMAXSB = 739 --INTR_X86_SSE41_PMAXSD = 740 --INTR_X86_SSE41_PMAXUD = 741 --INTR_X86_SSE41_PMAXUW = 742 --INTR_X86_SSE41_PMINSB = 743 --INTR_X86_SSE41_PMINSD = 744 --INTR_X86_SSE41_PMINUD = 745 --INTR_X86_SSE41_PMINUW = 746 --INTR_X86_SSE41_PMOVSXBD = 747 --INTR_X86_SSE41_PMOVSXBQ = 748 --INTR_X86_SSE41_PMOVSXBW = 749 --INTR_X86_SSE41_PMOVSXDQ = 750 --INTR_X86_SSE41_PMOVSXWD = 751 --INTR_X86_SSE41_PMOVSXWQ = 752 --INTR_X86_SSE41_PMOVZXBD = 753 --INTR_X86_SSE41_PMOVZXBQ = 754 --INTR_X86_SSE41_PMOVZXBW = 755 --INTR_X86_SSE41_PMOVZXDQ = 756 --INTR_X86_SSE41_PMOVZXWD = 757 --INTR_X86_SSE41_PMOVZXWQ = 758 --INTR_X86_SSE41_PMULDQ = 759 --INTR_X86_SSE41_PTESTC = 760 --INTR_X86_SSE41_PTESTNZC = 761 --INTR_X86_SSE41_PTESTZ = 762 --INTR_X86_SSE41_ROUND_PD = 763 --INTR_X86_SSE41_ROUND_PS = 764 --INTR_X86_SSE41_ROUND_SD = 765 --INTR_X86_SSE41_ROUND_SS = 766 --INTR_X86_SSE42_CRC32_16 = 767 --INTR_X86_SSE42_CRC32_32 = 768 --INTR_X86_SSE42_CRC32_8 = 769 --INTR_X86_SSE42_CRC64_64 = 770 --INTR_X86_SSE42_CRC64_8 = 771 --INTR_X86_SSE42_PCMPESTRI128 = 772 --INTR_X86_SSE42_PCMPESTRIA128 = 773 --INTR_X86_SSE42_PCMPESTRIC128 = 774 --INTR_X86_SSE42_PCMPESTRIO128 = 775 --INTR_X86_SSE42_PCMPESTRIS128 = 776 --INTR_X86_SSE42_PCMPESTRIZ128 = 777 --INTR_X86_SSE42_PCMPESTRM128 = 778 --INTR_X86_SSE42_PCMPGTQ = 779 --INTR_X86_SSE42_PCMPISTRI128 = 780 --INTR_X86_SSE42_PCMPISTRIA128 = 781 --INTR_X86_SSE42_PCMPISTRIC128 = 782 --INTR_X86_SSE42_PCMPISTRIO128 = 783 --INTR_X86_SSE42_PCMPISTRIS128 = 784 --INTR_X86_SSE42_PCMPISTRIZ128 = 785 --INTR_X86_SSE42_PCMPISTRM128 = 786 --INTR_X86_SSE_ADD_SS = 787 --INTR_X86_SSE_CMP_PS = 788 --INTR_X86_SSE_CMP_SS = 789 --INTR_X86_SSE_COMIEQ_SS = 790 --INTR_X86_SSE_COMIGE_SS = 791 --INTR_X86_SSE_COMIGT_SS = 792 --INTR_X86_SSE_COMILE_SS = 793 --INTR_X86_SSE_COMILT_SS = 794 --INTR_X86_SSE_COMINEQ_SS = 795 --INTR_X86_SSE_CVTPD2PI = 796 --INTR_X86_SSE_CVTPI2PD = 797 --INTR_X86_SSE_CVTPI2PS = 798 --INTR_X86_SSE_CVTPS2PI = 799 --INTR_X86_SSE_CVTSI2SS = 800 --INTR_X86_SSE_CVTSI642SS = 801 --INTR_X86_SSE_CVTSS2SI = 802 --INTR_X86_SSE_CVTSS2SI64 = 803 --INTR_X86_SSE_CVTTPD2PI = 804 --INTR_X86_SSE_CVTTPS2PI = 805 --INTR_X86_SSE_CVTTSS2SI = 806 --INTR_X86_SSE_CVTTSS2SI64 = 807 --INTR_X86_SSE_DIV_SS = 808 --INTR_X86_SSE_LDMXCSR = 809 --INTR_X86_SSE_LOADU_PS = 810 --INTR_X86_SSE_MAX_PS = 811 --INTR_X86_SSE_MAX_SS = 812 --INTR_X86_SSE_MIN_PS = 813 --INTR_X86_SSE_MIN_SS = 814 --INTR_X86_SSE_MOVMSK_PS = 815 --INTR_X86_SSE_MOVNT_PS = 816 --INTR_X86_SSE_MUL_SS = 817 --INTR_X86_SSE_RCP_PS = 818 --INTR_X86_SSE_RCP_SS = 819 --INTR_X86_SSE_RSQRT_PS = 820 --INTR_X86_SSE_RSQRT_SS = 821 --INTR_X86_SSE_SFENCE = 822 --INTR_X86_SSE_SQRT_PS = 823 --INTR_X86_SSE_SQRT_SS = 824 --INTR_X86_SSE_STMXCSR = 825 --INTR_X86_SSE_STOREU_PS = 826 --INTR_X86_SSE_SUB_SS = 827 --INTR_X86_SSE_UCOMIEQ_SS = 828 --INTR_X86_SSE_UCOMIGE_SS = 829 --INTR_X86_SSE_UCOMIGT_SS = 830 --INTR_X86_SSE_UCOMILE_SS = 831 --INTR_X86_SSE_UCOMILT_SS = 832 --INTR_X86_SSE_UCOMINEQ_SS = 833 --INTR_X86_SSSE3_PABS_B = 834 --INTR_X86_SSSE3_PABS_B_128 = 835 --INTR_X86_SSSE3_PABS_D = 836 --INTR_X86_SSSE3_PABS_D_128 = 837 --INTR_X86_SSSE3_PABS_W = 838 --INTR_X86_SSSE3_PABS_W_128 = 839 --INTR_X86_SSSE3_PHADD_D = 840 --INTR_X86_SSSE3_PHADD_D_128 = 841 --INTR_X86_SSSE3_PHADD_SW = 842 --INTR_X86_SSSE3_PHADD_SW_128 = 843 --INTR_X86_SSSE3_PHADD_W = 844 --INTR_X86_SSSE3_PHADD_W_128 = 845 --INTR_X86_SSSE3_PHSUB_D = 846 --INTR_X86_SSSE3_PHSUB_D_128 = 847 --INTR_X86_SSSE3_PHSUB_SW = 848 --INTR_X86_SSSE3_PHSUB_SW_128 = 849 --INTR_X86_SSSE3_PHSUB_W = 850 --INTR_X86_SSSE3_PHSUB_W_128 = 851 --INTR_X86_SSSE3_PMADD_UB_SW = 852 --INTR_X86_SSSE3_PMADD_UB_SW_128 = 853 --INTR_X86_SSSE3_PMUL_HR_SW = 854 --INTR_X86_SSSE3_PMUL_HR_SW_128 = 855 --INTR_X86_SSSE3_PSHUF_B = 856 --INTR_X86_SSSE3_PSHUF_B_128 = 857 --INTR_X86_SSSE3_PSHUF_W = 858 --INTR_X86_SSSE3_PSIGN_B = 859 --INTR_X86_SSSE3_PSIGN_B_128 = 860 --INTR_X86_SSSE3_PSIGN_D = 861 --INTR_X86_SSSE3_PSIGN_D_128 = 862 --INTR_X86_SSSE3_PSIGN_W = 863 --INTR_X86_SSSE3_PSIGN_W_128 = 864 --INTR_XCORE_BITREV = 865 --INTR_XCORE_GETID = 866 -- -+INTR_ARM_NEON_VCVTFP2HF = 17 -+INTR_ARM_NEON_VCVTFXS2FP = 18 -+INTR_ARM_NEON_VCVTFXU2FP = 19 -+INTR_ARM_NEON_VCVTHF2FP = 20 -+INTR_ARM_NEON_VHADDS = 21 -+INTR_ARM_NEON_VHADDU = 22 -+INTR_ARM_NEON_VHSUBS = 23 -+INTR_ARM_NEON_VHSUBU = 24 -+INTR_ARM_NEON_VLD1 = 25 -+INTR_ARM_NEON_VLD2 = 26 -+INTR_ARM_NEON_VLD2LANE = 27 -+INTR_ARM_NEON_VLD3 = 28 -+INTR_ARM_NEON_VLD3LANE = 29 -+INTR_ARM_NEON_VLD4 = 30 -+INTR_ARM_NEON_VLD4LANE = 31 -+INTR_ARM_NEON_VMAXS = 32 -+INTR_ARM_NEON_VMAXU = 33 -+INTR_ARM_NEON_VMINS = 34 -+INTR_ARM_NEON_VMINU = 35 -+INTR_ARM_NEON_VMULLP = 36 -+INTR_ARM_NEON_VMULP = 37 -+INTR_ARM_NEON_VPADALS = 38 -+INTR_ARM_NEON_VPADALU = 39 -+INTR_ARM_NEON_VPADD = 40 -+INTR_ARM_NEON_VPADDLS = 41 -+INTR_ARM_NEON_VPADDLU = 42 -+INTR_ARM_NEON_VPMAXS = 43 -+INTR_ARM_NEON_VPMAXU = 44 -+INTR_ARM_NEON_VPMINS = 45 -+INTR_ARM_NEON_VPMINU = 46 -+INTR_ARM_NEON_VQABS = 47 -+INTR_ARM_NEON_VQADDS = 48 -+INTR_ARM_NEON_VQADDU = 49 -+INTR_ARM_NEON_VQDMLAL = 50 -+INTR_ARM_NEON_VQDMLSL = 51 -+INTR_ARM_NEON_VQDMULH = 52 -+INTR_ARM_NEON_VQDMULL = 53 -+INTR_ARM_NEON_VQMOVNS = 54 -+INTR_ARM_NEON_VQMOVNSU = 55 -+INTR_ARM_NEON_VQMOVNU = 56 -+INTR_ARM_NEON_VQNEG = 57 -+INTR_ARM_NEON_VQRDMULH = 58 -+INTR_ARM_NEON_VQRSHIFTNS = 59 -+INTR_ARM_NEON_VQRSHIFTNSU = 60 -+INTR_ARM_NEON_VQRSHIFTNU = 61 -+INTR_ARM_NEON_VQRSHIFTS = 62 -+INTR_ARM_NEON_VQRSHIFTU = 63 -+INTR_ARM_NEON_VQSHIFTNS = 64 -+INTR_ARM_NEON_VQSHIFTNSU = 65 -+INTR_ARM_NEON_VQSHIFTNU = 66 -+INTR_ARM_NEON_VQSHIFTS = 67 -+INTR_ARM_NEON_VQSHIFTSU = 68 -+INTR_ARM_NEON_VQSHIFTU = 69 -+INTR_ARM_NEON_VQSUBS = 70 -+INTR_ARM_NEON_VQSUBU = 71 -+INTR_ARM_NEON_VRADDHN = 72 -+INTR_ARM_NEON_VRECPE = 73 -+INTR_ARM_NEON_VRECPS = 74 -+INTR_ARM_NEON_VRHADDS = 75 -+INTR_ARM_NEON_VRHADDU = 76 -+INTR_ARM_NEON_VRSHIFTN = 77 -+INTR_ARM_NEON_VRSHIFTS = 78 -+INTR_ARM_NEON_VRSHIFTU = 79 -+INTR_ARM_NEON_VRSQRTE = 80 -+INTR_ARM_NEON_VRSQRTS = 81 -+INTR_ARM_NEON_VRSUBHN = 82 -+INTR_ARM_NEON_VSHIFTINS = 83 -+INTR_ARM_NEON_VSHIFTLS = 84 -+INTR_ARM_NEON_VSHIFTLU = 85 -+INTR_ARM_NEON_VSHIFTN = 86 -+INTR_ARM_NEON_VSHIFTS = 87 -+INTR_ARM_NEON_VSHIFTU = 88 -+INTR_ARM_NEON_VST1 = 89 -+INTR_ARM_NEON_VST2 = 90 -+INTR_ARM_NEON_VST2LANE = 91 -+INTR_ARM_NEON_VST3 = 92 -+INTR_ARM_NEON_VST3LANE = 93 -+INTR_ARM_NEON_VST4 = 94 -+INTR_ARM_NEON_VST4LANE = 95 -+INTR_ARM_NEON_VSUBHN = 96 -+INTR_ARM_NEON_VTBL1 = 97 -+INTR_ARM_NEON_VTBL2 = 98 -+INTR_ARM_NEON_VTBL3 = 99 -+INTR_ARM_NEON_VTBL4 = 100 -+INTR_ARM_NEON_VTBX1 = 101 -+INTR_ARM_NEON_VTBX2 = 102 -+INTR_ARM_NEON_VTBX3 = 103 -+INTR_ARM_NEON_VTBX4 = 104 -+INTR_ARM_QADD = 105 -+INTR_ARM_QSUB = 106 -+INTR_ARM_SET_FPSCR = 107 -+INTR_ARM_SSAT = 108 -+INTR_ARM_THREAD_POINTER = 109 -+INTR_ARM_USAT = 110 -+INTR_ARM_VCVTR = 111 -+INTR_ARM_VCVTRU = 112 -+INTR_ATOMIC_CMP_SWAP = 113 -+INTR_ATOMIC_LOAD_ADD = 114 -+INTR_ATOMIC_LOAD_AND = 115 -+INTR_ATOMIC_LOAD_MAX = 116 -+INTR_ATOMIC_LOAD_MIN = 117 -+INTR_ATOMIC_LOAD_NAND = 118 -+INTR_ATOMIC_LOAD_OR = 119 -+INTR_ATOMIC_LOAD_SUB = 120 -+INTR_ATOMIC_LOAD_UMAX = 121 -+INTR_ATOMIC_LOAD_UMIN = 122 -+INTR_ATOMIC_LOAD_XOR = 123 -+INTR_ATOMIC_SWAP = 124 -+INTR_BSWAP = 125 -+INTR_CONVERT_FROM_FP16 = 126 -+INTR_CONVERT_TO_FP16 = 127 -+INTR_CONVERTFF = 128 -+INTR_CONVERTFSI = 129 -+INTR_CONVERTFUI = 130 -+INTR_CONVERTSIF = 131 -+INTR_CONVERTSS = 132 -+INTR_CONVERTSU = 133 -+INTR_CONVERTUIF = 134 -+INTR_CONVERTUS = 135 -+INTR_CONVERTUU = 136 -+INTR_COS = 137 -+INTR_CTLZ = 138 -+INTR_CTPOP = 139 -+INTR_CTTZ = 140 -+INTR_DBG_DECLARE = 141 -+INTR_DBG_VALUE = 142 -+INTR_EH_DWARF_CFA = 143 -+INTR_EH_EXCEPTION = 144 -+INTR_EH_RETURN_I32 = 145 -+INTR_EH_RETURN_I64 = 146 -+INTR_EH_SELECTOR = 147 -+INTR_EH_SJLJ_CALLSITE = 148 -+INTR_EH_SJLJ_DISPATCH_SETUP = 149 -+INTR_EH_SJLJ_LONGJMP = 150 -+INTR_EH_SJLJ_LSDA = 151 -+INTR_EH_SJLJ_SETJMP = 152 -+INTR_EH_TYPEID_FOR = 153 -+INTR_EH_UNWIND_INIT = 154 -+INTR_EXP = 155 -+INTR_EXP2 = 156 -+INTR_FLT_ROUNDS = 157 -+INTR_FRAMEADDRESS = 158 -+INTR_GCREAD = 159 -+INTR_GCROOT = 160 -+INTR_GCWRITE = 161 -+INTR_INIT_TRAMPOLINE = 162 -+INTR_INVARIANT_END = 163 -+INTR_INVARIANT_START = 164 -+INTR_LIFETIME_END = 165 -+INTR_LIFETIME_START = 166 -+INTR_LOG = 167 -+INTR_LOG10 = 168 -+INTR_LOG2 = 169 -+INTR_LONGJMP = 170 -+INTR_MEMCPY = 171 -+INTR_MEMMOVE = 172 -+INTR_MEMORY_BARRIER = 173 -+INTR_MEMSET = 174 -+INTR_OBJECTSIZE = 175 -+INTR_PCMARKER = 176 -+INTR_POW = 177 -+INTR_POWI = 178 -+INTR_PPC_ALTIVEC_DSS = 179 -+INTR_PPC_ALTIVEC_DSSALL = 180 -+INTR_PPC_ALTIVEC_DST = 181 -+INTR_PPC_ALTIVEC_DSTST = 182 -+INTR_PPC_ALTIVEC_DSTSTT = 183 -+INTR_PPC_ALTIVEC_DSTT = 184 -+INTR_PPC_ALTIVEC_LVEBX = 185 -+INTR_PPC_ALTIVEC_LVEHX = 186 -+INTR_PPC_ALTIVEC_LVEWX = 187 -+INTR_PPC_ALTIVEC_LVSL = 188 -+INTR_PPC_ALTIVEC_LVSR = 189 -+INTR_PPC_ALTIVEC_LVX = 190 -+INTR_PPC_ALTIVEC_LVXL = 191 -+INTR_PPC_ALTIVEC_MFVSCR = 192 -+INTR_PPC_ALTIVEC_MTVSCR = 193 -+INTR_PPC_ALTIVEC_STVEBX = 194 -+INTR_PPC_ALTIVEC_STVEHX = 195 -+INTR_PPC_ALTIVEC_STVEWX = 196 -+INTR_PPC_ALTIVEC_STVX = 197 -+INTR_PPC_ALTIVEC_STVXL = 198 -+INTR_PPC_ALTIVEC_VADDCUW = 199 -+INTR_PPC_ALTIVEC_VADDSBS = 200 -+INTR_PPC_ALTIVEC_VADDSHS = 201 -+INTR_PPC_ALTIVEC_VADDSWS = 202 -+INTR_PPC_ALTIVEC_VADDUBS = 203 -+INTR_PPC_ALTIVEC_VADDUHS = 204 -+INTR_PPC_ALTIVEC_VADDUWS = 205 -+INTR_PPC_ALTIVEC_VAVGSB = 206 -+INTR_PPC_ALTIVEC_VAVGSH = 207 -+INTR_PPC_ALTIVEC_VAVGSW = 208 -+INTR_PPC_ALTIVEC_VAVGUB = 209 -+INTR_PPC_ALTIVEC_VAVGUH = 210 -+INTR_PPC_ALTIVEC_VAVGUW = 211 -+INTR_PPC_ALTIVEC_VCFSX = 212 -+INTR_PPC_ALTIVEC_VCFUX = 213 -+INTR_PPC_ALTIVEC_VCMPBFP = 214 -+INTR_PPC_ALTIVEC_VCMPBFP_P = 215 -+INTR_PPC_ALTIVEC_VCMPEQFP = 216 -+INTR_PPC_ALTIVEC_VCMPEQFP_P = 217 -+INTR_PPC_ALTIVEC_VCMPEQUB = 218 -+INTR_PPC_ALTIVEC_VCMPEQUB_P = 219 -+INTR_PPC_ALTIVEC_VCMPEQUH = 220 -+INTR_PPC_ALTIVEC_VCMPEQUH_P = 221 -+INTR_PPC_ALTIVEC_VCMPEQUW = 222 -+INTR_PPC_ALTIVEC_VCMPEQUW_P = 223 -+INTR_PPC_ALTIVEC_VCMPGEFP = 224 -+INTR_PPC_ALTIVEC_VCMPGEFP_P = 225 -+INTR_PPC_ALTIVEC_VCMPGTFP = 226 -+INTR_PPC_ALTIVEC_VCMPGTFP_P = 227 -+INTR_PPC_ALTIVEC_VCMPGTSB = 228 -+INTR_PPC_ALTIVEC_VCMPGTSB_P = 229 -+INTR_PPC_ALTIVEC_VCMPGTSH = 230 -+INTR_PPC_ALTIVEC_VCMPGTSH_P = 231 -+INTR_PPC_ALTIVEC_VCMPGTSW = 232 -+INTR_PPC_ALTIVEC_VCMPGTSW_P = 233 -+INTR_PPC_ALTIVEC_VCMPGTUB = 234 -+INTR_PPC_ALTIVEC_VCMPGTUB_P = 235 -+INTR_PPC_ALTIVEC_VCMPGTUH = 236 -+INTR_PPC_ALTIVEC_VCMPGTUH_P = 237 -+INTR_PPC_ALTIVEC_VCMPGTUW = 238 -+INTR_PPC_ALTIVEC_VCMPGTUW_P = 239 -+INTR_PPC_ALTIVEC_VCTSXS = 240 -+INTR_PPC_ALTIVEC_VCTUXS = 241 -+INTR_PPC_ALTIVEC_VEXPTEFP = 242 -+INTR_PPC_ALTIVEC_VLOGEFP = 243 -+INTR_PPC_ALTIVEC_VMADDFP = 244 -+INTR_PPC_ALTIVEC_VMAXFP = 245 -+INTR_PPC_ALTIVEC_VMAXSB = 246 -+INTR_PPC_ALTIVEC_VMAXSH = 247 -+INTR_PPC_ALTIVEC_VMAXSW = 248 -+INTR_PPC_ALTIVEC_VMAXUB = 249 -+INTR_PPC_ALTIVEC_VMAXUH = 250 -+INTR_PPC_ALTIVEC_VMAXUW = 251 -+INTR_PPC_ALTIVEC_VMHADDSHS = 252 -+INTR_PPC_ALTIVEC_VMHRADDSHS = 253 -+INTR_PPC_ALTIVEC_VMINFP = 254 -+INTR_PPC_ALTIVEC_VMINSB = 255 -+INTR_PPC_ALTIVEC_VMINSH = 256 -+INTR_PPC_ALTIVEC_VMINSW = 257 -+INTR_PPC_ALTIVEC_VMINUB = 258 -+INTR_PPC_ALTIVEC_VMINUH = 259 -+INTR_PPC_ALTIVEC_VMINUW = 260 -+INTR_PPC_ALTIVEC_VMLADDUHM = 261 -+INTR_PPC_ALTIVEC_VMSUMMBM = 262 -+INTR_PPC_ALTIVEC_VMSUMSHM = 263 -+INTR_PPC_ALTIVEC_VMSUMSHS = 264 -+INTR_PPC_ALTIVEC_VMSUMUBM = 265 -+INTR_PPC_ALTIVEC_VMSUMUHM = 266 -+INTR_PPC_ALTIVEC_VMSUMUHS = 267 -+INTR_PPC_ALTIVEC_VMULESB = 268 -+INTR_PPC_ALTIVEC_VMULESH = 269 -+INTR_PPC_ALTIVEC_VMULEUB = 270 -+INTR_PPC_ALTIVEC_VMULEUH = 271 -+INTR_PPC_ALTIVEC_VMULOSB = 272 -+INTR_PPC_ALTIVEC_VMULOSH = 273 -+INTR_PPC_ALTIVEC_VMULOUB = 274 -+INTR_PPC_ALTIVEC_VMULOUH = 275 -+INTR_PPC_ALTIVEC_VNMSUBFP = 276 -+INTR_PPC_ALTIVEC_VPERM = 277 -+INTR_PPC_ALTIVEC_VPKPX = 278 -+INTR_PPC_ALTIVEC_VPKSHSS = 279 -+INTR_PPC_ALTIVEC_VPKSHUS = 280 -+INTR_PPC_ALTIVEC_VPKSWSS = 281 -+INTR_PPC_ALTIVEC_VPKSWUS = 282 -+INTR_PPC_ALTIVEC_VPKUHUS = 283 -+INTR_PPC_ALTIVEC_VPKUWUS = 284 -+INTR_PPC_ALTIVEC_VREFP = 285 -+INTR_PPC_ALTIVEC_VRFIM = 286 -+INTR_PPC_ALTIVEC_VRFIN = 287 -+INTR_PPC_ALTIVEC_VRFIP = 288 -+INTR_PPC_ALTIVEC_VRFIZ = 289 -+INTR_PPC_ALTIVEC_VRLB = 290 -+INTR_PPC_ALTIVEC_VRLH = 291 -+INTR_PPC_ALTIVEC_VRLW = 292 -+INTR_PPC_ALTIVEC_VRSQRTEFP = 293 -+INTR_PPC_ALTIVEC_VSEL = 294 -+INTR_PPC_ALTIVEC_VSL = 295 -+INTR_PPC_ALTIVEC_VSLB = 296 -+INTR_PPC_ALTIVEC_VSLH = 297 -+INTR_PPC_ALTIVEC_VSLO = 298 -+INTR_PPC_ALTIVEC_VSLW = 299 -+INTR_PPC_ALTIVEC_VSR = 300 -+INTR_PPC_ALTIVEC_VSRAB = 301 -+INTR_PPC_ALTIVEC_VSRAH = 302 -+INTR_PPC_ALTIVEC_VSRAW = 303 -+INTR_PPC_ALTIVEC_VSRB = 304 -+INTR_PPC_ALTIVEC_VSRH = 305 -+INTR_PPC_ALTIVEC_VSRO = 306 -+INTR_PPC_ALTIVEC_VSRW = 307 -+INTR_PPC_ALTIVEC_VSUBCUW = 308 -+INTR_PPC_ALTIVEC_VSUBSBS = 309 -+INTR_PPC_ALTIVEC_VSUBSHS = 310 -+INTR_PPC_ALTIVEC_VSUBSWS = 311 -+INTR_PPC_ALTIVEC_VSUBUBS = 312 -+INTR_PPC_ALTIVEC_VSUBUHS = 313 -+INTR_PPC_ALTIVEC_VSUBUWS = 314 -+INTR_PPC_ALTIVEC_VSUM2SWS = 315 -+INTR_PPC_ALTIVEC_VSUM4SBS = 316 -+INTR_PPC_ALTIVEC_VSUM4SHS = 317 -+INTR_PPC_ALTIVEC_VSUM4UBS = 318 -+INTR_PPC_ALTIVEC_VSUMSWS = 319 -+INTR_PPC_ALTIVEC_VUPKHPX = 320 -+INTR_PPC_ALTIVEC_VUPKHSB = 321 -+INTR_PPC_ALTIVEC_VUPKHSH = 322 -+INTR_PPC_ALTIVEC_VUPKLPX = 323 -+INTR_PPC_ALTIVEC_VUPKLSB = 324 -+INTR_PPC_ALTIVEC_VUPKLSH = 325 -+INTR_PPC_DCBA = 326 -+INTR_PPC_DCBF = 327 -+INTR_PPC_DCBI = 328 -+INTR_PPC_DCBST = 329 -+INTR_PPC_DCBT = 330 -+INTR_PPC_DCBTST = 331 -+INTR_PPC_DCBZ = 332 -+INTR_PPC_DCBZL = 333 -+INTR_PPC_SYNC = 334 -+INTR_PREFETCH = 335 -+INTR_PTR_ANNOTATION = 336 -+INTR_PTX_BAR_SYNC = 337 -+INTR_PTX_READ_TID_R64 = 338 -+INTR_PTX_READ_TID_V4I16 = 339 -+INTR_PTX_READ_TID_W = 340 -+INTR_PTX_READ_TID_X = 341 -+INTR_PTX_READ_TID_Y = 342 -+INTR_PTX_READ_TID_Z = 343 -+INTR_READCYCLECOUNTER = 344 -+INTR_RETURNADDRESS = 345 -+INTR_SADD_WITH_OVERFLOW = 346 -+INTR_SETJMP = 347 -+INTR_SIGLONGJMP = 348 -+INTR_SIGSETJMP = 349 -+INTR_SIN = 350 -+INTR_SMUL_WITH_OVERFLOW = 351 -+INTR_SPU_SI_A = 352 -+INTR_SPU_SI_ADDX = 353 -+INTR_SPU_SI_AH = 354 -+INTR_SPU_SI_AHI = 355 -+INTR_SPU_SI_AI = 356 -+INTR_SPU_SI_AND = 357 -+INTR_SPU_SI_ANDBI = 358 -+INTR_SPU_SI_ANDC = 359 -+INTR_SPU_SI_ANDHI = 360 -+INTR_SPU_SI_ANDI = 361 -+INTR_SPU_SI_BG = 362 -+INTR_SPU_SI_BGX = 363 -+INTR_SPU_SI_CEQ = 364 -+INTR_SPU_SI_CEQB = 365 -+INTR_SPU_SI_CEQBI = 366 -+INTR_SPU_SI_CEQH = 367 -+INTR_SPU_SI_CEQHI = 368 -+INTR_SPU_SI_CEQI = 369 -+INTR_SPU_SI_CG = 370 -+INTR_SPU_SI_CGT = 371 -+INTR_SPU_SI_CGTB = 372 -+INTR_SPU_SI_CGTBI = 373 -+INTR_SPU_SI_CGTH = 374 -+INTR_SPU_SI_CGTHI = 375 -+INTR_SPU_SI_CGTI = 376 -+INTR_SPU_SI_CGX = 377 -+INTR_SPU_SI_CLGT = 378 -+INTR_SPU_SI_CLGTB = 379 -+INTR_SPU_SI_CLGTBI = 380 -+INTR_SPU_SI_CLGTH = 381 -+INTR_SPU_SI_CLGTHI = 382 -+INTR_SPU_SI_CLGTI = 383 -+INTR_SPU_SI_DFA = 384 -+INTR_SPU_SI_DFM = 385 -+INTR_SPU_SI_DFMA = 386 -+INTR_SPU_SI_DFMS = 387 -+INTR_SPU_SI_DFNMA = 388 -+INTR_SPU_SI_DFNMS = 389 -+INTR_SPU_SI_DFS = 390 -+INTR_SPU_SI_FA = 391 -+INTR_SPU_SI_FCEQ = 392 -+INTR_SPU_SI_FCGT = 393 -+INTR_SPU_SI_FCMEQ = 394 -+INTR_SPU_SI_FCMGT = 395 -+INTR_SPU_SI_FM = 396 -+INTR_SPU_SI_FMA = 397 -+INTR_SPU_SI_FMS = 398 -+INTR_SPU_SI_FNMS = 399 -+INTR_SPU_SI_FS = 400 -+INTR_SPU_SI_FSMBI = 401 -+INTR_SPU_SI_MPY = 402 -+INTR_SPU_SI_MPYA = 403 -+INTR_SPU_SI_MPYH = 404 -+INTR_SPU_SI_MPYHH = 405 -+INTR_SPU_SI_MPYHHA = 406 -+INTR_SPU_SI_MPYHHAU = 407 -+INTR_SPU_SI_MPYHHU = 408 -+INTR_SPU_SI_MPYI = 409 -+INTR_SPU_SI_MPYS = 410 -+INTR_SPU_SI_MPYU = 411 -+INTR_SPU_SI_MPYUI = 412 -+INTR_SPU_SI_NAND = 413 -+INTR_SPU_SI_NOR = 414 -+INTR_SPU_SI_OR = 415 -+INTR_SPU_SI_ORBI = 416 -+INTR_SPU_SI_ORC = 417 -+INTR_SPU_SI_ORHI = 418 -+INTR_SPU_SI_ORI = 419 -+INTR_SPU_SI_SF = 420 -+INTR_SPU_SI_SFH = 421 -+INTR_SPU_SI_SFHI = 422 -+INTR_SPU_SI_SFI = 423 -+INTR_SPU_SI_SFX = 424 -+INTR_SPU_SI_SHLI = 425 -+INTR_SPU_SI_SHLQBI = 426 -+INTR_SPU_SI_SHLQBII = 427 -+INTR_SPU_SI_SHLQBY = 428 -+INTR_SPU_SI_SHLQBYI = 429 -+INTR_SPU_SI_XOR = 430 -+INTR_SPU_SI_XORBI = 431 -+INTR_SPU_SI_XORHI = 432 -+INTR_SPU_SI_XORI = 433 -+INTR_SQRT = 434 -+INTR_SSUB_WITH_OVERFLOW = 435 -+INTR_STACKPROTECTOR = 436 -+INTR_STACKRESTORE = 437 -+INTR_STACKSAVE = 438 -+INTR_TRAP = 439 -+INTR_UADD_WITH_OVERFLOW = 440 -+INTR_UMUL_WITH_OVERFLOW = 441 -+INTR_USUB_WITH_OVERFLOW = 442 -+INTR_VACOPY = 443 -+INTR_VAEND = 444 -+INTR_VAR_ANNOTATION = 445 -+INTR_VASTART = 446 -+INTR_X86_AESNI_AESDEC = 447 -+INTR_X86_AESNI_AESDECLAST = 448 -+INTR_X86_AESNI_AESENC = 449 -+INTR_X86_AESNI_AESENCLAST = 450 -+INTR_X86_AESNI_AESIMC = 451 -+INTR_X86_AESNI_AESKEYGENASSIST = 452 -+INTR_X86_AVX_ADDSUB_PD_256 = 453 -+INTR_X86_AVX_ADDSUB_PS_256 = 454 -+INTR_X86_AVX_BLEND_PD_256 = 455 -+INTR_X86_AVX_BLEND_PS_256 = 456 -+INTR_X86_AVX_BLENDV_PD_256 = 457 -+INTR_X86_AVX_BLENDV_PS_256 = 458 -+INTR_X86_AVX_CMP_PD_256 = 459 -+INTR_X86_AVX_CMP_PS_256 = 460 -+INTR_X86_AVX_CVT_PD2_PS_256 = 461 -+INTR_X86_AVX_CVT_PD2DQ_256 = 462 -+INTR_X86_AVX_CVT_PS2_PD_256 = 463 -+INTR_X86_AVX_CVT_PS2DQ_256 = 464 -+INTR_X86_AVX_CVTDQ2_PD_256 = 465 -+INTR_X86_AVX_CVTDQ2_PS_256 = 466 -+INTR_X86_AVX_CVTT_PD2DQ_256 = 467 -+INTR_X86_AVX_CVTT_PS2DQ_256 = 468 -+INTR_X86_AVX_DP_PS_256 = 469 -+INTR_X86_AVX_HADD_PD_256 = 470 -+INTR_X86_AVX_HADD_PS_256 = 471 -+INTR_X86_AVX_HSUB_PD_256 = 472 -+INTR_X86_AVX_HSUB_PS_256 = 473 -+INTR_X86_AVX_LDU_DQ_256 = 474 -+INTR_X86_AVX_LOADU_DQ_256 = 475 -+INTR_X86_AVX_LOADU_PD_256 = 476 -+INTR_X86_AVX_LOADU_PS_256 = 477 -+INTR_X86_AVX_MASKLOAD_PD = 478 -+INTR_X86_AVX_MASKLOAD_PD_256 = 479 -+INTR_X86_AVX_MASKLOAD_PS = 480 -+INTR_X86_AVX_MASKLOAD_PS_256 = 481 -+INTR_X86_AVX_MASKSTORE_PD = 482 -+INTR_X86_AVX_MASKSTORE_PD_256 = 483 -+INTR_X86_AVX_MASKSTORE_PS = 484 -+INTR_X86_AVX_MASKSTORE_PS_256 = 485 -+INTR_X86_AVX_MAX_PD_256 = 486 -+INTR_X86_AVX_MAX_PS_256 = 487 -+INTR_X86_AVX_MIN_PD_256 = 488 -+INTR_X86_AVX_MIN_PS_256 = 489 -+INTR_X86_AVX_MOVMSK_PD_256 = 490 -+INTR_X86_AVX_MOVMSK_PS_256 = 491 -+INTR_X86_AVX_MOVNT_DQ_256 = 492 -+INTR_X86_AVX_MOVNT_PD_256 = 493 -+INTR_X86_AVX_MOVNT_PS_256 = 494 -+INTR_X86_AVX_PTESTC_256 = 495 -+INTR_X86_AVX_PTESTNZC_256 = 496 -+INTR_X86_AVX_PTESTZ_256 = 497 -+INTR_X86_AVX_RCP_PS_256 = 498 -+INTR_X86_AVX_ROUND_PD_256 = 499 -+INTR_X86_AVX_ROUND_PS_256 = 500 -+INTR_X86_AVX_RSQRT_PS_256 = 501 -+INTR_X86_AVX_SQRT_PD_256 = 502 -+INTR_X86_AVX_SQRT_PS_256 = 503 -+INTR_X86_AVX_STOREU_DQ_256 = 504 -+INTR_X86_AVX_STOREU_PD_256 = 505 -+INTR_X86_AVX_STOREU_PS_256 = 506 -+INTR_X86_AVX_VBROADCAST_SD_256 = 507 -+INTR_X86_AVX_VBROADCASTF128_PD_256 = 508 -+INTR_X86_AVX_VBROADCASTF128_PS_256 = 509 -+INTR_X86_AVX_VBROADCASTSS = 510 -+INTR_X86_AVX_VBROADCASTSS_256 = 511 -+INTR_X86_AVX_VEXTRACTF128_PD_256 = 512 -+INTR_X86_AVX_VEXTRACTF128_PS_256 = 513 -+INTR_X86_AVX_VEXTRACTF128_SI_256 = 514 -+INTR_X86_AVX_VINSERTF128_PD_256 = 515 -+INTR_X86_AVX_VINSERTF128_PS_256 = 516 -+INTR_X86_AVX_VINSERTF128_SI_256 = 517 -+INTR_X86_AVX_VPERM2F128_PD_256 = 518 -+INTR_X86_AVX_VPERM2F128_PS_256 = 519 -+INTR_X86_AVX_VPERM2F128_SI_256 = 520 -+INTR_X86_AVX_VPERMIL_PD = 521 -+INTR_X86_AVX_VPERMIL_PD_256 = 522 -+INTR_X86_AVX_VPERMIL_PS = 523 -+INTR_X86_AVX_VPERMIL_PS_256 = 524 -+INTR_X86_AVX_VPERMILVAR_PD = 525 -+INTR_X86_AVX_VPERMILVAR_PD_256 = 526 -+INTR_X86_AVX_VPERMILVAR_PS = 527 -+INTR_X86_AVX_VPERMILVAR_PS_256 = 528 -+INTR_X86_AVX_VTESTC_PD = 529 -+INTR_X86_AVX_VTESTC_PD_256 = 530 -+INTR_X86_AVX_VTESTC_PS = 531 -+INTR_X86_AVX_VTESTC_PS_256 = 532 -+INTR_X86_AVX_VTESTNZC_PD = 533 -+INTR_X86_AVX_VTESTNZC_PD_256 = 534 -+INTR_X86_AVX_VTESTNZC_PS = 535 -+INTR_X86_AVX_VTESTNZC_PS_256 = 536 -+INTR_X86_AVX_VTESTZ_PD = 537 -+INTR_X86_AVX_VTESTZ_PD_256 = 538 -+INTR_X86_AVX_VTESTZ_PS = 539 -+INTR_X86_AVX_VTESTZ_PS_256 = 540 -+INTR_X86_AVX_VZEROALL = 541 -+INTR_X86_AVX_VZEROUPPER = 542 -+INTR_X86_INT = 543 -+INTR_X86_MMX_EMMS = 544 -+INTR_X86_MMX_FEMMS = 545 -+INTR_X86_MMX_MASKMOVQ = 546 -+INTR_X86_MMX_MOVNT_DQ = 547 -+INTR_X86_MMX_PACKSSDW = 548 -+INTR_X86_MMX_PACKSSWB = 549 -+INTR_X86_MMX_PACKUSWB = 550 -+INTR_X86_MMX_PADD_B = 551 -+INTR_X86_MMX_PADD_D = 552 -+INTR_X86_MMX_PADD_Q = 553 -+INTR_X86_MMX_PADD_W = 554 -+INTR_X86_MMX_PADDS_B = 555 -+INTR_X86_MMX_PADDS_W = 556 -+INTR_X86_MMX_PADDUS_B = 557 -+INTR_X86_MMX_PADDUS_W = 558 -+INTR_X86_MMX_PALIGNR_B = 559 -+INTR_X86_MMX_PAND = 560 -+INTR_X86_MMX_PANDN = 561 -+INTR_X86_MMX_PAVG_B = 562 -+INTR_X86_MMX_PAVG_W = 563 -+INTR_X86_MMX_PCMPEQ_B = 564 -+INTR_X86_MMX_PCMPEQ_D = 565 -+INTR_X86_MMX_PCMPEQ_W = 566 -+INTR_X86_MMX_PCMPGT_B = 567 -+INTR_X86_MMX_PCMPGT_D = 568 -+INTR_X86_MMX_PCMPGT_W = 569 -+INTR_X86_MMX_PEXTR_W = 570 -+INTR_X86_MMX_PINSR_W = 571 -+INTR_X86_MMX_PMADD_WD = 572 -+INTR_X86_MMX_PMAXS_W = 573 -+INTR_X86_MMX_PMAXU_B = 574 -+INTR_X86_MMX_PMINS_W = 575 -+INTR_X86_MMX_PMINU_B = 576 -+INTR_X86_MMX_PMOVMSKB = 577 -+INTR_X86_MMX_PMULH_W = 578 -+INTR_X86_MMX_PMULHU_W = 579 -+INTR_X86_MMX_PMULL_W = 580 -+INTR_X86_MMX_PMULU_DQ = 581 -+INTR_X86_MMX_POR = 582 -+INTR_X86_MMX_PSAD_BW = 583 -+INTR_X86_MMX_PSLL_D = 584 -+INTR_X86_MMX_PSLL_Q = 585 -+INTR_X86_MMX_PSLL_W = 586 -+INTR_X86_MMX_PSLLI_D = 587 -+INTR_X86_MMX_PSLLI_Q = 588 -+INTR_X86_MMX_PSLLI_W = 589 -+INTR_X86_MMX_PSRA_D = 590 -+INTR_X86_MMX_PSRA_W = 591 -+INTR_X86_MMX_PSRAI_D = 592 -+INTR_X86_MMX_PSRAI_W = 593 -+INTR_X86_MMX_PSRL_D = 594 -+INTR_X86_MMX_PSRL_Q = 595 -+INTR_X86_MMX_PSRL_W = 596 -+INTR_X86_MMX_PSRLI_D = 597 -+INTR_X86_MMX_PSRLI_Q = 598 -+INTR_X86_MMX_PSRLI_W = 599 -+INTR_X86_MMX_PSUB_B = 600 -+INTR_X86_MMX_PSUB_D = 601 -+INTR_X86_MMX_PSUB_Q = 602 -+INTR_X86_MMX_PSUB_W = 603 -+INTR_X86_MMX_PSUBS_B = 604 -+INTR_X86_MMX_PSUBS_W = 605 -+INTR_X86_MMX_PSUBUS_B = 606 -+INTR_X86_MMX_PSUBUS_W = 607 -+INTR_X86_MMX_PUNPCKHBW = 608 -+INTR_X86_MMX_PUNPCKHDQ = 609 -+INTR_X86_MMX_PUNPCKHWD = 610 -+INTR_X86_MMX_PUNPCKLBW = 611 -+INTR_X86_MMX_PUNPCKLDQ = 612 -+INTR_X86_MMX_PUNPCKLWD = 613 -+INTR_X86_MMX_PXOR = 614 -+INTR_X86_SSE2_ADD_SD = 615 -+INTR_X86_SSE2_CLFLUSH = 616 -+INTR_X86_SSE2_CMP_PD = 617 -+INTR_X86_SSE2_CMP_SD = 618 -+INTR_X86_SSE2_COMIEQ_SD = 619 -+INTR_X86_SSE2_COMIGE_SD = 620 -+INTR_X86_SSE2_COMIGT_SD = 621 -+INTR_X86_SSE2_COMILE_SD = 622 -+INTR_X86_SSE2_COMILT_SD = 623 -+INTR_X86_SSE2_COMINEQ_SD = 624 -+INTR_X86_SSE2_CVTDQ2PD = 625 -+INTR_X86_SSE2_CVTDQ2PS = 626 -+INTR_X86_SSE2_CVTPD2DQ = 627 -+INTR_X86_SSE2_CVTPD2PS = 628 -+INTR_X86_SSE2_CVTPS2DQ = 629 -+INTR_X86_SSE2_CVTPS2PD = 630 -+INTR_X86_SSE2_CVTSD2SI = 631 -+INTR_X86_SSE2_CVTSD2SI64 = 632 -+INTR_X86_SSE2_CVTSD2SS = 633 -+INTR_X86_SSE2_CVTSI2SD = 634 -+INTR_X86_SSE2_CVTSI642SD = 635 -+INTR_X86_SSE2_CVTSS2SD = 636 -+INTR_X86_SSE2_CVTTPD2DQ = 637 -+INTR_X86_SSE2_CVTTPS2DQ = 638 -+INTR_X86_SSE2_CVTTSD2SI = 639 -+INTR_X86_SSE2_CVTTSD2SI64 = 640 -+INTR_X86_SSE2_DIV_SD = 641 -+INTR_X86_SSE2_LFENCE = 642 -+INTR_X86_SSE2_LOADU_DQ = 643 -+INTR_X86_SSE2_LOADU_PD = 644 -+INTR_X86_SSE2_MASKMOV_DQU = 645 -+INTR_X86_SSE2_MAX_PD = 646 -+INTR_X86_SSE2_MAX_SD = 647 -+INTR_X86_SSE2_MFENCE = 648 -+INTR_X86_SSE2_MIN_PD = 649 -+INTR_X86_SSE2_MIN_SD = 650 -+INTR_X86_SSE2_MOVMSK_PD = 651 -+INTR_X86_SSE2_MOVNT_DQ = 652 -+INTR_X86_SSE2_MOVNT_I = 653 -+INTR_X86_SSE2_MOVNT_PD = 654 -+INTR_X86_SSE2_MUL_SD = 655 -+INTR_X86_SSE2_PACKSSDW_128 = 656 -+INTR_X86_SSE2_PACKSSWB_128 = 657 -+INTR_X86_SSE2_PACKUSWB_128 = 658 -+INTR_X86_SSE2_PADDS_B = 659 -+INTR_X86_SSE2_PADDS_W = 660 -+INTR_X86_SSE2_PADDUS_B = 661 -+INTR_X86_SSE2_PADDUS_W = 662 -+INTR_X86_SSE2_PAVG_B = 663 -+INTR_X86_SSE2_PAVG_W = 664 -+INTR_X86_SSE2_PCMPEQ_B = 665 -+INTR_X86_SSE2_PCMPEQ_D = 666 -+INTR_X86_SSE2_PCMPEQ_W = 667 -+INTR_X86_SSE2_PCMPGT_B = 668 -+INTR_X86_SSE2_PCMPGT_D = 669 -+INTR_X86_SSE2_PCMPGT_W = 670 -+INTR_X86_SSE2_PMADD_WD = 671 -+INTR_X86_SSE2_PMAXS_W = 672 -+INTR_X86_SSE2_PMAXU_B = 673 -+INTR_X86_SSE2_PMINS_W = 674 -+INTR_X86_SSE2_PMINU_B = 675 -+INTR_X86_SSE2_PMOVMSKB_128 = 676 -+INTR_X86_SSE2_PMULH_W = 677 -+INTR_X86_SSE2_PMULHU_W = 678 -+INTR_X86_SSE2_PMULU_DQ = 679 -+INTR_X86_SSE2_PSAD_BW = 680 -+INTR_X86_SSE2_PSLL_D = 681 -+INTR_X86_SSE2_PSLL_DQ = 682 -+INTR_X86_SSE2_PSLL_DQ_BS = 683 -+INTR_X86_SSE2_PSLL_Q = 684 -+INTR_X86_SSE2_PSLL_W = 685 -+INTR_X86_SSE2_PSLLI_D = 686 -+INTR_X86_SSE2_PSLLI_Q = 687 -+INTR_X86_SSE2_PSLLI_W = 688 -+INTR_X86_SSE2_PSRA_D = 689 -+INTR_X86_SSE2_PSRA_W = 690 -+INTR_X86_SSE2_PSRAI_D = 691 -+INTR_X86_SSE2_PSRAI_W = 692 -+INTR_X86_SSE2_PSRL_D = 693 -+INTR_X86_SSE2_PSRL_DQ = 694 -+INTR_X86_SSE2_PSRL_DQ_BS = 695 -+INTR_X86_SSE2_PSRL_Q = 696 -+INTR_X86_SSE2_PSRL_W = 697 -+INTR_X86_SSE2_PSRLI_D = 698 -+INTR_X86_SSE2_PSRLI_Q = 699 -+INTR_X86_SSE2_PSRLI_W = 700 -+INTR_X86_SSE2_PSUBS_B = 701 -+INTR_X86_SSE2_PSUBS_W = 702 -+INTR_X86_SSE2_PSUBUS_B = 703 -+INTR_X86_SSE2_PSUBUS_W = 704 -+INTR_X86_SSE2_SQRT_PD = 705 -+INTR_X86_SSE2_SQRT_SD = 706 -+INTR_X86_SSE2_STOREL_DQ = 707 -+INTR_X86_SSE2_STOREU_DQ = 708 -+INTR_X86_SSE2_STOREU_PD = 709 -+INTR_X86_SSE2_SUB_SD = 710 -+INTR_X86_SSE2_UCOMIEQ_SD = 711 -+INTR_X86_SSE2_UCOMIGE_SD = 712 -+INTR_X86_SSE2_UCOMIGT_SD = 713 -+INTR_X86_SSE2_UCOMILE_SD = 714 -+INTR_X86_SSE2_UCOMILT_SD = 715 -+INTR_X86_SSE2_UCOMINEQ_SD = 716 -+INTR_X86_SSE3_ADDSUB_PD = 717 -+INTR_X86_SSE3_ADDSUB_PS = 718 -+INTR_X86_SSE3_HADD_PD = 719 -+INTR_X86_SSE3_HADD_PS = 720 -+INTR_X86_SSE3_HSUB_PD = 721 -+INTR_X86_SSE3_HSUB_PS = 722 -+INTR_X86_SSE3_LDU_DQ = 723 -+INTR_X86_SSE3_MONITOR = 724 -+INTR_X86_SSE3_MWAIT = 725 -+INTR_X86_SSE41_BLENDPD = 726 -+INTR_X86_SSE41_BLENDPS = 727 -+INTR_X86_SSE41_BLENDVPD = 728 -+INTR_X86_SSE41_BLENDVPS = 729 -+INTR_X86_SSE41_DPPD = 730 -+INTR_X86_SSE41_DPPS = 731 -+INTR_X86_SSE41_EXTRACTPS = 732 -+INTR_X86_SSE41_INSERTPS = 733 -+INTR_X86_SSE41_MOVNTDQA = 734 -+INTR_X86_SSE41_MPSADBW = 735 -+INTR_X86_SSE41_PACKUSDW = 736 -+INTR_X86_SSE41_PBLENDVB = 737 -+INTR_X86_SSE41_PBLENDW = 738 -+INTR_X86_SSE41_PCMPEQQ = 739 -+INTR_X86_SSE41_PEXTRB = 740 -+INTR_X86_SSE41_PEXTRD = 741 -+INTR_X86_SSE41_PEXTRQ = 742 -+INTR_X86_SSE41_PHMINPOSUW = 743 -+INTR_X86_SSE41_PMAXSB = 744 -+INTR_X86_SSE41_PMAXSD = 745 -+INTR_X86_SSE41_PMAXUD = 746 -+INTR_X86_SSE41_PMAXUW = 747 -+INTR_X86_SSE41_PMINSB = 748 -+INTR_X86_SSE41_PMINSD = 749 -+INTR_X86_SSE41_PMINUD = 750 -+INTR_X86_SSE41_PMINUW = 751 -+INTR_X86_SSE41_PMOVSXBD = 752 -+INTR_X86_SSE41_PMOVSXBQ = 753 -+INTR_X86_SSE41_PMOVSXBW = 754 -+INTR_X86_SSE41_PMOVSXDQ = 755 -+INTR_X86_SSE41_PMOVSXWD = 756 -+INTR_X86_SSE41_PMOVSXWQ = 757 -+INTR_X86_SSE41_PMOVZXBD = 758 -+INTR_X86_SSE41_PMOVZXBQ = 759 -+INTR_X86_SSE41_PMOVZXBW = 760 -+INTR_X86_SSE41_PMOVZXDQ = 761 -+INTR_X86_SSE41_PMOVZXWD = 762 -+INTR_X86_SSE41_PMOVZXWQ = 763 -+INTR_X86_SSE41_PMULDQ = 764 -+INTR_X86_SSE41_PTESTC = 765 -+INTR_X86_SSE41_PTESTNZC = 766 -+INTR_X86_SSE41_PTESTZ = 767 -+INTR_X86_SSE41_ROUND_PD = 768 -+INTR_X86_SSE41_ROUND_PS = 769 -+INTR_X86_SSE41_ROUND_SD = 770 -+INTR_X86_SSE41_ROUND_SS = 771 -+INTR_X86_SSE42_CRC32_16 = 772 -+INTR_X86_SSE42_CRC32_32 = 773 -+INTR_X86_SSE42_CRC32_8 = 774 -+INTR_X86_SSE42_CRC64_64 = 775 -+INTR_X86_SSE42_CRC64_8 = 776 -+INTR_X86_SSE42_PCMPESTRI128 = 777 -+INTR_X86_SSE42_PCMPESTRIA128 = 778 -+INTR_X86_SSE42_PCMPESTRIC128 = 779 -+INTR_X86_SSE42_PCMPESTRIO128 = 780 -+INTR_X86_SSE42_PCMPESTRIS128 = 781 -+INTR_X86_SSE42_PCMPESTRIZ128 = 782 -+INTR_X86_SSE42_PCMPESTRM128 = 783 -+INTR_X86_SSE42_PCMPGTQ = 784 -+INTR_X86_SSE42_PCMPISTRI128 = 785 -+INTR_X86_SSE42_PCMPISTRIA128 = 786 -+INTR_X86_SSE42_PCMPISTRIC128 = 787 -+INTR_X86_SSE42_PCMPISTRIO128 = 788 -+INTR_X86_SSE42_PCMPISTRIS128 = 789 -+INTR_X86_SSE42_PCMPISTRIZ128 = 790 -+INTR_X86_SSE42_PCMPISTRM128 = 791 -+INTR_X86_SSE_ADD_SS = 792 -+INTR_X86_SSE_CMP_PS = 793 -+INTR_X86_SSE_CMP_SS = 794 -+INTR_X86_SSE_COMIEQ_SS = 795 -+INTR_X86_SSE_COMIGE_SS = 796 -+INTR_X86_SSE_COMIGT_SS = 797 -+INTR_X86_SSE_COMILE_SS = 798 -+INTR_X86_SSE_COMILT_SS = 799 -+INTR_X86_SSE_COMINEQ_SS = 800 -+INTR_X86_SSE_CVTPD2PI = 801 -+INTR_X86_SSE_CVTPI2PD = 802 -+INTR_X86_SSE_CVTPI2PS = 803 -+INTR_X86_SSE_CVTPS2PI = 804 -+INTR_X86_SSE_CVTSI2SS = 805 -+INTR_X86_SSE_CVTSI642SS = 806 -+INTR_X86_SSE_CVTSS2SI = 807 -+INTR_X86_SSE_CVTSS2SI64 = 808 -+INTR_X86_SSE_CVTTPD2PI = 809 -+INTR_X86_SSE_CVTTPS2PI = 810 -+INTR_X86_SSE_CVTTSS2SI = 811 -+INTR_X86_SSE_CVTTSS2SI64 = 812 -+INTR_X86_SSE_DIV_SS = 813 -+INTR_X86_SSE_LDMXCSR = 814 -+INTR_X86_SSE_LOADU_PS = 815 -+INTR_X86_SSE_MAX_PS = 816 -+INTR_X86_SSE_MAX_SS = 817 -+INTR_X86_SSE_MIN_PS = 818 -+INTR_X86_SSE_MIN_SS = 819 -+INTR_X86_SSE_MOVMSK_PS = 820 -+INTR_X86_SSE_MOVNT_PS = 821 -+INTR_X86_SSE_MUL_SS = 822 -+INTR_X86_SSE_PSHUF_W = 823 -+INTR_X86_SSE_RCP_PS = 824 -+INTR_X86_SSE_RCP_SS = 825 -+INTR_X86_SSE_RSQRT_PS = 826 -+INTR_X86_SSE_RSQRT_SS = 827 -+INTR_X86_SSE_SFENCE = 828 -+INTR_X86_SSE_SQRT_PS = 829 -+INTR_X86_SSE_SQRT_SS = 830 -+INTR_X86_SSE_STMXCSR = 831 -+INTR_X86_SSE_STOREU_PS = 832 -+INTR_X86_SSE_SUB_SS = 833 -+INTR_X86_SSE_UCOMIEQ_SS = 834 -+INTR_X86_SSE_UCOMIGE_SS = 835 -+INTR_X86_SSE_UCOMIGT_SS = 836 -+INTR_X86_SSE_UCOMILE_SS = 837 -+INTR_X86_SSE_UCOMILT_SS = 838 -+INTR_X86_SSE_UCOMINEQ_SS = 839 -+INTR_X86_SSSE3_PABS_B = 840 -+INTR_X86_SSSE3_PABS_B_128 = 841 -+INTR_X86_SSSE3_PABS_D = 842 -+INTR_X86_SSSE3_PABS_D_128 = 843 -+INTR_X86_SSSE3_PABS_W = 844 -+INTR_X86_SSSE3_PABS_W_128 = 845 -+INTR_X86_SSSE3_PHADD_D = 846 -+INTR_X86_SSSE3_PHADD_D_128 = 847 -+INTR_X86_SSSE3_PHADD_SW = 848 -+INTR_X86_SSSE3_PHADD_SW_128 = 849 -+INTR_X86_SSSE3_PHADD_W = 850 -+INTR_X86_SSSE3_PHADD_W_128 = 851 -+INTR_X86_SSSE3_PHSUB_D = 852 -+INTR_X86_SSSE3_PHSUB_D_128 = 853 -+INTR_X86_SSSE3_PHSUB_SW = 854 -+INTR_X86_SSSE3_PHSUB_SW_128 = 855 -+INTR_X86_SSSE3_PHSUB_W = 856 -+INTR_X86_SSSE3_PHSUB_W_128 = 857 -+INTR_X86_SSSE3_PMADD_UB_SW = 858 -+INTR_X86_SSSE3_PMADD_UB_SW_128 = 859 -+INTR_X86_SSSE3_PMUL_HR_SW = 860 -+INTR_X86_SSSE3_PMUL_HR_SW_128 = 861 -+INTR_X86_SSSE3_PSHUF_B = 862 -+INTR_X86_SSSE3_PSHUF_B_128 = 863 -+INTR_X86_SSSE3_PSIGN_B = 864 -+INTR_X86_SSSE3_PSIGN_B_128 = 865 -+INTR_X86_SSSE3_PSIGN_D = 866 -+INTR_X86_SSSE3_PSIGN_D_128 = 867 -+INTR_X86_SSSE3_PSIGN_W = 868 -+INTR_X86_SSSE3_PSIGN_W_128 = 869 -+INTR_XCORE_BITREV = 870 -+INTR_XCORE_CHKCT = 871 -+INTR_XCORE_CLRE = 872 -+INTR_XCORE_EEU = 873 -+INTR_XCORE_FREER = 874 -+INTR_XCORE_GETID = 875 -+INTR_XCORE_GETR = 876 -+INTR_XCORE_GETTS = 877 -+INTR_XCORE_IN = 878 -+INTR_XCORE_INCT = 879 -+INTR_XCORE_INSHR = 880 -+INTR_XCORE_INT = 881 -+INTR_XCORE_OUT = 882 -+INTR_XCORE_OUTCT = 883 -+INTR_XCORE_OUTSHR = 884 -+INTR_XCORE_OUTT = 885 -+INTR_XCORE_SETC = 886 -+INTR_XCORE_SETD = 887 -+INTR_XCORE_SETPT = 888 -+INTR_XCORE_SETTW = 889 -+INTR_XCORE_SETV = 890 -+INTR_XCORE_SYNCR = 891 -+INTR_XCORE_WAITEVENT = 892 -Index: _core.c -=================================================================== ---- _core.c (revision 105) -+++ _core.c (working copy) -@@ -807,7 +807,7 @@ - _wrap_pass( EdgeProfiler ) - _wrap_pass( FunctionAttrs ) - _wrap_pass( FunctionInlining ) --_wrap_pass( GEPSplitter ) -+//_wrap_pass( GEPSplitter ) - _wrap_pass( GlobalDCE ) - _wrap_pass( GlobalOptimizer ) - _wrap_pass( GlobalsModRef ) -@@ -822,11 +822,11 @@ - _wrap_pass( LazyValueInfo ) - _wrap_pass( LCSSA ) - _wrap_pass( LICM ) --_wrap_pass( LiveValues ) -+//_wrap_pass( LiveValues ) - _wrap_pass( LoopDeletion ) - _wrap_pass( LoopDependenceAnalysis ) - _wrap_pass( LoopExtractor ) --_wrap_pass( LoopIndexSplit ) -+//_wrap_pass( LoopIndexSplit ) - _wrap_pass( LoopRotate ) - _wrap_pass( LoopSimplify ) - _wrap_pass( LoopStrengthReduce ) -@@ -841,7 +841,7 @@ - _wrap_pass( NoProfileInfo ) - _wrap_pass( OptimalEdgeProfiler ) - _wrap_pass( PartialInlining ) --_wrap_pass( PartialSpecialization ) -+//_wrap_pass( PartialSpecialization ) - _wrap_pass( PostDomOnlyPrinter ) - _wrap_pass( PostDomOnlyViewer ) - _wrap_pass( PostDomPrinter ) -@@ -855,7 +855,7 @@ - _wrap_pass( ScalarEvolutionAliasAnalysis ) - _wrap_pass( ScalarReplAggregates ) - _wrap_pass( SCCP ) --_wrap_pass( SimplifyHalfPowrLibCalls ) -+//_wrap_pass( SimplifyHalfPowrLibCalls ) - _wrap_pass( SimplifyLibCalls ) - _wrap_pass( SingleLoopExtractor ) - _wrap_pass( StripDeadPrototypes ) -@@ -1162,7 +1162,7 @@ - Py_RETURN_NONE; - } - --_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) -+//_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) - - /* Expose the void* inside a PyCObject as a PyLong. This allows us to - * use it as a unique ID. */ -@@ -1569,7 +1569,7 @@ - _pass( EdgeProfiler ) - _pass( FunctionAttrs ) - _pass( FunctionInlining ) -- _pass( GEPSplitter ) -+ //_pass( GEPSplitter ) - _pass( GlobalDCE ) - _pass( GlobalOptimizer ) - _pass( GlobalsModRef ) -@@ -1584,11 +1584,11 @@ - _pass( LazyValueInfo ) - _pass( LCSSA ) - _pass( LICM ) -- _pass( LiveValues ) -+ //_pass( LiveValues ) - _pass( LoopDeletion ) - _pass( LoopDependenceAnalysis ) - _pass( LoopExtractor ) -- _pass( LoopIndexSplit ) -+ //_pass( LoopIndexSplit ) - _pass( LoopRotate ) - _pass( LoopSimplify ) - _pass( LoopStrengthReduce ) -@@ -1603,7 +1603,7 @@ - _pass( NoProfileInfo ) - _pass( OptimalEdgeProfiler ) - _pass( PartialInlining ) -- _pass( PartialSpecialization ) -+ //_pass( PartialSpecialization ) - _pass( PostDomOnlyPrinter ) - _pass( PostDomOnlyViewer ) - _pass( PostDomPrinter ) -@@ -1617,7 +1617,7 @@ - _pass( ScalarEvolutionAliasAnalysis ) - _pass( ScalarReplAggregates ) - _pass( SCCP ) -- _pass( SimplifyHalfPowrLibCalls ) -+ //_pass( SimplifyHalfPowrLibCalls ) - _pass( SimplifyLibCalls ) - _pass( SingleLoopExtractor ) - _pass( StripDeadPrototypes ) -@@ -1672,7 +1672,7 @@ - /* Misc */ - _method( LLVMGetIntrinsic ) - _method( LLVMLoadLibraryPermanently ) -- _method( LLVMInlineFunction ) -+ //_method( LLVMInlineFunction ) - _method( PyCObjectVoidPtrToPyLong ) - - { NULL } -Index: extra.h -=================================================================== ---- extra.h (revision 105) -+++ extra.h (working copy) -@@ -181,7 +181,7 @@ - /* Wraps llvm::InlineFunction(). Inlines a function. C is the call - * instruction, created by LLVMBuildCall. Even if it fails, the Function - * containing the call is still in a proper state (not changed). */ --int LLVMInlineFunction(LLVMValueRef call); -+//int LLVMInlineFunction(LLVMValueRef call); - - /* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the - * already available LLVMSetParamAlignment(). */ -@@ -209,13 +209,13 @@ - declare_pass( DomPrinter ) - declare_pass( DomViewer ) - declare_pass( EdgeProfiler ) --declare_pass( GEPSplitter ) -+//declare_pass( GEPSplitter ) - declare_pass( GlobalsModRef ) - declare_pass( InstCount ) - declare_pass( InstructionNamer ) - declare_pass( LazyValueInfo ) - declare_pass( LCSSA ) --declare_pass( LiveValues ) -+//declare_pass( LiveValues ) - declare_pass( LoopDependenceAnalysis ) - declare_pass( LoopExtractor ) - declare_pass( LoopSimplify ) -@@ -227,7 +227,7 @@ - declare_pass( NoProfileInfo ) - declare_pass( OptimalEdgeProfiler ) - declare_pass( PartialInlining ) --declare_pass( PartialSpecialization ) -+//declare_pass( PartialSpecialization ) - declare_pass( PostDomOnlyPrinter ) - declare_pass( PostDomOnlyViewer ) - declare_pass( PostDomPrinter ) diff --git a/llvm/__init__.py b/llvm/__init__.py index 8f61f35..e69de29 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,154 +0,0 @@ -""" -Common classes related to LLVM. -""" - -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions - - -from weakref import WeakValueDictionary -from . import _core - -#===----------------------------------------------------------------------=== -# LLVM Version -#===----------------------------------------------------------------------=== - -version = _core.LLVMGetVersion() - -def require_version_at_least(major, minor): - '''Sentry to guard version requirement - ''' - if version < (major, minor): - raise Exception(major, minor) - -#===----------------------------------------------------------------------=== -# Exceptions -#===----------------------------------------------------------------------=== - -class LLVMException(Exception): - """Generic LLVM exception.""" - - def __init__(self, msg=""): - Exception.__init__(self, msg) - - -#===----------------------------------------------------------------------=== -# Ownables -#===----------------------------------------------------------------------=== - -class Ownable(object): - """Objects that can be owned. - - Modules and Module Providers can be owned, i.e., the responsibility of - destruction of ownable objects can be handed over to other objects. The - llvm.Ownable class represents objects that can be so owned. This class - is NOT intended for public use. - """ - - def __init__(self, ptr, del_fn): - self.ptr = ptr - self.owner = None - self.del_fn = del_fn - - def _own(self, owner): - if self.owner: - raise LLVMException("object already owned") - self.owner = owner - - def _disown(self): - if not self.owner: - raise LLVMException("not owned") - self.owner = None - - def __del__(self): - if not self.owner: - self.del_fn(self.ptr) - - -#===----------------------------------------------------------------------=== -# Dummy owner, will not delete ownee. Be careful. -#===----------------------------------------------------------------------=== - -class DummyOwner(object): - pass - - -#===----------------------------------------------------------------------=== -# A metaclass to prevent aliasing. It stores a (weak) reference to objects -# constructed based on a PyCObject. If an object is constructed based on a -# PyCObject with the same underlying pointer as a previous object, a reference -# to the previous object is returned rather than a new one. -#===----------------------------------------------------------------------=== - -class _ObjectCache(type): - """A metaclass to prevent aliasing. - - Classes using 'ObjectCache' as a metaclass must have constructors - that take a PyCObject as their first argument. When the class is - called (to create a new instance of the class), the value of the - pointer wrapped by the PyCObj is checked: - - If no previous object has been created based on the same - underlying pointer (note that different PyCObject objects can - wrap the same pointer), the object will be initialized as - usual and returned. - - If a previous has been created based on the same pointer, - then a reference to that object will be returned, and no - object initialization is performed. - """ - - __instances = WeakValueDictionary() - - def __call__(cls, ptr, *args, **kwargs): - objid = _core.PyCObjectVoidPtrToPyLong(ptr) - key = "%s:%d" % (cls.__name__, objid) - obj = _ObjectCache.__instances.get(key) - if obj is None: - obj = super(_ObjectCache, cls).__call__(ptr, *args, **kwargs) - _ObjectCache.__instances[key] = obj - return obj - - @staticmethod - def forget(obj): - objid = _core.PyCObjectVoidPtrToPyLong(obj.ptr) - key = "%s:%d" % (type(obj).__name__, objid) - if key in _ObjectCache.__instances: - del _ObjectCache.__instances[key] - - -#===----------------------------------------------------------------------=== -# Cacheables -#===----------------------------------------------------------------------=== - -# version 2/3 compatibility help -# version 2 metaclass -# class Cacheable(object): -# __metaclass__ = _ObjectCache # Doing nothing for version 3 -# -# version 3 metaclass -# class Cacheable(metaclass=_ObjectCache): -# -# Reference: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/#using-the-metaclass-in-python-3-x -ObjectCache = _ObjectCache('ObjectCache', (object, ), {}) - -class Cacheable(ObjectCache): - """Objects that can be cached. - - Objects that wrap a PyCObject are cached to avoid "aliasing", i.e., - two Python objects each containing a PyCObject which internally points - to the same C pointer.""" - - def forget(self): - ObjectCache.forget(self) - - -def test(verbosity=1): - """test(verbosity=1) -> TextTestResult - - Run self-test, and return unittest.runner.TextTestResult object. - """ - from llvm.test_llvmpy import run - - return run(verbosity=verbosity) diff --git a/llvm/_core.cpp b/llvm/_core.cpp deleted file mode 100644 index db5287e..0000000 --- a/llvm/_core.cpp +++ /dev/null @@ -1,2212 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* our includes */ -#include "wrap.h" -#include "extra.h" - - - -// Python include -#include "Python.h" - -/* LLVM includes */ -#include "llvm-c/Analysis.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/IPO.h" - -#include "llvm/Support/CommandLine.h" -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #include "llvm-c/Linker.h" -#else - typedef unsigned int LLVMLinkerMode; -#endif - -/* Compatibility with Python 2.4: Py_ssize_t is not available. */ -#ifndef PY_SSIZE_T_MAX -typedef int Py_ssize_t; -#endif - - -// explicit specializations -template <> PyObject* pycap_new(int i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(unsigned long i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMTypeKind i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMLinkage i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMVisibility i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMByteOrdering i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(unsigned PY_LONG_LONG ull) -{ - return PyLong_FromUnsignedLongLong(ull); -} - -template <> PyObject* pycap_new(PY_LONG_LONG ll) -{ - return PyLong_FromLongLong(ll); -} - -/*===----------------------------------------------------------------------===*/ -/* Modules */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMModuleCreateWithName(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *s; - - if (!PyArg_ParseTuple(args, "s:LLVMModuleCreateWithName", &s)) { - return NULL; - } - - const LLVMModuleRef module = LLVMModuleCreateWithName(s); - return pycap_new(module); - LLVMPY_CATCH_ALL -} - -_wrap_obj2str(LLVMGetDataLayout, LLVMModuleRef) -_wrap_objstr2none(LLVMSetDataLayout, LLVMModuleRef) -_wrap_obj2str(LLVMGetModuleIdentifier, LLVMModuleRef) -_wrap_objstr2none(LLVMSetModuleIdentifier, LLVMModuleRef) -_wrap_obj2str(LLVMGetTarget, LLVMModuleRef) -_wrap_objstr2none(LLVMSetTarget, LLVMModuleRef) -_wrap_objstr2none(LLVMModuleAddLibrary, LLVMModuleRef) -_wrap_objstr2obj(LLVMGetTypeByName, LLVMModuleRef, LLVMTypeRef) -_wrap_obj2none(LLVMDumpModule, LLVMModuleRef) -_wrap_obj2none(LLVMDisposeModule, LLVMModuleRef) -_wrap_dumper(LLVMDumpModuleToString, LLVMModuleRef) - _wrap_obj2obj( LLVMModuleGetPointerSize, LLVMModuleRef, int) -_wrap_objstrobj2obj(LLVMModuleGetOrInsertFunction, LLVMModuleRef, - LLVMTypeRef, LLVMValueRef) - -static PyObject * -_wLLVMVerifyModule(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMModuleRef m = get_object_arg(args) ; - if (!m) return NULL; - - char *outmsg = 0; - (void) LLVMVerifyModule(m, LLVMReturnStatusAction, &outmsg); - - PyObject *ret; - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = PyUnicode_FromString(""); - } - - return ret; - LLVMPY_CATCH_ALL -} - -///// unused -// typedef LLVMModuleRef (*asm_or_bc_fn_t)(const char *A, unsigned Len, char **OutMessage); - - -static PyObject* -_wLLVMGetModuleFromAssembly(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char * str; -#if (PY_MAJOR_VERSION >= 3) - if ( !PyArg_ParseTuple(args, "y", &str) ){ -#else - if ( !PyArg_ParseTuple(args, "s", &str) ){ -#endif - return NULL; - } - - char * outmsg = 0; - const LLVMModuleRef mod = LLVMGetModuleFromAssembly(str, &outmsg); - - if ( !mod ){ - if ( outmsg ){ - PyObject * ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } else { - Py_RETURN_NONE; - } - } - - return pycap_new(mod); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj ; - - if (!PyArg_ParseTuple(args, "S", &obj)) - return NULL; - - const char *start = PyBytes_AsString(obj); - const Py_ssize_t len = PyBytes_Size(obj); - - char *outmsg = 0; - LLVMModuleRef m = LLVMGetModuleFromBitcode(start, len, &outmsg); - - PyObject *ret; - if (!m) { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } else { - Py_RETURN_NONE; - } - } - - return pycap_new(m); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMModuleRef m = get_object_arg(args) ; - if (!m ) return NULL; - - size_t len; - const unsigned char *ubytes = LLVMGetBitcodeFromModule(m, &len) ; - if ( !ubytes ) Py_RETURN_NONE; - - const char *chars = reinterpret_cast(ubytes) ; - PyObject *ret = PyBytes_FromStringAndSize(chars, len); - delete [] ubytes; - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetNativeCodeFromModule(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - PyObject * arg_m; - int arg_use_asm; - - if (!PyArg_ParseTuple(args, "Oi", &arg_m, &arg_use_asm)) - return NULL; - - const LLVMModuleRef m = pycap_get( arg_m ) ; - - std::string error; - size_t len; - unsigned const char * ubytes - = LLVMGetNativeCodeFromModule(m, arg_use_asm, &len, error); - if ( !error.empty() ){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - } - - const char *chars = reinterpret_cast(ubytes) ; - PyObject * ret = PyBytes_FromStringAndSize(chars, len); - - delete [] ubytes; - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMLinkModules(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - size_t mode = 0; - - PyObject *dest_obj, *src_obj ; - if (!PyArg_ParseTuple(args, "OO|I", &dest_obj, &src_obj, &mode)) - return NULL; - - const LLVMModuleRef dest = pycap_get(dest_obj ) ; - const LLVMModuleRef src = pycap_get(src_obj) ; - - PyObject *ret = NULL; - char *errmsg = NULL; - if (LLVMLinkModules(dest, src, (LLVMLinkerMode)mode, &errmsg)) { - if (errmsg) { - ret = PyUnicode_FromString(errmsg); - LLVMDisposeMessage(errmsg); - } else { - ret = PyUnicode_FromString("Link error"); - } - return ret; - } - - /* note: success => None, failure => string with error message */ - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -_wrap_objstr2obj(LLVMModuleGetOrInsertNamedMetaData, LLVMModuleRef, LLVMNamedMDRef) -_wrap_objstr2obj(LLVMModuleGetNamedMetaData, LLVMModuleRef, LLVMNamedMDRef) -_wrap_obj2obj(LLVMCloneModule, LLVMModuleRef, LLVMModuleRef) - -/*===----------------------------------------------------------------------===*/ -/* Types */ -/*===----------------------------------------------------------------------===*/ - -/*===-- General ----------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetTypeKind, LLVMTypeRef, int) -_wrap_dumper(LLVMDumpTypeToString, LLVMTypeRef) - -/*===-- Integer types ----------------------------------------------------===*/ - -_wrap_none2obj(LLVMInt1Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt8Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt16Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt32Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt64Type, LLVMTypeRef) -_wrap_int2obj(LLVMIntType, LLVMTypeRef) -_wrap_obj2obj(LLVMGetIntTypeWidth, LLVMTypeRef, int) - -/*===-- Floating-point types ---------------------------------------------===*/ - -_wrap_none2obj(LLVMFloatType, LLVMTypeRef) -_wrap_none2obj(LLVMDoubleType, LLVMTypeRef) -_wrap_none2obj(LLVMX86FP80Type, LLVMTypeRef) -_wrap_none2obj(LLVMFP128Type, LLVMTypeRef) -_wrap_none2obj(LLVMPPCFP128Type, LLVMTypeRef) - -/*===-- Function types ---------------------------------------------------===*/ - -_wrap_objlistint2obj(LLVMFunctionType, LLVMTypeRef, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMIsFunctionVarArg, LLVMTypeRef, int) -_wrap_obj2obj(LLVMGetReturnType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMCountParamTypes, LLVMTypeRef, int) - -/* The LLVMGetParamTypes and LLVMGetStructElementTypes functions both - * have the same signatures. The following implementation takes advantage - * of this. - */ - -typedef void (*obj2arr_fn_t)(LLVMTypeRef ty, LLVMTypeRef *outv); -typedef unsigned (*arrcnt_fn_t)(LLVMTypeRef ty); - -static PyObject * -obj2arr(PyObject *self, PyObject *args, arrcnt_fn_t cntfunc, obj2arr_fn_t arrfunc) -{ - size_t param_count; - - /* get the function object ptr */ - const LLVMTypeRef type = get_object_arg(args) ; - - /* get param count */ - param_count = cntfunc(type); - - /* alloc enough space for all of them */ - LLVMTypeRef* param_types = new LLVMTypeRef[param_count] ; - - /* call LLVM func */ - arrfunc(type, param_types); - - /* create a list from the array */ - PyObject *list = make_list(param_types, param_count); - - /* free temp storage */ - delete [] param_types ; - - return list; -} - -static PyObject * -_wLLVMGetFunctionTypeParams(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - return obj2arr(self, args, LLVMCountParamTypes, LLVMGetParamTypes); - LLVMPY_CATCH_ALL -} - -/*===-- Struct types -----------------------------------------------------===*/ - -_wrap_listint2obj(LLVMStructType, LLVMTypeRef, LLVMTypeRef) -_wrap_str2obj(LLVMStructTypeIdentified, LLVMTypeRef) -_wrap_objlistint2none(LLVMSetStructBody, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMCountStructElementTypes, LLVMTypeRef, int) -_wrap_obj2str(LLVMGetStructName, LLVMTypeRef) -_wrap_objstr2none(LLVMSetStructName, LLVMTypeRef) - - -static PyObject * -_wLLVMGetStructElementTypes(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - return obj2arr(self, args, LLVMCountStructElementTypes, - LLVMGetStructElementTypes); - LLVMPY_CATCH_ALL -} - - -_wrap_obj2obj(LLVMIsPackedStruct, LLVMTypeRef, int) -_wrap_obj2obj(LLVMIsOpaqueStruct, LLVMTypeRef, int) -_wrap_obj2obj(LLVMIsLiteralStruct, LLVMTypeRef, int) - -/*===-- Array types ------------------------------------------------------===*/ - -_wrap_objint2obj(LLVMArrayType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetElementType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetArrayLength, LLVMTypeRef, int) - -/*===-- Pointer types ----------------------------------------------------===*/ - -_wrap_objint2obj(LLVMPointerType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetPointerAddressSpace, LLVMTypeRef, int) - -/*===-- Vector type ------------------------------------------------------===*/ - -_wrap_objint2obj(LLVMVectorType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetVectorSize, LLVMTypeRef, int) - -/*===-- Other types ------------------------------------------------------===*/ - -_wrap_none2obj(LLVMVoidType, LLVMTypeRef) -_wrap_none2obj(LLVMLabelType, LLVMTypeRef) - -/*===-- Type handles -----------------------------------------------------===*/ - -/* -_wrap_obj2obj(LLVMCreateTypeHandle, LLVMTypeRef, LLVMTypeHandleRef) -_wrap_obj2obj(LLVMResolveTypeHandle, LLVMTypeHandleRef, LLVMTypeRef) -_wrap_obj2none(LLVMDisposeTypeHandle, LLVMTypeHandleRef) -*/ - - -/*===----------------------------------------------------------------------===*/ -/* Values */ -/*===----------------------------------------------------------------------===*/ - -/* Operations on all values */ - -_wrap_obj2obj(LLVMTypeOf, LLVMValueRef, LLVMTypeRef) -_wrap_obj2str(LLVMGetValueName, LLVMValueRef) -_wrap_objstr2none(LLVMSetValueName, LLVMValueRef) -_wrap_obj2none(LLVMDumpValue, LLVMValueRef) -_wrap_dumper(LLVMDumpValueToString, LLVMValueRef) -_wrap_obj2obj(LLVMValueGetID, LLVMValueRef, int) -_wrap_obj2obj(LLVMValueGetNumUses, LLVMValueRef, int) - -static PyObject * -_wLLVMValueGetUses(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMValueRef value = get_object_arg(args) ; - - LLVMValueRef *uses = 0; - size_t n = LLVMValueGetUses(value, &uses); - - PyObject *list = make_list(uses, n); - if (n > 0) - LLVMDisposeValueRefArray(uses); - - return list; - LLVMPY_CATCH_ALL -} - -/*===-- Users ------------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMUserGetNumOperands, LLVMValueRef, int) -_wrap_objint2obj(LLVMUserGetOperand, LLVMValueRef, LLVMValueRef) - -/*===-- Constant Values --------------------------------------------------===*/ - -/* Operations on constants of any type */ - -_wrap_obj2obj(LLVMConstNull, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstAllOnes, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetUndef, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMIsConstant, LLVMValueRef, int) -_wrap_obj2obj(LLVMIsNull, LLVMValueRef, int) -_wrap_obj2obj(LLVMIsUndef, LLVMValueRef, int) - -/* Operations on scalar constants */ - -static PyObject * -_wLLVMConstInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - unsigned PY_LONG_LONG n; - int sign_extend; - - if (!PyArg_ParseTuple(args, "OKi", &obj, &n, &sign_extend)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj ) ; - - const LLVMValueRef val = LLVMConstInt(ty, n, sign_extend); - - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMConstReal(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - double d; - - if (!PyArg_ParseTuple(args, "Od", &obj, &d)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj ) ; - - const LLVMValueRef val = LLVMConstReal(ty, d); - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -_wrap_objstr2obj(LLVMConstRealOfString, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstIntGetZExtValue, LLVMValueRef, llvmwrap_ull) -_wrap_obj2obj(LLVMConstIntGetSExtValue, LLVMValueRef, llvmwrap_ll) - -/* Operations on composite constants */ - -static PyObject * -_wLLVMConstString(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *s; - int dont_null_terminate; - - if (!PyArg_ParseTuple(args, "si:LLVMConstString", &s, &dont_null_terminate)) { - return NULL; - } - - LLVMValueRef val = LLVMConstString(s, strlen(s), dont_null_terminate); - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -_wrap_objlist2obj(LLVMConstArray, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_listint2obj(LLVMConstStruct, LLVMValueRef, LLVMValueRef) -_wrap_list2obj(LLVMConstVector, LLVMValueRef, LLVMValueRef) - -/* Constant expressions */ - -_wrap_obj2obj(LLVMGetConstExprOpcode, LLVMValueRef, int) -_wrap_obj2str(LLVMGetConstExprOpcodeName, LLVMValueRef) -_wrap_obj2obj(LLVMSizeOf, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstNeg, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstNot, LLVMValueRef, LLVMValueRef) - -_wrap_objobj2obj(LLVMConstAdd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFAdd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSub, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFSub, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstMul, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFMul, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstUDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstURem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSRem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFRem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstAnd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstOr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstXor, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_enumobjobj2obj(LLVMConstICmp, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_enumobjobj2obj(LLVMConstFCmp, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_objobj2obj(LLVMConstShl, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstLShr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstAShr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objlist2obj(LLVMConstGEP, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstTrunc, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstZExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPTrunc, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstUIToFP, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSIToFP, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPToUI, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPToSI, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstPtrToInt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstIntToPtr, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstBitCast, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstSelect, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstExtractElement, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstInsertElement, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstShuffleVector, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Globals */ -/*===----------------------------------------------------------------------===*/ - -/*===-- Globals ----------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetGlobalParent, LLVMValueRef, LLVMModuleRef) -_wrap_obj2obj(LLVMIsDeclaration, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetLinkage, LLVMValueRef, int) -_wrap_objenum2none(LLVMSetLinkage, LLVMValueRef, LLVMLinkage) -_wrap_obj2str(LLVMGetSection, LLVMValueRef) -_wrap_objstr2none(LLVMSetSection, LLVMValueRef) -_wrap_obj2obj(LLVMGetVisibility, LLVMValueRef, int) -_wrap_objenum2none(LLVMSetVisibility, LLVMValueRef, LLVMVisibility) -_wrap_obj2obj(LLVMGetAlignment, LLVMValueRef, int) -_wrap_objint2none(LLVMSetAlignment, LLVMValueRef) - -/*===-- Global Variables -------------------------------------------------===*/ - -_wrap_objobjstr2obj(LLVMAddGlobal, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjstrint2obj(LLVMAddGlobalInAddressSpace, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objstr2obj(LLVMGetNamedGlobal, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetFirstGlobal, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextGlobal, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMDeleteGlobal, LLVMValueRef) -_wrap_obj2obj(LLVMHasInitializer, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetInitializer, LLVMValueRef, LLVMValueRef) -_wrap_objobj2none(LLVMSetInitializer, LLVMValueRef, LLVMValueRef) -_wrap_objint2none(LLVMSetGlobalConstant, LLVMValueRef) -_wrap_obj2obj(LLVMIsGlobalConstant, LLVMValueRef, int) -_wrap_objint2none(LLVMSetThreadLocal, LLVMValueRef) -_wrap_obj2obj(LLVMIsThreadLocal, LLVMValueRef, int) - - -/*===-- Functions --------------------------------------------------------===*/ - -_wrap_objstrobj2obj(LLVMAddFunction, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objstr2obj(LLVMGetNamedFunction, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetFirstFunction, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextFunction, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMDeleteFunction, LLVMValueRef) -_wrap_obj2obj(LLVMGetIntrinsicID, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFunctionCallConv, LLVMValueRef, int) -_wrap_objint2none(LLVMSetFunctionCallConv, LLVMValueRef) -_wrap_obj2str(LLVMGetGC, LLVMValueRef) -_wrap_objstr2none(LLVMSetGC, LLVMValueRef) -_wrap_obj2obj(LLVMGetDoesNotThrow, LLVMValueRef, int) -_wrap_objint2none(LLVMSetDoesNotThrow, LLVMValueRef) -_wrap_obj2none(LLVMViewFunctionCFG, LLVMValueRef) -_wrap_obj2none(LLVMViewFunctionCFGOnly, LLVMValueRef) -_wrap_objenum2none(LLVMAddFunctionAttr, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMRemoveFunctionAttr, LLVMValueRef, LLVMAttribute) - -static PyObject * -_wLLVMVerifyFunction(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMValueRef fn = get_object_arg(args); - if (!fn) return NULL; - - return pycap_new(LLVMVerifyFunction(fn, LLVMReturnStatusAction)); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetFunctionFromInlineAsm(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *pycapFuncType; - const char *inlineAsm = NULL; - const char *constrains = NULL; - int hasSideEffect; - int isAlignStack; - int asmDialect; - - if (!PyArg_ParseTuple(args, "Ossiii", &pycapFuncType, &inlineAsm, - &constrains, &hasSideEffect, - &isAlignStack, &asmDialect)) - return NULL; - - - LLVMTypeRef funcType = pycap_get(pycapFuncType); - LLVMValueRef inlineAsmRef; - inlineAsmRef = LLVMGetFunctionFromInlineAsm(funcType, inlineAsm, constrains, - hasSideEffect, isAlignStack, - asmDialect); - - return pycap_new(inlineAsmRef); - LLVMPY_CATCH_ALL -} - - -/*===-- Arguments --------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMCountParams, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFirstParam, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextParam, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetParamParent, LLVMValueRef, LLVMValueRef) -_wrap_objenum2none(LLVMAddAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMRemoveAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMSetParamAlignment, LLVMValueRef, LLVMAttribute) -_wrap_obj2obj(LLVMGetParamAlignment, LLVMValueRef, int) - -/*===-- Basic Blocks -----------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetBasicBlockParent, LLVMBasicBlockRef, LLVMValueRef) -_wrap_obj2obj(LLVMCountBasicBlocks, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFirstBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetNextBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetEntryBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_objstr2obj(LLVMAppendBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_objstr2obj(LLVMInsertBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) -_wrap_obj2none(LLVMDeleteBasicBlock, LLVMBasicBlockRef) - - -/*===-- MetaData -----------------------------------------------------===*/ - -_wrap_objlist2obj(LLVMMetaDataGet, LLVMModuleRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrobj2none(LLVMAddNamedMetadataOperand, LLVMModuleRef, LLVMValueRef) -_wrap_objint2obj(LLVMMetaDataGetOperand, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMMetaDataGetNumOperands, LLVMValueRef, int) -_wrap_objstr2obj(LLVMMetaDataStringGet, LLVMModuleRef, LLVMValueRef) - -static PyObject * -_wLLVMGetNamedMetadataOperands(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_module; - const char *name; - - if (!PyArg_ParseTuple(args, "Os", &obj_module, &name)) - return NULL; - - LLVMModuleRef module = pycap_get(obj_module); - unsigned num_operands = LLVMGetNamedMetadataNumOperands(module, name); - LLVMValueRef *operands = new LLVMValueRef[num_operands]; - LLVMGetNamedMetadataOperands(module, name, operands); - - PyObject *list = make_list(operands, num_operands); - delete [] operands; - - return list; - LLVMPY_CATCH_ALL -} - - -/*===-- NamedMetaData -----------------------------------------------------===*/ - -_wrap_obj2str( LLVMNamedMetaDataGetName, LLVMNamedMDRef ) -_wrap_objobj2none( LLVMNamedMetaDataAddOperand, LLVMNamedMDRef, LLVMValueRef ) -_wrap_obj2none( LLVMEraseNamedMetaData, LLVMNamedMDRef ) -_wrap_dumper(LLVMDumpNamedMDToString, LLVMNamedMDRef) - -/*===-- Instructions -----------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetInstructionParent, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetFirstInstruction, LLVMBasicBlockRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextInstruction, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMInstIsTerminator, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsBinaryOp, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsCast, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsLogicalShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsArithmeticShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsAssociative, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsCommutative, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsVolatile, LLVMValueRef, int) -_wrap_objint2none(LLVMSetVolatile, LLVMValueRef) -_wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int) -_wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef) - -_wrap_objstrobj2none(LLVMInstSetMetaData, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMInstructionEraseFromParent, LLVMValueRef) - -/*===-- Call Sites (Call or Invoke) --------------------------------------===*/ - -_wrap_objint2none(LLVMSetInstructionCallConv, LLVMValueRef) -_wrap_obj2obj(LLVMGetInstructionCallConv, LLVMValueRef, int) -_wrap_objintenum2none(LLVMAddInstrAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objintenum2none(LLVMRemoveInstrAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objintint2none(LLVMSetInstrParamAlignment, LLVMValueRef) -_wrap_obj2obj(LLVMIsTailCall, LLVMValueRef, int) -_wrap_objint2none(LLVMSetTailCall, LLVMValueRef) -_wrap_obj2obj(LLVMInstGetCalledFunction, LLVMValueRef, LLVMValueRef) -_wrap_objobj2none(LLVMInstSetCalledFunction, LLVMValueRef, LLVMValueRef) - -/*===-- PHI Nodes --------------------------------------------------------===*/ - -static void LLVMAddIncoming1(LLVMValueRef PhiNode, LLVMValueRef IncomingValue, LLVMBasicBlockRef IncomingBlock) -{ - LLVMAddIncoming(PhiNode, &IncomingValue, &IncomingBlock, 1); -} - -_wrap_objobjobj2none(LLVMAddIncoming1, LLVMValueRef, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMCountIncoming, LLVMValueRef, int) -_wrap_objint2obj(LLVMGetIncomingValue, LLVMValueRef, LLVMValueRef) -_wrap_objint2obj(LLVMGetIncomingBlock, LLVMValueRef, LLVMBasicBlockRef) - -/*===-- Compare Instructions ---------------------------------------------===*/ - -_wrap_obj2obj(LLVMCmpInstGetPredicate, LLVMValueRef, int) - -/*===-- Instruction builders ----------------------------------------------===*/ - -_wrap_none2obj(LLVMCreateBuilder, LLVMBuilderRef) -_wrap_objobj2none(LLVMPositionBuilderBefore, LLVMBuilderRef, LLVMValueRef) -_wrap_objobj2none(LLVMPositionBuilderAtEnd, LLVMBuilderRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetInsertBlock, LLVMBuilderRef, LLVMBasicBlockRef) -_wrap_obj2none(LLVMDisposeBuilder, LLVMBuilderRef) - -/* Terminators */ - -_wrap_obj2obj(LLVMBuildRetVoid, LLVMBuilderRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildRet, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objlist2obj(LLVMBuildRetMultiple, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildBr, LLVMBuilderRef, LLVMBasicBlockRef, LLVMValueRef) -_wrap_objobjobjobj2obj(LLVMBuildCondBr, LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef, LLVMValueRef) -_wrap_objobjobjint2obj(LLVMBuildSwitch, LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMValueRef) - -static PyObject * -_wLLVMBuildInvoke(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1, *obj2, *obj3, *obj4, *obj5; - const char *name; - - if (!PyArg_ParseTuple(args, "OOOOOs:LLVMBuildInvoke", &obj1, &obj2, &obj3, &obj4, &obj5, &name)) { - return NULL; - } - - const LLVMBuilderRef builder = pycap_get( obj1); - const LLVMValueRef func = pycap_get( obj2 ) ; - - size_t fnarg_count = PyList_Size(obj3); - LLVMValueRef *fnargs - = make_array_from_list(obj3, fnarg_count); - - const LLVMBasicBlockRef then_blk = pycap_get ( obj4 ) ; - const LLVMBasicBlockRef catch_blk = pycap_get ( obj5 ) ; - - const LLVMValueRef inst - = LLVMBuildInvoke(builder, func, fnargs, fnarg_count, then_blk, - catch_blk, name); - - delete [] fnargs; - - return pycap_new(inst); - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMBuildUnreachable, LLVMBuilderRef, LLVMValueRef) - -/* Add a case to the switch instruction */ - -_wrap_objobjobj2none(LLVMAddCase, LLVMValueRef, LLVMValueRef, LLVMBasicBlockRef) - -/* Arithmetic */ - -_wrap_objobjobjstr2obj(LLVMBuildAdd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFAdd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSub, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFSub, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildMul, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFMul, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildUDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildURem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSRem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFRem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildShl, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildLShr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildAShr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildAnd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildOr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildXor, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildNeg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildNot, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) - -/* Memory */ - -_wrap_objobjstr2obj(LLVMBuildMalloc, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildArrayMalloc, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildAlloca, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildArrayAlloca, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildFree, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMBuildStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildGEP, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildInBoundsGEP, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - - -_wrap_objint2none(LLVMLdSetAlignment, LLVMValueRef) -_wrap_objint2none(LLVMStSetAlignment, LLVMValueRef) - -/* Casts */ - -_wrap_objobjobjstr2obj(LLVMBuildTrunc, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildZExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPToUI, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPToSI, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildUIToFP, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSIToFP, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPTrunc, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildPtrToInt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildIntToPtr, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildBitCast, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) - -/* Comparisons */ - -_wrap_objenumobjobjstr2obj(LLVMBuildICmp, LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/* Atomics */ -_wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjintstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjintstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef) - -/* Miscellaneous instructions */ - -_wrap_objobjintstr2obj(LLVMBuildGetResult, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjintstr2obj(LLVMBuildInsertValue, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildPhi, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildCall, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildSelect, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildVAArg, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildExtractElement, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildInsertElement, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildShuffleVector, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Memory Buffer */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateMemoryBufferWithContentsOfFile(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *path; - LLVMMemoryBufferRef ref; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s:LLVMCreateMemoryBufferWithContentsOfFile", &path)) { - return NULL; - } - - char *outmsg; - if (!LLVMCreateMemoryBufferWithContentsOfFile(path, &ref, &outmsg)) { - ret = pycap_new(ref); - } else { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateMemoryBufferWithSTDIN(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *ret; - LLVMMemoryBufferRef ref; - char *outmsg; - if (!LLVMCreateMemoryBufferWithSTDIN(&ref, &outmsg)) { - ret = pycap_new(ref); - } else { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } - - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeMemoryBuffer, LLVMMemoryBufferRef) - - -/*===----------------------------------------------------------------------===*/ -/* Pass Manager Builder */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2obj(LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderRef) -_wrap_obj2none(LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderRef) - -_wrap_objint2none(LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetOptLevel, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetSizeLevel, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetSizeLevel, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetVectorize, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetVectorize, LLVMPassManagerBuilderRef, int) - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -_wrap_objint2none(LLVMPassManagerBuilderSetLoopVectorize, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetLoopVectorize, LLVMPassManagerBuilderRef, int) -#endif //llvm-3.2 - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnitAtATime, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnitAtATime, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnrollLoops, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnrollLoops, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableSimplifyLibCalls, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableSimplifyLibCalls, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderUseInlinerWithThreshold, - LLVMPassManagerBuilderRef) - - -_wrap_objobj2none(LLVMPassManagerBuilderPopulateFunctionPassManager, - LLVMPassManagerBuilderRef, - LLVMPassManagerRef) - -_wrap_objobj2none(LLVMPassManagerBuilderPopulateModulePassManager, - LLVMPassManagerBuilderRef, - LLVMPassManagerRef) - - -/*===----------------------------------------------------------------------===*/ -/* Pass Manager */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2obj(LLVMCreatePassManager, LLVMPassManagerRef) -_wrap_obj2obj(LLVMCreateFunctionPassManagerForModule, LLVMModuleRef, LLVMPassManagerRef) -_wrap_objobj2obj(LLVMRunPassManager, LLVMPassManagerRef, LLVMModuleRef, int) -_wrap_obj2obj(LLVMInitializeFunctionPassManager, LLVMPassManagerRef, int) -_wrap_objobj2obj(LLVMRunFunctionPassManager, LLVMPassManagerRef, LLVMValueRef, int) -_wrap_obj2obj(LLVMFinalizeFunctionPassManager, LLVMPassManagerRef, int) -_wrap_obj2none(LLVMDisposePassManager, LLVMPassManagerRef) -_wrap_none2str(LLVMDumpPasses) -_wrap_objstr2obj(LLVMAddPassByName, LLVMPassManagerRef, int) - - -_wrap_objobj2none(LLVMAddPass, LLVMPassManagerRef, LLVMPassRef) -_wrap_none2none(LLVMInitializePasses) - -_wrap_none2obj(LLVMInitializeNativeTarget, int) -_wrap_none2obj(LLVMInitializeNativeTargetAsmPrinter, int) -#if !defined(LLVM_DISABLE_PTX) -# if LLVM_HAS_NVPTX -_wrap_none2none(LLVMInitializeNVPTXTarget) -_wrap_none2none(LLVMInitializeNVPTXTargetInfo) -_wrap_none2none( LLVMInitializeNVPTXTargetMC ) -_wrap_none2none(LLVMInitializeNVPTXAsmPrinter) -# else -_wrap_none2none(LLVMInitializePTXTarget) -_wrap_none2none(LLVMInitializePTXTargetInfo) -_wrap_none2none( LLVMInitializePTXTargetMC ) -_wrap_none2none(LLVMInitializePTXAsmPrinter) -# endif -#endif - -/*===----------------------------------------------------------------------===*/ -/* Passes */ -/*===----------------------------------------------------------------------===*/ - -_wrap_str2obj(LLVMCreatePassByName, LLVMPassRef) -_wrap_obj2none(LLVMDisposePass, LLVMPassRef) -_wrap_obj2str(LLVMGetPassName, LLVMPassRef) -_wrap_obj2none(LLVMPassDump, LLVMPassRef) - -_wrap_str2obj(LLVMCreateTargetLibraryInfo, LLVMPassRef) - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -_wrap_obj2obj(LLVMCreateTargetTransformInfo, LLVMTargetMachineRef, LLVMPassRef) -#endif - - -/*===----------------------------------------------------------------------===*/ -/* Target Machine */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2str(LLVMGetHostCPUName); - -_wrap_obj2obj(LLVMTargetMachineFromEngineBuilder, LLVMEngineBuilderRef, - LLVMTargetMachineRef) -_wrap_obj2none(LLVMDisposeTargetMachine, LLVMTargetMachineRef) - -static PyObject * -_wLLVMTargetMachineLookup(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - const char *triple; - const char *cpu; - const char *features; - int opt, codemodel; - - if (!PyArg_ParseTuple(args, "sssii", &triple, &cpu, &features, - &opt, &codemodel)) - return NULL; - - std::string error; - LLVMTargetMachineRef tm = LLVMTargetMachineLookup(triple, cpu, features, - opt, codemodel, error); - if(!error.empty()){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - return pycap_new(tm); - LLVMPY_CATCH_ALL -} - - -static PyObject * -_wLLVMCreateTargetMachine(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - const char *triple; - const char *cpu; - const char *features; - int opt, codemodel; - - if (!PyArg_ParseTuple(args, "sssii", &triple, &cpu, &features, - &opt, &codemodel)) - return NULL; - - std::string error; - LLVMTargetMachineRef tm = LLVMCreateTargetMachine(triple, cpu, features, - opt, codemodel, error); - if(!error.empty()){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - return pycap_new(tm); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - PyObject *arg_tm, *arg_m; - int arg_use_asm; - - if (!PyArg_ParseTuple(args, "OOi", &arg_tm, &arg_m, &arg_use_asm)) - return NULL; - - const LLVMTargetMachineRef tm - = pycap_get( arg_tm ) ; - const LLVMModuleRef m = pycap_get( arg_m ) ; - - std::string error; - size_t len; - unsigned const char * ubytes - = LLVMTargetMachineEmitFile(tm, m, arg_use_asm, &len, error); - if ( !error.empty() ){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - - const char *chars = reinterpret_cast(ubytes) ; - PyObject * ret = PyBytes_FromStringAndSize(chars, len); - delete [] ubytes; - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMTargetMachineGetTargetData, LLVMTargetMachineRef, - LLVMTargetDataRef) -_wrap_obj2str(LLVMTargetMachineGetTargetName, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetTargetShortDescription, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetTriple, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetCPU, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetFS, LLVMTargetMachineRef) -_wrap_none2none(LLVMPrintRegisteredTargetsForVersion) - - -/*===----------------------------------------------------------------------===*/ -/* Target Data */ -/*===----------------------------------------------------------------------===*/ - -_wrap_str2obj(LLVMCreateTargetData, LLVMTargetDataRef) -_wrap_obj2none(LLVMDisposeTargetData, LLVMTargetDataRef) - -static PyObject * -_wLLVMTargetDataAsString(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMTargetDataRef td = get_object_arg(args); - - char *tdrep = LLVMCopyStringRepOfTargetData(td); - PyObject *ret = PyUnicode_FromString(tdrep); - LLVMDisposeMessage(tdrep); - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_objobj2none(LLVMAddTargetData, LLVMTargetDataRef, LLVMPassManagerRef) -_wrap_obj2obj(LLVMByteOrder, LLVMTargetDataRef, int) -_wrap_obj2obj(LLVMPointerSize, LLVMTargetDataRef, int) -_wrap_obj2obj(LLVMIntPtrType, LLVMTargetDataRef, LLVMTypeRef) -_wrap_objobj2obj(LLVMSizeOfTypeInBits, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMStoreSizeOfType, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMABISizeOfType, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMABIAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMCallFrameAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMPreferredAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMPreferredAlignmentOfGlobal, LLVMTargetDataRef, - LLVMValueRef, int) -_wrap_objobjull2obj(LLVMElementAtOffset, LLVMTargetDataRef, LLVMTypeRef, int) -_wrap_objobjint2obj(LLVMOffsetOfElement, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) - - -/*===----------------------------------------------------------------------===*/ -/* Engine Builder */ -/*===----------------------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMCreateEngineBuilder, LLVMModuleRef, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMDisposeEngineBuilder, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMEngineBuilderForceJIT, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMEngineBuilderForceInterpreter, LLVMEngineBuilderRef) -_wrap_objint2none(LLVMEngineBuilderSetOptLevel, LLVMEngineBuilderRef) -_wrap_objstr2none(LLVMEngineBuilderSetMCPU, LLVMEngineBuilderRef) -_wrap_objstr2none(LLVMEngineBuilderSetMAttrs, LLVMEngineBuilderRef) - -static PyObject * -_wLLVMEngineBuilderCreate(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMEngineBuilderRef obj - = get_object_arg(args) ; - - std::string outmsg; - const LLVMExecutionEngineRef ee = LLVMEngineBuilderCreate(obj, outmsg); - - PyObject * ret; - if( !ee ){ // check if error message is set. - ret = PyUnicode_FromString(outmsg.c_str()); - }else{ - ret = pycap_new(ee); - } - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMEngineBuilderCreateTM(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj, *tm; - if (!PyArg_ParseTuple(args, "OO", &obj, &tm)) - return NULL; - - const LLVMEngineBuilderRef objref = pycap_get( obj ); - const LLVMTargetMachineRef tmref = pycap_get( tm ); - std::string outmsg; - - const LLVMExecutionEngineRef ee = LLVMEngineBuilderCreateTM(objref, tmref, - outmsg); - - PyObject * ret; - if( !ee ){ // check if error message is set. - ret = PyUnicode_FromString(outmsg.c_str()); - }else{ - ret = pycap_new(ee); - } - - return ret; - LLVMPY_CATCH_ALL -} - -/*===----------------------------------------------------------------------===*/ -/* Execution Engine */ -/*===----------------------------------------------------------------------===*/ - -// Use EngineBuilder -//static PyObject * -//_wLLVMCreateExecutionEngine(PyObject *self, PyObject *args) -//{ -// LLVMPY_TRY -// PyObject *obj; -// int force_interpreter; -// char *outmsg = 0; -// int error; -// -// if (!PyArg_ParseTuple(args, "Oi", &obj, &force_interpreter)) -// return NULL; -// -// const LLVMModuleRef mod = pycap_get( obj ) ; -// -// LLVMExecutionEngineRef ee; -// if (force_interpreter) -// error = LLVMCreateInterpreterForModule(&ee, mod, &outmsg); -// else -// error = LLVMCreateJITCompilerForModule(&ee, mod, 1 /*fast*/, &outmsg); -// -// PyObject *ret; -// if (error) { -// ret = PyUnicode_FromString(outmsg); -// LLVMDisposeMessage(outmsg); -// } else { -// ret = pycap_new(ee); -// } -// -// return ret; -// LLVMPY_CATCH_ALL -//} - -static PyObject * -_wLLVMGetPointerToFunction(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_fn; - - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_fn)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get(obj_ee ) ; - const LLVMValueRef fn = pycap_get( obj_fn ) ; - - return PyLong_FromVoidPtr(LLVMGetPointerToFunction(ee,fn)); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetPointerToGlobal(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_val; - - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_val)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ) ; - const LLVMValueRef val = pycap_get( obj_val ) ; - - return PyLong_FromVoidPtr(LLVMGetPointerToGlobal(ee, val)); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMAddGlobalMapping(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_val; - PyObject *obj_long; - void* address; - - if (!PyArg_ParseTuple(args, "OOO", &obj_ee, &obj_val, &obj_long)) - return NULL; - - address = PyLong_AsVoidPtr(obj_long); - if (PyErr_Occurred()) return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ); - const LLVMValueRef val = pycap_get( obj_val ); - - LLVMAddGlobalMapping(ee, val, address); - - Py_RETURN_NONE; - - LLVMPY_CATCH_ALL -} - -/* the args should have been ptr, num */ -LLVMGenericValueRef LLVMRunFunction2(LLVMExecutionEngineRef EE, - LLVMValueRef F, LLVMGenericValueRef *Args, unsigned NumArgs) -{ - return LLVMRunFunction(EE, F, NumArgs, Args); -} - -static PyObject * -_wLLVMRemoveModule2(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_mod; - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_mod)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ) ; - const LLVMModuleRef mod = pycap_get(obj_mod) ; - - char *outmsg = 0; - LLVMModuleRef mod_new = 0; - LLVMRemoveModule(ee, mod, &mod_new, &outmsg); - PyObject *ret; - if (mod_new) { - ret = pycap_new(mod_new); - } else { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = PyUnicode_FromString("error"); - } - } - - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeExecutionEngine, LLVMExecutionEngineRef) -_wrap_objint2none(LLVMExecutionEngineDisableLazyCompilation, - LLVMExecutionEngineRef) -_wrap_objobjlist2obj(LLVMRunFunction2, LLVMExecutionEngineRef, - LLVMValueRef, LLVMGenericValueRef, LLVMGenericValueRef) -_wrap_obj2obj(LLVMGetExecutionEngineTargetData, LLVMExecutionEngineRef, - LLVMTargetDataRef) -_wrap_obj2none(LLVMRunStaticConstructors, LLVMExecutionEngineRef) -_wrap_obj2none(LLVMRunStaticDestructors, LLVMExecutionEngineRef) -_wrap_objobj2none(LLVMFreeMachineCodeForFunction, LLVMExecutionEngineRef, - LLVMValueRef) -_wrap_objobj2none(LLVMAddModule, LLVMExecutionEngineRef, - LLVMModuleRef) - - -/*===----------------------------------------------------------------------===*/ -/* Generic Value */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateGenericValueOfInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - unsigned PY_LONG_LONG n; - int is_signed; - LLVMGenericValueRef gv; - - if (!PyArg_ParseTuple(args, "OKi", &obj1, &n, &is_signed)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - - gv = LLVMCreateGenericValueOfInt(ty, n, is_signed); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateGenericValueOfFloat(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - double d; - LLVMGenericValueRef gv; - - if (!PyArg_ParseTuple(args, "Od", &obj1, &d)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - - gv = LLVMCreateGenericValueOfFloat(ty, d); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateGenericValueOfPointer(PyObject *self, PyObject *args) -{ - LLVMPY_TRY -// PyObject *obj1; -// LLVMTypeRef ty; //unused? - unsigned PY_LONG_LONG n_; - size_t n; - - if (!PyArg_ParseTuple(args, "K", &n_)) - return NULL; - - n=n_; - - const LLVMGenericValueRef gv = LLVMCreateGenericValueOfPointer((void*)n); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - int is_signed; - unsigned PY_LONG_LONG val; - - if (!PyArg_ParseTuple(args, "Oi", &obj1, &is_signed)) - return NULL; - - LLVMGenericValueRef gv = pycap_get(obj1); - - val = LLVMGenericValueToInt(gv, is_signed); - return is_signed ? - PyLong_FromLongLong((PY_LONG_LONG)val) : - PyLong_FromUnsignedLongLong(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToFloat(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1, *obj2; - - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - const LLVMGenericValueRef gv = pycap_get( obj2 ) ; - - double val = LLVMGenericValueToFloat(ty, gv); - return PyFloat_FromDouble(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToPointer(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - - if (!PyArg_ParseTuple(args, "O", &obj1)) - return NULL; - - const LLVMGenericValueRef gv = pycap_get( obj1 ) ; - - void * val = LLVMGenericValueToPointer(gv); - return PyLong_FromVoidPtr(val); - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeGenericValue, LLVMGenericValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Misc */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMGetVersion(PyObject *self, PyObject *args) -{ - int major = LLVM_VERSION_MAJOR; - int minor = LLVM_VERSION_MINOR; - return Py_BuildValue("(i,i)", major, minor); -} - -_wrap_objintlist2obj(LLVMGetIntrinsic, LLVMModuleRef, LLVMTypeRef, - LLVMValueRef) - -static PyObject * -_wLLVMLoadLibraryPermanently(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *filename; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s:LLVMLoadLibraryPermanently", &filename)) { - return NULL; - } - - char *outmsg = 0; - if (!LLVMLoadLibraryPermanently(filename, &outmsg)) { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } - } - - /* note: success => None, failure => string with error message */ - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMParseEnvOpts(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char * progname; - const char * envname; - if(!PyArg_ParseTuple(args, "ss", &progname, &envname)) { - return NULL; - } - - llvm::cl::ParseEnvironmentOptions(progname, envname); - - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) - -_wrap_none2str(LLVMDefaultTargetTriple) - - -/* Expose the void* inside a PyCObject as a PyLong. This allows us to - * use it as a unique ID. */ -static PyObject * -_wPyCObjectVoidPtrToPyLong(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - void *p = get_object_arg(args); - return PyLong_FromVoidPtr(p); - LLVMPY_CATCH_ALL -} - - -/*===----------------------------------------------------------------------===*/ -/* Python member method table */ -/*===----------------------------------------------------------------------===*/ - -#define _method( func ) { # func , ( PyCFunction )_w ## func , METH_VARARGS , NULL }, -#define _pass( P ) _method( LLVMAdd ## P ## Pass ) - -static PyMethodDef core_methods[] = { - - /* Modules */ - _method( LLVMModuleCreateWithName ) - _method( LLVMGetDataLayout ) - _method( LLVMSetDataLayout ) - _method( LLVMGetModuleIdentifier ) - _method( LLVMSetModuleIdentifier ) - _method( LLVMGetTarget ) - _method( LLVMSetTarget ) - _method( LLVMModuleAddLibrary ) - _method( LLVMGetTypeByName ) - _method( LLVMDumpModule ) - _method( LLVMDisposeModule ) - _method( LLVMDumpModuleToString ) - _method( LLVMVerifyModule ) - _method( LLVMGetModuleFromAssembly ) - _method( LLVMGetModuleFromBitcode ) - _method( LLVMGetBitcodeFromModule ) - _method( LLVMGetNativeCodeFromModule ) - _method( LLVMModuleGetPointerSize ) - _method( LLVMModuleGetOrInsertFunction ) - _method( LLVMLinkModules ) - _method( LLVMModuleGetOrInsertNamedMetaData ) - _method( LLVMModuleGetNamedMetaData ) - _method( LLVMCloneModule ) - - /* Types */ - - /* General */ - _method( LLVMGetTypeKind ) - _method( LLVMDumpTypeToString ) - - /* Integer types */ - _method( LLVMInt1Type ) - _method( LLVMInt8Type ) - _method( LLVMInt16Type ) - _method( LLVMInt32Type ) - _method( LLVMInt64Type ) - _method( LLVMIntType ) - _method( LLVMGetIntTypeWidth ) - - /* Floating-point types */ - _method( LLVMFloatType ) - _method( LLVMDoubleType ) - _method( LLVMX86FP80Type ) - _method( LLVMFP128Type ) - _method( LLVMPPCFP128Type ) - - /* Function types */ - _method( LLVMFunctionType ) - _method( LLVMIsFunctionVarArg ) - _method( LLVMGetReturnType ) - _method( LLVMCountParamTypes ) - _method( LLVMGetFunctionTypeParams ) - - /* Struct types */ - _method( LLVMStructType ) - _method( LLVMStructTypeIdentified ) - _method( LLVMSetStructBody ) - _method( LLVMCountStructElementTypes ) - _method( LLVMGetStructElementTypes ) - _method( LLVMIsPackedStruct ) - _method( LLVMIsOpaqueStruct ) - _method( LLVMIsLiteralStruct ) - _method( LLVMGetStructName ) - _method( LLVMSetStructName ) - - /* Array types */ - _method( LLVMArrayType ) - _method( LLVMGetElementType ) - _method( LLVMGetArrayLength ) - - /* Pointer types */ - _method( LLVMPointerType ) - _method( LLVMGetPointerAddressSpace ) - - /* Vector type */ - _method( LLVMVectorType ) - _method( LLVMGetVectorSize ) - - /* Other types */ - _method( LLVMVoidType ) - _method( LLVMLabelType ) - - /* Type handles */ - /* - _method( LLVMResolveTypeHandle ) - _method( LLVMDisposeTypeHandle ) - */ - - /* Values */ - - /* Operations on all values */ - _method( LLVMTypeOf ) - _method( LLVMGetValueName ) - _method( LLVMSetValueName ) - _method( LLVMDumpValue ) - _method( LLVMDumpValueToString ) - _method( LLVMValueGetID ) - _method( LLVMValueGetNumUses ) - _method( LLVMValueGetUses ) - - /* Users */ - - _method( LLVMUserGetNumOperands ) - _method( LLVMUserGetOperand ) - - /* Constant Values */ - - /* Operations on constants of any type */ - _method( LLVMConstNull ) - _method( LLVMConstAllOnes ) - _method( LLVMGetUndef ) - _method( LLVMIsConstant ) - _method( LLVMIsNull ) - _method( LLVMIsUndef ) - - /* Operations on scalar constants */ - _method( LLVMConstInt ) - _method( LLVMConstReal ) - _method( LLVMConstRealOfString ) - _method( LLVMConstIntGetZExtValue ) - _method( LLVMConstIntGetSExtValue ) - - /* Operations on composite constants */ - _method( LLVMConstString ) - _method( LLVMConstArray ) - _method( LLVMConstStruct ) - _method( LLVMConstVector ) - - /* Constant expressions */ - _method( LLVMGetConstExprOpcode ) - _method( LLVMGetConstExprOpcodeName ) - _method( LLVMSizeOf ) - _method( LLVMConstNeg ) - _method( LLVMConstNot ) - _method( LLVMConstAdd ) - _method( LLVMConstFAdd ) - _method( LLVMConstSub ) - _method( LLVMConstFSub ) - _method( LLVMConstMul ) - _method( LLVMConstFMul ) - _method( LLVMConstUDiv ) - _method( LLVMConstSDiv ) - _method( LLVMConstFDiv ) - _method( LLVMConstURem ) - _method( LLVMConstSRem ) - _method( LLVMConstFRem ) - _method( LLVMConstAnd ) - _method( LLVMConstOr ) - _method( LLVMConstXor ) - _method( LLVMConstICmp ) - _method( LLVMConstFCmp ) - _method( LLVMConstShl ) - _method( LLVMConstLShr ) - _method( LLVMConstAShr ) - _method( LLVMConstGEP ) - _method( LLVMConstTrunc ) - _method( LLVMConstSExt ) - _method( LLVMConstZExt ) - _method( LLVMConstFPTrunc ) - _method( LLVMConstFPExt ) - _method( LLVMConstUIToFP ) - _method( LLVMConstSIToFP ) - _method( LLVMConstFPToUI ) - _method( LLVMConstFPToSI ) - _method( LLVMConstPtrToInt ) - _method( LLVMConstIntToPtr ) - _method( LLVMConstBitCast ) - _method( LLVMConstSelect ) - _method( LLVMConstExtractElement ) - _method( LLVMConstInsertElement ) - _method( LLVMConstShuffleVector ) - - /* Globals */ - - /* Globals (general) */ - _method( LLVMGetGlobalParent ) - _method( LLVMIsDeclaration ) - _method( LLVMGetLinkage ) - _method( LLVMSetLinkage ) - _method( LLVMGetSection ) - _method( LLVMSetSection ) - _method( LLVMGetVisibility ) - _method( LLVMSetVisibility ) - _method( LLVMGetAlignment ) - _method( LLVMSetAlignment ) - - /* Global Variables */ - _method( LLVMAddGlobal ) - _method( LLVMAddGlobalInAddressSpace ) - _method( LLVMGetNamedGlobal ) - _method( LLVMGetFirstGlobal ) - _method( LLVMGetNextGlobal ) - _method( LLVMDeleteGlobal ) - _method( LLVMHasInitializer ) - _method( LLVMGetInitializer ) - _method( LLVMSetInitializer ) - _method( LLVMSetThreadLocal ) - _method( LLVMIsThreadLocal ) - _method( LLVMSetGlobalConstant ) - _method( LLVMIsGlobalConstant ) - - /* Functions */ - _method( LLVMAddFunction ) - _method( LLVMGetNamedFunction ) - _method( LLVMGetFirstFunction ) - _method( LLVMGetNextFunction ) - _method( LLVMDeleteFunction ) - _method( LLVMGetIntrinsicID ) - _method( LLVMGetFunctionCallConv ) - _method( LLVMSetFunctionCallConv ) - _method( LLVMGetGC ) - _method( LLVMSetGC ) - _method( LLVMGetDoesNotThrow ) - _method( LLVMSetDoesNotThrow ) - _method( LLVMVerifyFunction ) - _method( LLVMViewFunctionCFG ) - _method( LLVMViewFunctionCFGOnly ) - _method( LLVMAddFunctionAttr ) - _method( LLVMRemoveFunctionAttr ) - _method( LLVMGetFunctionFromInlineAsm ) - - /* Arguments */ - _method( LLVMCountParams ) - _method( LLVMGetFirstParam ) - _method( LLVMGetNextParam ) - _method( LLVMGetParamParent ) - _method( LLVMAddAttribute ) - _method( LLVMRemoveAttribute ) - _method( LLVMSetParamAlignment ) - _method( LLVMGetParamAlignment ) - - /* Basic Blocks */ - _method( LLVMGetBasicBlockParent ) - _method( LLVMCountBasicBlocks ) - _method( LLVMGetFirstBasicBlock ) - _method( LLVMGetNextBasicBlock ) - _method( LLVMGetEntryBasicBlock ) - _method( LLVMAppendBasicBlock ) - _method( LLVMInsertBasicBlock ) - _method( LLVMDeleteBasicBlock ) - - /* MetaData */ - _method( LLVMMetaDataGet ) - _method( LLVMGetNamedMetadataOperands ) - _method( LLVMAddNamedMetadataOperand ) - _method( LLVMMetaDataGetOperand ) - _method( LLVMMetaDataGetNumOperands ) - _method( LLVMMetaDataStringGet ) - - /* NamedMetaData */ - _method( LLVMNamedMetaDataGetName ) - _method( LLVMNamedMetaDataAddOperand ) - _method( LLVMEraseNamedMetaData ) - _method( LLVMDumpNamedMDToString ) - - /* Instructions */ - _method( LLVMGetInstructionParent ) - _method( LLVMGetFirstInstruction ) - _method( LLVMGetNextInstruction ) - _method( LLVMInstIsTerminator ) - _method( LLVMInstIsBinaryOp ) - _method( LLVMInstIsShift ) - _method( LLVMInstIsCast ) - _method( LLVMInstIsLogicalShift ) - _method( LLVMInstIsArithmeticShift ) - _method( LLVMInstIsAssociative ) - _method( LLVMInstIsCommutative ) - _method( LLVMInstIsVolatile ) - _method( LLVMSetVolatile ) - _method( LLVMInstGetOpcode ) - _method( LLVMInstGetOpcodeName ) - - _method( LLVMInstSetMetaData ) - _method( LLVMInstructionEraseFromParent ) - - /* Call Sites (Call or Invoke) */ - _method( LLVMSetInstructionCallConv ) - _method( LLVMGetInstructionCallConv ) - _method( LLVMIsTailCall ) - _method( LLVMSetTailCall ) - _method( LLVMAddInstrAttribute ) - _method( LLVMRemoveInstrAttribute ) - _method( LLVMSetInstrParamAlignment ) - _method( LLVMInstGetCalledFunction ) - _method( LLVMInstSetCalledFunction ) - - /* PHI Nodes */ - _method( LLVMAddIncoming1 ) - _method( LLVMCountIncoming ) - _method( LLVMGetIncomingValue ) - _method( LLVMGetIncomingBlock ) - - /* Comparison Instructions */ - _method( LLVMCmpInstGetPredicate ) - - /* Instruction builders */ - _method( LLVMCreateBuilder ) - _method( LLVMPositionBuilderBefore ) - _method( LLVMPositionBuilderAtEnd ) - _method( LLVMGetInsertBlock ) - _method( LLVMDisposeBuilder ) - - /* Terminators */ - _method( LLVMBuildRetVoid ) - _method( LLVMBuildRet ) - _method( LLVMBuildRetMultiple ) - _method( LLVMBuildBr ) - _method( LLVMBuildCondBr ) - _method( LLVMBuildSwitch ) - _method( LLVMBuildInvoke ) - _method( LLVMBuildUnreachable ) - - /* Add a case to the switch instruction */ - _method( LLVMAddCase ) - - /* Arithmetic */ - _method( LLVMBuildAdd ) - _method( LLVMBuildFAdd) - _method( LLVMBuildSub ) - _method( LLVMBuildFSub) - _method( LLVMBuildMul ) - _method( LLVMBuildFMul) - _method( LLVMBuildUDiv ) - _method( LLVMBuildSDiv ) - _method( LLVMBuildFDiv ) - _method( LLVMBuildURem ) - _method( LLVMBuildSRem ) - _method( LLVMBuildFRem ) - _method( LLVMBuildShl ) - _method( LLVMBuildLShr ) - _method( LLVMBuildAShr ) - _method( LLVMBuildAnd ) - _method( LLVMBuildOr ) - _method( LLVMBuildXor ) - _method( LLVMBuildNeg ) - _method( LLVMBuildNot ) - - /* Memory */ - _method( LLVMBuildMalloc ) - _method( LLVMBuildArrayMalloc ) - _method( LLVMBuildAlloca ) - _method( LLVMBuildArrayAlloca ) - _method( LLVMBuildFree ) - _method( LLVMBuildLoad ) - _method( LLVMBuildStore ) - _method( LLVMBuildGEP ) - _method( LLVMBuildInBoundsGEP ) - - _method( LLVMLdSetAlignment ) - _method( LLVMStSetAlignment ) - - /* Casts */ - _method( LLVMBuildTrunc ) - _method( LLVMBuildZExt ) - _method( LLVMBuildSExt ) - _method( LLVMBuildFPToUI ) - _method( LLVMBuildFPToSI ) - _method( LLVMBuildUIToFP ) - _method( LLVMBuildSIToFP ) - _method( LLVMBuildFPTrunc ) - _method( LLVMBuildFPExt ) - _method( LLVMBuildPtrToInt ) - _method( LLVMBuildIntToPtr ) - _method( LLVMBuildBitCast ) - - /* Comparisons */ - _method( LLVMBuildICmp ) - _method( LLVMBuildFCmp ) - - /* Atomics */ - _method( LLVMBuildAtomicCmpXchg ) - _method( LLVMBuildAtomicRMW ) - _method( LLVMBuildAtomicLoad ) - _method( LLVMBuildAtomicStore ) - _method( LLVMBuildFence ) - - /* Miscellaneous instructions */ - _method( LLVMBuildGetResult ) - _method( LLVMBuildInsertValue ) - _method( LLVMBuildPhi ) - _method( LLVMBuildCall ) - _method( LLVMBuildSelect ) - _method( LLVMBuildVAArg ) - _method( LLVMBuildExtractElement ) - _method( LLVMBuildInsertElement ) - _method( LLVMBuildShuffleVector ) - - /* Memory Buffer */ - _method( LLVMCreateMemoryBufferWithContentsOfFile ) - _method( LLVMCreateMemoryBufferWithSTDIN ) - _method( LLVMDisposeMemoryBuffer ) - - /* Pass Manager Builder */ - - _method( LLVMPassManagerBuilderCreate ) - _method( LLVMPassManagerBuilderDispose ) - - _method( LLVMPassManagerBuilderSetOptLevel ) - _method( LLVMPassManagerBuilderGetOptLevel ) - - _method( LLVMPassManagerBuilderSetSizeLevel ) - _method( LLVMPassManagerBuilderGetSizeLevel ) - - _method( LLVMPassManagerBuilderSetVectorize ) - _method( LLVMPassManagerBuilderGetVectorize ) -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - _method( LLVMPassManagerBuilderSetLoopVectorize ) - _method( LLVMPassManagerBuilderGetLoopVectorize ) -#endif // llvm-3.2 - - _method( LLVMPassManagerBuilderSetDisableUnitAtATime ) - _method( LLVMPassManagerBuilderGetDisableUnitAtATime ) - - _method( LLVMPassManagerBuilderSetDisableUnrollLoops ) - _method( LLVMPassManagerBuilderGetDisableUnrollLoops ) - - _method( LLVMPassManagerBuilderSetDisableSimplifyLibCalls ) - _method( LLVMPassManagerBuilderGetDisableSimplifyLibCalls ) - - _method( LLVMPassManagerBuilderUseInlinerWithThreshold ) - - _method( LLVMPassManagerBuilderPopulateFunctionPassManager ) - _method( LLVMPassManagerBuilderPopulateModulePassManager ) - - /* Pass Manager */ - _method( LLVMCreatePassManager ) - _method( LLVMCreateFunctionPassManagerForModule ) - _method( LLVMRunPassManager ) - _method( LLVMInitializeFunctionPassManager ) - _method( LLVMRunFunctionPassManager ) - _method( LLVMFinalizeFunctionPassManager ) - _method( LLVMDisposePassManager ) - _method( LLVMDumpPasses ) - _method( LLVMAddPassByName ) - _method( LLVMAddPass ) - _method( LLVMInitializePasses ) - - _method( LLVMInitializeNativeTarget ) - _method( LLVMInitializeNativeTargetAsmPrinter ) -#if !defined(LLVM_DISABLE_PTX) -# if LLVM_HAS_NVPTX - _method( LLVMInitializeNVPTXTarget ) - _method( LLVMInitializeNVPTXTargetInfo ) - _method( LLVMInitializeNVPTXTargetMC ) - _method( LLVMInitializeNVPTXAsmPrinter ) -# else - _method( LLVMInitializePTXTarget ) - _method( LLVMInitializePTXTargetInfo ) - _method( LLVMInitializePTXTargetMC ) - _method( LLVMInitializePTXAsmPrinter ) -# endif -#endif - - /* Target Machine */ - _method( LLVMTargetMachineFromEngineBuilder ) - _method( LLVMDisposeTargetMachine ) - _method( LLVMCreateTargetMachine ) - _method( LLVMTargetMachineLookup ) - _method( LLVMTargetMachineEmitFile ) - _method( LLVMTargetMachineGetTargetData ) - _method( LLVMTargetMachineGetTargetName ) - _method( LLVMTargetMachineGetTargetShortDescription ) - _method( LLVMTargetMachineGetTriple ) - _method( LLVMTargetMachineGetCPU ) - _method( LLVMTargetMachineGetFS ) - - _method( LLVMPrintRegisteredTargetsForVersion ) - _method( LLVMGetHostCPUName ) - - /* Target Data */ - _method( LLVMCreateTargetData ) - _method( LLVMDisposeTargetData ) - _method( LLVMTargetDataAsString ) - _method( LLVMAddTargetData ) - _method( LLVMByteOrder ) - _method( LLVMPointerSize ) - _method( LLVMIntPtrType ) - _method( LLVMSizeOfTypeInBits ) - _method( LLVMStoreSizeOfType ) - _method( LLVMABISizeOfType ) - _method( LLVMABIAlignmentOfType ) - _method( LLVMCallFrameAlignmentOfType ) - _method( LLVMPreferredAlignmentOfType ) - _method( LLVMPreferredAlignmentOfGlobal ) - _method( LLVMElementAtOffset ) - _method( LLVMOffsetOfElement ) - - /* Engine Builder */ - - _method( LLVMCreateEngineBuilder ) - _method( LLVMDisposeEngineBuilder ) - _method( LLVMEngineBuilderForceJIT ) - _method( LLVMEngineBuilderForceInterpreter ) - _method( LLVMEngineBuilderSetOptLevel ) - _method( LLVMEngineBuilderSetMCPU ) - _method( LLVMEngineBuilderSetMAttrs ) - _method( LLVMEngineBuilderCreate ) - _method( LLVMEngineBuilderCreateTM ) - - /* Execution Engine */ -// Use EngineBuilder instead -// _method( LLVMCreateExecutionEngine ) - _method( LLVMDisposeExecutionEngine ) - _method( LLVMExecutionEngineDisableLazyCompilation ) - _method( LLVMRunFunction2 ) - _method( LLVMGetPointerToFunction ) - _method( LLVMGetPointerToGlobal ) - _method( LLVMAddGlobalMapping ) - _method( LLVMGetExecutionEngineTargetData ) - _method( LLVMRunStaticConstructors ) - _method( LLVMRunStaticDestructors ) - _method( LLVMFreeMachineCodeForFunction ) - _method( LLVMAddModule ) - _method( LLVMRemoveModule2 ) - - /* Generic Value */ - _method( LLVMCreateGenericValueOfInt ) - _method( LLVMCreateGenericValueOfFloat ) - _method( LLVMCreateGenericValueOfPointer ) - _method( LLVMGenericValueToInt ) - _method( LLVMGenericValueToFloat ) - _method( LLVMGenericValueToPointer ) - _method( LLVMDisposeGenericValue ) - - /* Passes */ - _method( LLVMCreatePassByName ) - _method( LLVMDisposePass ) - _method( LLVMGetPassName ) - _method( LLVMPassDump ) - - _method( LLVMCreateTargetLibraryInfo ) - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - _method( LLVMCreateTargetTransformInfo ) -#endif - - /* Misc */ - _method( LLVMGetVersion ) - _method( LLVMGetIntrinsic ) - _method( LLVMLoadLibraryPermanently ) - _method( LLVMParseEnvOpts ) - _method( LLVMDefaultTargetTriple ) - _method( LLVMInlineFunction ) - _method( PyCObjectVoidPtrToPyLong ) - { NULL } -}; - - - -// Module main function, hairy because of py3k port -extern "C" { - -#if (PY_MAJOR_VERSION >= 3) -struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "_core", - NULL, - -1, - core_methods, - NULL, NULL, NULL, NULL -}; -#define INITERROR return NULL -PyObject * -PyInit__core(void) -#else -#define INITERROR return -PyMODINIT_FUNC -init_core(void) -#endif -{ - LLVMLinkInJIT(); - LLVMLinkInInterpreter(); - LLVMInitializeNativeTarget(); -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create( &module_def ); -#else - PyObject *module = Py_InitModule("_core", core_methods); -#endif - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - - return module; -#endif -} - -} // end extern C diff --git a/llvm/_dwarf.cpp b/llvm/_dwarf.cpp deleted file mode 100644 index 43f75aa..0000000 --- a/llvm/_dwarf.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -namespace llvmpy { -namespace dwarf { - -using namespace llvm::dwarf; - -const char *constant_names[] = { - "LLVMDebugVersion", - - #define define(x) #x, - #include "_dwarf.h" - #undef define -}; - -int constant_values[] = { - llvm::LLVMDebugVersion, - - #define define(x) x, - #include "_dwarf.h" - #undef define -}; - -enum enum_values { - __llvmpy_LLVMDebugVersion, - - #define define(x) __llvmpy_##x, - #include "_dwarf.h" - #undef define - - NVALUES /* Get the number of constants */ -}; - -} // End namespace dwarf - -int -set_dwarf_constants(PyObject *module) -{ - int i; - for (i = 0; i < dwarf::NVALUES; i++) { - if (PyModule_AddIntConstant(module, dwarf::constant_names[i], - dwarf::constant_values[i]) > 0) - return -1; - } - - return 0; -} - -} // End namespace llvmpy - -#if (PY_MAJOR_VERSION >= 3) - struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "_dwarf", - NULL, - -1, - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ - }; - - #define INITERROR return NULL - PyObject *PyInit__dwarf(void) -#else - #define INITERROR return - PyMODINIT_FUNC init_dwarf(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create( &module_def ); -#else - PyObject *module = Py_InitModule("_dwarf", NULL); -#endif - if (module == NULL) - INITERROR; - - if (llvmpy::set_dwarf_constants(module) < 0) - INITERROR; - -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/llvm/_dwarf.h b/llvm/_dwarf.h deleted file mode 100644 index 78eada0..0000000 --- a/llvm/_dwarf.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Dwarf constant wrapping. See include/llvm/Support/Dwarf.h */ - -define(DWARF_VERSION) - -/* Dwarf tags */ -define(DW_TAG_array_type) -define(DW_TAG_class_type) -define(DW_TAG_entry_point) -define(DW_TAG_enumeration_type) -define(DW_TAG_formal_parameter) -define(DW_TAG_imported_declaration) -define(DW_TAG_label) -define(DW_TAG_lexical_block) -define(DW_TAG_member) -define(DW_TAG_pointer_type) -define(DW_TAG_reference_type) -define(DW_TAG_compile_unit) -define(DW_TAG_string_type) -define(DW_TAG_structure_type) -define(DW_TAG_subroutine_type) -define(DW_TAG_typedef) -define(DW_TAG_union_type) -define(DW_TAG_unspecified_parameters) -define(DW_TAG_variant) -define(DW_TAG_common_block) -define(DW_TAG_common_inclusion) -define(DW_TAG_inheritance) -define(DW_TAG_inlined_subroutine) -define(DW_TAG_module) -define(DW_TAG_ptr_to_member_type) -define(DW_TAG_set_type) -define(DW_TAG_subrange_type) -define(DW_TAG_with_stmt) -define(DW_TAG_access_declaration) -define(DW_TAG_base_type) -define(DW_TAG_catch_block) -define(DW_TAG_const_type) -define(DW_TAG_constant) -define(DW_TAG_enumerator) -define(DW_TAG_file_type) -define(DW_TAG_friend) -define(DW_TAG_namelist) -define(DW_TAG_namelist_item) -define(DW_TAG_packed_type) -define(DW_TAG_subprogram) -define(DW_TAG_template_type_parameter) -define(DW_TAG_template_value_parameter) -define(DW_TAG_thrown_type) -define(DW_TAG_try_block) -define(DW_TAG_variant_part) -define(DW_TAG_variable) -define(DW_TAG_volatile_type) -define(DW_TAG_dwarf_procedure) -define(DW_TAG_restrict_type) -define(DW_TAG_interface_type) -define(DW_TAG_namespace) -define(DW_TAG_imported_module) -define(DW_TAG_unspecified_type) -define(DW_TAG_partial_unit) -define(DW_TAG_imported_unit) -define(DW_TAG_condition) -define(DW_TAG_shared_type) -define(DW_TAG_type_unit) -define(DW_TAG_rvalue_reference_type) -define(DW_TAG_template_alias) -define(DW_TAG_MIPS_loop) -define(DW_TAG_format_label) -define(DW_TAG_function_template) -define(DW_TAG_class_template) -define(DW_TAG_GNU_template_template_param) -define(DW_TAG_GNU_template_parameter_pack) -define(DW_TAG_GNU_formal_parameter_pack) -define(DW_TAG_lo_user) -define(DW_TAG_APPLE_property) -define(DW_TAG_hi_user) - -/* Dwarf language constants */ -define(DW_LANG_C89) -define(DW_LANG_C) -define(DW_LANG_Ada83) -define(DW_LANG_C_plus_plus) -define(DW_LANG_Cobol74) -define(DW_LANG_Cobol85) -define(DW_LANG_Fortran77) -define(DW_LANG_Fortran90) -define(DW_LANG_Pascal83) -define(DW_LANG_Modula2) -define(DW_LANG_Java) -define(DW_LANG_C99) -define(DW_LANG_Ada95) -define(DW_LANG_Fortran95) -define(DW_LANG_PLI) -define(DW_LANG_ObjC) -define(DW_LANG_ObjC_plus_plus) -define(DW_LANG_UPC) -define(DW_LANG_D) -define(DW_LANG_Python) -define(DW_LANG_lo_user) -define(DW_LANG_Mips_Assembler) -define(DW_LANG_hi_user) - diff --git a/llvm/_util.py b/llvm/_util.py deleted file mode 100644 index da003b0..0000000 --- a/llvm/_util.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Utility functions and classes. - -Used only in other modules, not for public use.""" - -import llvm -import llvm._core as _core # for PyCObjectVoidPtrToPyLong - - -#===----------------------------------------------------------------------=== -# A set of helpers to check various things. Raises exceptions on -# failures. -#===----------------------------------------------------------------------=== - -def check_gen(obj, typ): - if not isinstance(obj, typ): - typ_str = typ.__name__ - msg = "argument not an instance of llvm.core.%s" % typ_str - raise TypeError(msg) - -def check_is_unowned(ownable): - if ownable.owner: - raise llvm.LLVMException("object is already owned") - - -#===----------------------------------------------------------------------=== -# A set of helpers to unpack a list of Python wrapper objects -# into a list of PyCObject wrapped objects, checking types along -# the way. -#===----------------------------------------------------------------------=== - -def unpack_gen(objlist, check_fn): - for obj in objlist: check_fn(obj) - return [ obj.ptr for obj in objlist ] - -def unpack_gen_allow_none(objlist, check_fn): - for obj in objlist: - if obj is not None: - check_fn(obj) - return [ (obj.ptr if obj is not None else None) for obj in objlist ] - -#===----------------------------------------------------------------------=== -# Helper to wrap over iterables (LLVMFirstXXX, LLVMNextXXX). This used -# to be a generator, but that loses subscriptability of the result, so -# we now return a list. -#===----------------------------------------------------------------------=== - -def wrapiter(first, next, container, wrapper): - ret = [] - ptr = first(container) - while ptr: - ret.append(wrapper(ptr)) - ptr = next(ptr) - return ret - - -#===----------------------------------------------------------------------=== -# Py2/3 compatibility string check -#===----------------------------------------------------------------------=== -def _isstring_py2(x): - return isinstance(x, basestring) - -def _isstring_py3(x): - return isinstance(x, str) - -def _isstring_choose(): - try: - basestring - return _isstring_py2 - except: - return _isstring_py3 - -isstring = _isstring_choose() - -try: - unicode_type = unicode -except NameError: # Py3 - unicode_type = str - diff --git a/llvm/_version.py b/llvm/_version.py deleted file mode 100644 index a90c5b8..0000000 --- a/llvm/_version.py +++ /dev/null @@ -1,193 +0,0 @@ - -IN_LONG_VERSION_PY = True -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by github's download-from-tag -# feature). Distribution tarballs (build by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.7+ (https://github.com/warner/python-versioneer) - -# these strings will be replaced by git during git-archive -git_refnames = "$Format:%d$" -git_full = "$Format:%H$" -GIT = "git" - -import subprocess -import sys - -def run_command(args, cwd=None, verbose=False): - try: - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) - except EnvironmentError: - e = sys.exc_info()[1] - if verbose: - print("unable to run %s" % args[0]) - print(e) - return None - stdout = p.communicate()[0].strip() - if sys.version >= '3': - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % args[0]) - return None - return stdout - - -import sys -import re -import os.path - -def get_expanded_variables(versionfile_source): - # the code embedded in _version.py can just fetch the value of these - # variables. When used from setup.py, we don't want to import - # _version.py, so we do it with a regexp instead. This function is not - # used from _version.py. - variables = {} - try: - for line in open(versionfile_source,"r").readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["full"] = mo.group(1) - except EnvironmentError: - pass - return variables - -def versions_from_expanded_variables(variables, tag_prefix, verbose=False): - refnames = variables["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("variables are unexpanded, not using") - return {} # unexpanded, so not in an unpacked git-archive tarball - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - for ref in list(refs): - if not re.search(r'\d', ref): - if verbose: - print("discarding '%s', no digits" % ref) - refs.discard(ref) - # Assume all version tags have a digit. git's %d expansion - # behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us - # distinguish between branches and tags. By ignoring refnames - # without digits, we filter out many common branch names like - # "release" and "stabilization", as well as "HEAD" and "master". - if verbose: - print("remaining refs: %s" % ",".join(sorted(refs))) - for ref in sorted(refs): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %s" % r) - return { "version": r, - "full": variables["full"].strip() } - # no suitable tags, so we use the full revision id - if verbose: - print("no suitable tags, using full revision id") - return { "version": variables["full"].strip(), - "full": variables["full"].strip() } - -def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): - # this runs 'git' from the root of the source tree. That either means - # someone ran a setup.py command (and this code is in versioneer.py, so - # IN_LONG_VERSION_PY=False, thus the containing directory is the root of - # the source tree), or someone ran a project-specific entry point (and - # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the - # containing directory is somewhere deeper in the source tree). This only - # gets called if the git-archive 'subst' variables were *not* expanded, - # and _version.py hasn't already been rewritten with a short version - # string, meaning we're inside a checked out source tree. - - try: - here = os.path.abspath(__file__) - except NameError: - # some py2exe/bbfreeze/non-CPython implementations don't do __file__ - return {} # not always correct - - # versionfile_source is the relative path from the top of the source tree - # (where the .git directory might live) to this file. Invert this to find - # the root from __file__. - root = here - if IN_LONG_VERSION_PY: - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - else: - root = os.path.dirname(here) - if not os.path.exists(os.path.join(root, ".git")): - if verbose: - print("no .git in %s" % root) - return {} - - stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], - cwd=root) - if stdout is None: - return {} - if not stdout.startswith(tag_prefix): - if verbose: - print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) - return {} - tag = stdout[len(tag_prefix):] - stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) - if stdout is None: - return {} - full = stdout.strip() - if tag.endswith("-dirty"): - full += "-dirty" - return {"version": tag, "full": full} - - -def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): - if IN_LONG_VERSION_PY: - # We're running from _version.py. If it's from a source tree - # (execute-in-place), we can work upwards to find the root of the - # tree, and then check the parent directory for a version string. If - # it's in an installed application, there's no hope. - try: - here = os.path.abspath(__file__) - except NameError: - # py2exe/bbfreeze/non-CPython don't have __file__ - return {} # without __file__, we have no hope - # versionfile_source is the relative path from the top of the source - # tree to _version.py. Invert this to find the root from __file__. - root = here - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - else: - # we're running from versioneer.py, which means we're running from - # the setup.py in a source tree. sys.argv[0] is setup.py in the root. - here = os.path.abspath(sys.argv[0]) - root = os.path.dirname(here) - - # Source tarballs conventionally unpack into a directory that includes - # both the project name and a version string. - dirname = os.path.basename(root) - if not dirname.startswith(parentdir_prefix): - if verbose: - print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % - (root, dirname, parentdir_prefix)) - return None - return {"version": dirname[len(parentdir_prefix):], "full": ""} - -tag_prefix = "" -parentdir_prefix = "llvmpy-" -versionfile_source = "llvm/_version.py" - -def get_versions(default={"version": "unknown", "full": ""}, verbose=False): - variables = { "refnames": git_refnames, "full": git_full } - ver = versions_from_expanded_variables(variables, tag_prefix, verbose) - if not ver: - ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) - if not ver: - ver = versions_from_parentdir(parentdir_prefix, versionfile_source, - verbose) - if not ver: - ver = default - return ver diff --git a/llvm/capsulethunk.h b/llvm/capsulethunk.h deleted file mode 100644 index 6b20564..0000000 --- a/llvm/capsulethunk.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef __CAPSULETHUNK_H -#define __CAPSULETHUNK_H - -#if ( (PY_VERSION_HEX < 0x02070000) \ - || ((PY_VERSION_HEX >= 0x03000000) \ - && (PY_VERSION_HEX < 0x03010000)) ) - -#define __PyCapsule_GetField(capsule, field, default_value) \ - ( PyCapsule_CheckExact(capsule) \ - ? (((PyCObject *)capsule)->field) \ - : (default_value) \ - ) \ - -#define __PyCapsule_SetField(capsule, field, value) \ - ( PyCapsule_CheckExact(capsule) \ - ? (((PyCObject *)capsule)->field = value), 1 \ - : 0 \ - ) \ - - -#define PyCapsule_Type PyCObject_Type - -#define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -#define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule)) - - -#define PyCapsule_New(pointer, name, destructor) \ - (PyCObject_FromVoidPtr(pointer, destructor)) - - -#define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) - -/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */ -#define PyCapsule_SetPointer(capsule, pointer) \ - __PyCapsule_SetField(capsule, cobject, pointer) - - -#define PyCapsule_GetDestructor(capsule) \ - __PyCapsule_GetField(capsule, destructor) - -#define PyCapsule_SetDestructor(capsule, dtor) \ - __PyCapsule_SetField(capsule, destructor, dtor) - - -/* - * Sorry, there's simply no place - * to store a Capsule "name" in a CObject. - */ -#define PyCapsule_GetName(capsule) NULL - -static int -PyCapsule_SetName(PyObject *capsule, const char *unused) -{ - unused = unused; - PyErr_SetString(PyExc_NotImplementedError, - "can't use PyCapsule_SetName with CObjects"); - return 1; -} - - - -#define PyCapsule_GetContext(capsule) \ - __PyCapsule_GetField(capsule, descr) - -#define PyCapsule_SetContext(capsule, context) \ - __PyCapsule_SetField(capsule, descr, context) - - -static void * -PyCapsule_Import(const char *name, int no_block) -{ - PyObject *object = NULL; - void *return_value = NULL; - char *trace; - size_t name_length = (strlen(name) + 1) * sizeof(char); - char *name_dup = (char *)PyMem_MALLOC(name_length); - - if (!name_dup) { - return NULL; - } - - memcpy(name_dup, name, name_length); - - trace = name_dup; - while (trace) { - char *dot = strchr(trace, '.'); - if (dot) { - *dot++ = '\0'; - } - - if (object == NULL) { - if (no_block) { - object = PyImport_ImportModuleNoBlock(trace); - } else { - object = PyImport_ImportModule(trace); - if (!object) { - PyErr_Format(PyExc_ImportError, - "PyCapsule_Import could not " - "import module \"%s\"", trace); - } - } - } else { - PyObject *object2 = PyObject_GetAttrString(object, trace); - Py_DECREF(object); - object = object2; - } - if (!object) { - goto EXIT; - } - - trace = dot; - } - - if (PyCObject_Check(object)) { - PyCObject *cobject = (PyCObject *)object; - return_value = cobject->cobject; - } else { - PyErr_Format(PyExc_AttributeError, - "PyCapsule_Import \"%s\" is not valid", - name); - } - -EXIT: - Py_XDECREF(object); - if (name_dup) { - PyMem_FREE(name_dup); - } - return return_value; -} - -#endif /* #if PY_VERSION_HEX < 0x02070000 */ - -#endif /* __CAPSULETHUNK_H */ diff --git a/llvm/core.py b/llvm/core.py index fa9dc77..0bf99fd 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1,43 +1,9 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Core classes of LLVM. - -The llvm.core module contains classes and constants required to build the -in-memory intermediate representation (IR) data structures.""" - - -import llvm # top-level, for common stuff -import llvm._core as _core # C wrappers -import llvm._util as _util # utility functions +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +import api #===----------------------------------------------------------------------=== # Enumerations @@ -276,72 +242,16 @@ ATTR_INLINE_HINT = 1<<25 ATTR_STACK_ALIGNMENT = 7<<26 ATTR_HOTPATCH = 1<<29 -# intrinsic IDs -from llvm._intrinsic_ids import * - - -#===----------------------------------------------------------------------=== -# Helpers (for internal use) -#===----------------------------------------------------------------------=== - -def check_is_type(obj): _util.check_gen(obj, Type) -def check_is_type_struct(obj): _util.check_gen(obj, StructType) -def check_is_value(obj): _util.check_gen(obj, Value) -def check_is_constant(obj): _util.check_gen(obj, Constant) -def check_is_function(obj): _util.check_gen(obj, Function) -def check_is_global_value(obj): _util.check_gen(obj, GlobalValue) -def check_is_basic_block(obj): _util.check_gen(obj, BasicBlock) -def check_is_module(obj): _util.check_gen(obj, Module) - -def unpack_types(objlst): return _util.unpack_gen(objlst, check_is_type) -def unpack_values(objlst): return _util.unpack_gen(objlst, check_is_value) -def unpack_constants(objlst): return _util.unpack_gen(objlst, check_is_constant) - -def unpack_values_or_none(objlst): - return _util.unpack_gen_allow_none(objlst, check_is_value) - -def check_is_callable(obj): - if isinstance(obj, Function): - return - typ = obj.type - if isinstance(typ, PointerType) and \ - isinstance(typ.pointee, FunctionType): - return - raise TypeError("argument is neither a function nor a function pointer") - -def _to_int(v): - if v: - return 1 - else: - return 0 - - -#===----------------------------------------------------------------------=== -# Module -#===----------------------------------------------------------------------=== - -class Module(llvm.Ownable, llvm.Cacheable): - """A Module instance stores all the information related to an LLVM module. - - Modules are the top level container of all other LLVM Intermediate - Representation (IR) objects. Each module directly contains a list of - globals variables, a list of functions, a list of libraries (or - other modules) this module depends on, a symbol table, and various - data about the target's characteristics. - - Construct a Module only using the static methods defined below, *NOT* - using the constructor. A correct usage is: - - module_obj = Module.new('my_module') - """ - +class Module(object): @staticmethod def new(id): """Create a new Module instance. Creates an instance of Module, having the id `id'. """ - return Module(_core.LLVMModuleCreateWithName(id)) + context = api.getGlobalContext() + m = api.Module.new(id, context) + return Module(m) @staticmethod def from_bitcode(fileobj_or_str): @@ -349,2049 +259,21 @@ class Module(llvm.Ownable, llvm.Cacheable): file. fileobj_or_str -- takes a file-like object or string that contains - a module represented in bitcode. + a module represented in bitcode. """ - - if isinstance(fileobj_or_str, _util.unicode_type): - data = fileobj_or_str.encode('utf-8') - elif isinstance(fileobj_or_str, bytes): - data = fileobj_or_str + if isinstance(fileobj_or_str, str): + bc = fileobj_or_str else: - data = fileobj_or_str.read() - ret = _core.LLVMGetModuleFromBitcode(data) - if not ret: - raise llvm.LLVMException("Unable to create module from bitcode") - elif _util.isstring(ret): - raise llvm.LLVMException(ret) - else: - return Module(ret) - - @staticmethod - def from_assembly(fileobj_or_str): - """Create a Module instance from the contents of an LLVM - assembly (.ll) file. - - - fileobj_or_str -- takes a file-like object or string that contains - a module represented in llvm-ir assembly. - """ - - if isinstance(fileobj_or_str, _util.unicode_type): - data = fileobj_or_str.encode('utf-8') - elif isinstance(fileobj_or_str, bytes): - data = fileobj_or_str - else: - data = fileobj_or_str.read() - if isinstance(data, _util.unicode_type): - data = data.encode() - ret = _core.LLVMGetModuleFromAssembly(data) - if not ret: - raise llvm.LLVMException("Unable to create module from assembly") - elif isinstance(ret, str): - raise llvm.LLVMException(ret) - else: - return Module(ret) - - def __init__(self, ptr): - """DO NOT CALL DIRECTLY. - - Use the static method `Module.new' instead. - """ - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule) - - def __str__(self): - """Text representation of a module. - - Returns the textual representation (`llvm assembly') of the - module. Use it like this: - - ll = str(module_obj) - print module_obj # same as `print ll' - """ - return _core.LLVMDumpModuleToString(self.ptr) - - def __eq__(self, rhs): - if isinstance(rhs, Module): - return str(self) == str(rhs) - else: - return False - - def __ne__(self, rhs): - return not self == rhs - - def _get_target(self): - return _core.LLVMGetTarget(self.ptr) - - def _set_target(self, value): - return _core.LLVMSetTarget(self.ptr, value) - - target = property(_get_target, _set_target, - """The target triple string describing the target host.""" - ) - - def _get_data_layout(self): - return _core.LLVMGetDataLayout(self.ptr) - - def _set_data_layout(self, value): - _core.LLVMSetDataLayout(self.ptr, value) - - data_layout = property(_get_data_layout, _set_data_layout, - """The data layout string for the module's target platform. - - The data layout strings is an encoded representation of - the type sizes and alignments expected by this module. - """ - ) - - @property - def pointer_size(self): - """Pointer size of target platform. - - Can be 0, 32 or 64. Zero represents - llvm::Module::AnyPointerSize.""" - return _core.LLVMModuleGetPointerSize(self.ptr) - - def link_in(self, other, preserve=False): - """Link the `other' module into this one. - - The `other' module is linked into this one such that types, - global variables, function, etc. are matched and resolved. - - The `other' module is no longer valid after this method is - invoked, all refs to it should be dropped. - - In the future, this API might be replaced with a full-fledged - Linker class. - """ - check_is_module(other) - if not preserve: - other.forget() # remove it from object cache - result = _core.LLVMLinkModules(self.ptr, other.ptr, int(bool(preserve))) - if result is not None: - raise llvm.LLVMException(result) - if not preserve: - # Prevent user from using the other module - other.ptr = None - # Use a dummy owner to prevent other.ptr to be deleted - other._own(llvm.DummyOwner()) - - def get_type_named(self, name): - """Return a Type object with the given name.""" - ptr = _core.LLVMGetTypeByName(self.ptr, name) - if ptr: - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - return None - - def add_global_variable(self, ty, name, addrspace=0): - """Add a global variable of given type with given name.""" - return GlobalVariable.new(self, ty, name, addrspace) - - def get_global_variable_named(self, name): - """Return a GlobalVariable object for the given name.""" - return GlobalVariable.get(self, name) - - @property - def global_variables(self): - """All global variables in this module.""" - return _util.wrapiter(_core.LLVMGetFirstGlobal, - _core.LLVMGetNextGlobal, self.ptr, _make_value) - - def add_function(self, ty, name): - """Add a function of given type with given name.""" - return Function.new(self, ty, name) - - def get_function_named(self, name): - """Return a Function object representing function with given name.""" - return Function.get(self, name) - - def get_or_insert_function(self, ty, name): - """Like get_function_named(), but does add_function() first, if - function is not present.""" - return Function.get_or_insert(self, ty, name) - - @property - def functions(self): - """All functions in this module.""" - return _util.wrapiter(_core.LLVMGetFirstFunction, - _core.LLVMGetNextFunction, self.ptr, _make_value) - - def verify(self): - """Verify module. - - Checks module for errors. Raises `llvm.LLVMException' on any - error.""" - ret = _core.LLVMVerifyModule(self.ptr) - # Note: LLVM has a bug in preverifier that will always abort - # the process upon failure. - if ret != "": - raise llvm.LLVMException(ret) - - def to_bitcode(self, fileobj=None): - """Write bitcode representation of module to given file-like - object. - - fileobj -- A file-like object to where the bitcode is written. - If it is None, the bitcode is returned. - - Return value -- Returns None if fileobj is not None. - Otherwise, return the bitcode as a bytestring. - """ - - data = _core.LLVMGetBitcodeFromModule(self.ptr) - if not data: - raise llvm.LLVMException("Unable to create bitcode") - if fileobj is not None: - fileobj.write(data) - else: - return data - - def add_library(self, name): - return _core.LLVMModuleAddLibrary(self.ptr, name) - - def _get_id(self): - return _core.LLVMGetModuleIdentifier(self.ptr) - - def _set_id(self, string): - _core.LLVMSetModuleIdentifier(self.ptr, string) - - id = property(_get_id, _set_id) - - def to_native_object(self, fileobj=None): - '''Outputs the byte string of the module as native object code - - If a fileobj is given, the output is written to it; - Otherwise, the output is returned - ''' - data = _core.LLVMGetNativeCodeFromModule(self.ptr, 0) - if fileobj is not None: - fileobj.write(data) - else: - return data - - def to_native_assembly(self, fileobj=None): - '''Outputs the byte string of the module as native assembly code - - If a fileobj is given, the output is written to it; - Otherwise, the output is returned - ''' - data = _core.LLVMGetNativeCodeFromModule(self.ptr, 1) - if fileobj is not None: - fileobj.write(data) - else: - return data - - def get_or_insert_named_metadata(self, name): - ptr = _core.LLVMModuleGetOrInsertNamedMetaData(self.ptr, name) - return NamedMetaData(ptr) - - def get_named_metadata(self, name): - ptr = _core.LLVMModuleGetNamedMetaData(self.ptr, name) - return NamedMetaData(ptr) - - def clone(self): - return Module(_core.LLVMCloneModule(self.ptr)) - -#===----------------------------------------------------------------------=== -# Types -#===----------------------------------------------------------------------=== - -class Type(object): - """Represents a type, like a 32-bit integer or an 80-bit x86 float. - - Use one of the static methods to create an instance. Example: - ty = Type.double() - """ - - @staticmethod - def int(bits=32): - """Create an integer type having the given bit width.""" - if bits == 1: - return _make_type(_core.LLVMInt1Type(), TYPE_INTEGER) - elif bits == 8: - return _make_type(_core.LLVMInt8Type(), TYPE_INTEGER) - elif bits == 16: - return _make_type(_core.LLVMInt16Type(), TYPE_INTEGER) - elif bits == 32: - return _make_type(_core.LLVMInt32Type(), TYPE_INTEGER) - elif bits == 64: - return _make_type(_core.LLVMInt64Type(), TYPE_INTEGER) - else: - bits = int(bits) # bits must be an int - return _make_type(_core.LLVMIntType(bits), TYPE_INTEGER) - - @staticmethod - def float(): - """Create a 32-bit floating point type.""" - return _make_type(_core.LLVMFloatType(), TYPE_FLOAT) - - @staticmethod - def double(): - """Create a 64-bit floating point type.""" - return _make_type(_core.LLVMDoubleType(), TYPE_DOUBLE) - - @staticmethod - def x86_fp80(): - """Create a 80-bit x86 floating point type.""" - return _make_type(_core.LLVMX86FP80Type(), TYPE_X86_FP80) - - @staticmethod - def fp128(): - """Create a 128-bit floating point type (with 112-bit - mantissa).""" - return _make_type(_core.LLVMFP128Type(), TYPE_FP128) - - @staticmethod - def ppc_fp128(): - """Create a 128-bit floating point type (two 64-bits).""" - return _make_type(_core.LLVMPPCFP128Type(), TYPE_PPC_FP128) - - @staticmethod - def function(return_ty, param_tys, var_arg=False): - """Create a function type. - - Creates a function type that returns a value of type - `return_ty', takes arguments of types as given in the iterable - `param_tys'. Set `var_arg' to True (default is False) for a - variadic function.""" - check_is_type(return_ty) - var_arg = _to_int(var_arg) # ensure int - params = unpack_types(param_tys) - return _make_type(_core.LLVMFunctionType(return_ty.ptr, params, - var_arg), TYPE_FUNCTION) - - @staticmethod - def opaque(name): - """Create a opaque StructType""" - if not name: - raise llvm.LLVMException("Must specify a name") - - objptr = _core.LLVMStructTypeIdentified(name) - return _make_type(objptr, TYPE_STRUCT) - - @staticmethod - def struct(element_tys, name=''): # not packed - """Create a (unpacked) structure type. - - Creates a structure type with elements of types as given in the - iterable `element_tys'. This method creates a unpacked - structure. For a packed one, use the packed_struct() method. - - If name is not '', creates a identified type; - otherwise, creates a literal type.""" - return Type.__struct(element_tys, packed=False, name=name) - - @staticmethod - def packed_struct(element_tys, name=''): - """Create a (packed) structure type. - - Creates a structure type with elements of types as given in the - iterable `element_tys'. This method creates a packed - structure. For an unpacked one, use the struct() method. - - If name is not '', creates a identified type; - otherwise, creates a literal type.""" - return Type.__struct(element_tys, packed=True, name=name) - - @staticmethod - def __struct(element_tys, packed, name): - elems = unpack_types(element_tys) - packed = int(bool(packed)) - - if name: # create Identified StructType - objptr = _core.LLVMStructTypeIdentified(name) - _core.LLVMSetStructBody(objptr, elems, packed) - else: # create Literal StructType - objptr = _core.LLVMStructType(elems, packed) - - return _make_type(objptr, TYPE_STRUCT) - - - @staticmethod - def array(element_ty, count): - """Create an array type. - - Creates a type for an array of elements of type `element_ty', - having 'count' elements.""" - check_is_type(element_ty) - count = int(count) # must be an int - return _make_type(_core.LLVMArrayType(element_ty.ptr, count), - TYPE_ARRAY) - - @staticmethod - def pointer(pointee_ty, addr_space=0): - """Create a pointer type. - - Creates a pointer type, which can point to values of type - `pointee_ty', in the address space `addr_space'.""" - check_is_type(pointee_ty) - addr_space = int(addr_space) # must be an int - return _make_type(_core.LLVMPointerType(pointee_ty.ptr, - addr_space), TYPE_POINTER) - - @staticmethod - def vector(element_ty, count): - """Create a vector type. - - Creates a type for a vector of elements of type `element_ty', - having `count' elements.""" - check_is_type(element_ty) - count = int(count) # must be an int - return _make_type(_core.LLVMVectorType(element_ty.ptr, count), - TYPE_VECTOR) - - @staticmethod - def void(): - """Create a void type. - - Represents the `void' type.""" - return _make_type(_core.LLVMVoidType(), TYPE_VOID) - - @staticmethod - def label(): - """Create a label type.""" - return _make_type(_core.LLVMLabelType(), TYPE_LABEL) - - def __init__(self, ptr, kind): - """DO NOT CALL DIRECTLY. - - Use one of the static methods instead.""" - self.ptr = ptr - self.kind = kind - """An enum (int) value denoting which type this is. - - Use the symbolic constants TYPE_* defined in llvm.core - module.""" - - def __str__(self): - """Text representation of a type. - - Returns the textual representation (`llvm assembly') of the type.""" - return _core.LLVMDumpTypeToString(self.ptr) - - def __eq__(self, rhs): - if isinstance(rhs, Type): - return str(self) == str(rhs) - else: - return False - - def __ne__(self, rhs): - return not self == rhs - - -class IntegerType(Type): - """Represents an integer type.""" - - @property - def width(self): - """The width of the integer type, in bits.""" - return _core.LLVMGetIntTypeWidth(self.ptr) - - -class FunctionType(Type): - """Represents a function type.""" - - @property - def return_type(self): - """The type of the value returned by this function.""" - ptr = _core.LLVMGetReturnType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def vararg(self): - """True if this function is variadic.""" - return _core.LLVMIsFunctionVarArg(self.ptr) != 0 - - @property - def args(self): - """An iterable that yields Type objects, representing the types of the - arguments accepted by this function, in order.""" - pp = _core.LLVMGetFunctionTypeParams(self.ptr) - return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] - - @property - def arg_count(self): - """Number of arguments accepted by this function. - - Same as len(obj.args), but faster.""" - return _core.LLVMCountParamTypes(self.ptr) - - -class StructType(Type): - """Represents a structure type.""" - - @property - def element_count(self): - """Number of elements (members) in the structure. - - Same as len(obj.elements), but faster.""" - return _core.LLVMCountStructElementTypes(self.ptr) - - @property - def elements(self): - """An iterable that yieldsd Type objects, representing the types of the - elements (members) of the structure, in order.""" - pp = _core.LLVMGetStructElementTypes(self.ptr) - return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] - - def set_body(self, elems, packed=False): - """Filled the body of a opaque type. - """ - # check - if not self.is_opaque: - raise llvm.LLVMException("Body is already defined.") - - # prepare arguments - elems = unpack_types(elems) - if packed: - packed = 1 - else: - packed = 0 - - # call c API - _core.LLVMSetStructBody(self.ptr, elems, packed) - - @property - def packed(self): - """True if the structure is packed, False otherwise.""" - return _core.LLVMIsPackedStruct(self.ptr) != 0 - - def _set_name(self, name): - _core.LLVMSetStructName(self.ptr, name) - - def _get_name(self): - return _core.LLVMGetStructName(self.ptr) - - name = property(_get_name, _set_name) - - @property - def is_literal(self): - return bool(_core.LLVMIsLiteralStruct(self.ptr)) - - @property - def is_identified(self): - return not _core.LLVMIsLiteralStruct(self.ptr) - - @property - def is_opaque(self): - return bool(_core.LLVMIsOpaqueStruct(self.ptr)) - -class ArrayType(Type): - """Represents an array type.""" - - @property - def element(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def count(self): - return _core.LLVMGetArrayLength(self.ptr) - - -class PointerType(Type): - - @property - def pointee(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def address_space(self): - return _core.LLVMGetPointerAddressSpace(self.ptr) - - -class VectorType(Type): - - @property - def element(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def count(self): - return _core.LLVMGetVectorSize(self.ptr) - - -#===----------------------------------------------------------------------=== -# Type factory method -#===----------------------------------------------------------------------=== - -# type ID -> class map -__class_for_typeid = { - TYPE_INTEGER : IntegerType, - TYPE_FUNCTION : FunctionType, - TYPE_STRUCT : StructType, - TYPE_ARRAY : ArrayType, - TYPE_POINTER : PointerType, - TYPE_VECTOR : VectorType, -} - -def _make_type(ptr, kind): - class_obj = __class_for_typeid.get(kind) - if class_obj: - return class_obj(ptr, kind) - else: - # "generic" type - return Type(ptr, kind) - - -#===----------------------------------------------------------------------=== -# Values -#===----------------------------------------------------------------------=== - -class Value(llvm.Cacheable): + bc = fileobj_or_str.read() + errbuf = StringIO() + m = api.ParseBitCodeFile(bc, context, errbuf) + if not m: + raise Exception(errbuf.getvalue()) + errbuf.close() + return Module(m) def __init__(self, ptr): self.ptr = ptr - def __str__(self): - return _core.LLVMDumpValueToString(self.ptr) - - def __eq__(self, rhs): - if isinstance(rhs, Value): - return str(self) == str(rhs) - else: - return False - - def __ne__(self, rhs): - return not self == rhs - - def _get_name(self): - return _core.LLVMGetValueName(self.ptr) - - def _set_name(self, value): - return _core.LLVMSetValueName(self.ptr, value) - - name = property(_get_name, _set_name) - - @property - def value_id(self): - return _core.LLVMValueGetID(self.ptr) - - @property - def type(self): - ptr = _core.LLVMTypeOf(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def use_count(self): - return _core.LLVMValueGetNumUses(self.ptr) - - @property - def uses(self): - return [ _make_value(v) for v in _core.LLVMValueGetUses(self.ptr) ] - - -class User(Value): - - @property - def operand_count(self): - return _core.LLVMUserGetNumOperands(self.ptr) - - @property - def operands(self): - """Yields operands of this instruction.""" - return [self._get_operand(i) for i in range(self.operand_count)] - - def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) - - -class Constant(User): - - @staticmethod - def null(ty): - check_is_type(ty) - return _make_value(_core.LLVMConstNull(ty.ptr)) - - @staticmethod - def all_ones(ty): - check_is_type(ty) - return _make_value(_core.LLVMConstAllOnes(ty.ptr)) - - @staticmethod - def undef(ty): - check_is_type(ty) - return _make_value(_core.LLVMGetUndef(ty.ptr)) - - @staticmethod - def int(ty, value): - check_is_type(ty) - return _make_value(_core.LLVMConstInt(ty.ptr, value, 0)) - - @staticmethod - def int_signextend(ty, value): - check_is_type(ty) - return _make_value(_core.LLVMConstInt(ty.ptr, value, 1)) - - @staticmethod - def real(ty, value): - check_is_type(ty) - if isinstance(value, str): - return _make_value(_core.LLVMConstRealOfString(ty.ptr, value)) - else: - return _make_value(_core.LLVMConstReal(ty.ptr, value)) - - @staticmethod - def string(strval): # dont_null_terminate=True - return _make_value(_core.LLVMConstString(strval, 1)) - - @staticmethod - def stringz(strval): # dont_null_terminate=False - return _make_value(_core.LLVMConstString(strval, 0)) - - @staticmethod - def array(ty, consts): - check_is_type(ty) - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstArray(ty.ptr, const_ptrs)) - - @staticmethod - def struct(consts): # not packed - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstStruct(const_ptrs, 0)) - - @staticmethod - def packed_struct(consts): - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstStruct(const_ptrs, 1)) - - @staticmethod - def vector(consts): - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstVector(const_ptrs)) - - @staticmethod - def sizeof(ty): - check_is_type(ty) - return _make_value(_core.LLVMSizeOf(ty.ptr)) - - def neg(self): - return _make_value(_core.LLVMConstNeg(self.ptr)) - - def not_(self): - return _make_value(_core.LLVMConstNot(self.ptr)) - - def add(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAdd(self.ptr, rhs.ptr)) - - def fadd(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFAdd(self.ptr, rhs.ptr)) - - def sub(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSub(self.ptr, rhs.ptr)) - - def fsub(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFSub(self.ptr, rhs.ptr)) - - def mul(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstMul(self.ptr, rhs.ptr)) - - def fmul(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFMul(self.ptr, rhs.ptr)) - - def udiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstUDiv(self.ptr, rhs.ptr)) - - def sdiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSDiv(self.ptr, rhs.ptr)) - - def fdiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFDiv(self.ptr, rhs.ptr)) - - def urem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstURem(self.ptr, rhs.ptr)) - - def srem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSRem(self.ptr, rhs.ptr)) - - def frem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFRem(self.ptr, rhs.ptr)) - - def and_(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAnd(self.ptr, rhs.ptr)) - - def or_(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstOr(self.ptr, rhs.ptr)) - - def xor(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstXor(self.ptr, rhs.ptr)) - - def icmp(self, int_pred, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstICmp(int_pred, self.ptr, rhs.ptr)) - - def fcmp(self, real_pred, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFCmp(real_pred, self.ptr, rhs.ptr)) - - def shl(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstShl(self.ptr, rhs.ptr)) - - def lshr(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstLShr(self.ptr, rhs.ptr)) - - def ashr(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAShr(self.ptr, rhs.ptr)) - - def gep(self, indices): - index_ptrs = unpack_constants(indices) - return _make_value(_core.LLVMConstGEP(self.ptr, index_ptrs)) - - def trunc(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstTrunc(self.ptr, ty.ptr)) - - def sext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstSExt(self.ptr, ty.ptr)) - - def zext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstZExt(self.ptr, ty.ptr)) - - def fptrunc(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPTrunc(self.ptr, ty.ptr)) - - def fpext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPExt(self.ptr, ty.ptr)) - - def uitofp(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstUIToFP(self.ptr, ty.ptr)) - - def sitofp(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstSIToFP(self.ptr, ty.ptr)) - - def fptoui(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPToUI(self.ptr, ty.ptr)) - - def fptosi(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPToSI(self.ptr, ty.ptr)) - - def ptrtoint(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstPtrToInt(self.ptr, ty.ptr)) - - def inttoptr(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstIntToPtr(self.ptr, ty.ptr)) - - def bitcast(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstBitCast(self.ptr, ty.ptr)) - - def select(self, true_const, false_const): - check_is_constant(true_const) - check_is_constant(false_const) - return _make_value( - _core.LLVMConstSelect(self.ptr, true_const.ptr, false_const.ptr)) - - def extract_element(self, index): # note: self must be a _vector_ constant - check_is_constant(index) - return _make_value( - _core.LLVMConstExtractElement(self.ptr, index.ptr)) - - def insert_element(self, value, index): - # note: self must be a _vector_ constant - check_is_constant(value) - check_is_constant(index) - return _make_value( - _core.LLVMConstInsertElement(self.ptr, value.ptr, index.ptr)) - - def shuffle_vector(self, vector_b, mask): - # note: self must be a _vector_ constant - check_is_constant(vector_b) - # note: vector_b must be a _vector_ constant - check_is_constant(mask) - return _make_value( - _core.LLVMConstShuffleVector(self.ptr, vector_b.ptr, mask.ptr)) - - -class ConstantExpr(Constant): - @property - def opcode(self): - return _core.LLVMGetConstExprOpcode(self.ptr) - - @property - def opcode_name(self): - return _core.LLVMGetConstExprOpcodeName(self.ptr) - - -class ConstantAggregateZero(Constant): - pass - - -class ConstantDataArray(Constant): - pass - - -class ConstantDataVector(Constant): - pass - -class ConstantInt(Constant): - @property - def z_ext_value(self): - '''Obtain the zero extended value for an integer constant value.''' - # Warning: assertion failure when value does not fit in 64 bits - return _core.LLVMConstIntGetZExtValue(self.ptr) - - @property - def s_ext_value(self): - '''Obtain the sign extended value for an integer constant value.''' - # Warning: assertion failure when value does not fit in 64 bits - return _core.LLVMConstIntGetSExtValue(self.ptr) - - -class ConstantFP(Constant): - pass - - -class ConstantArray(Constant): - pass - - -class ConstantStruct(Constant): - pass - - -class ConstantVector(Constant): - pass - - -class ConstantPointerNull(Constant): - pass - - -class UndefValue(Constant): - pass - - -class GlobalValue(Constant): - - def __init__(self, ptr): - Constant.__init__(self, ptr) - # Hang on to the module, don't let it die before we do. - # It is nice to have just a map of functions without - # retaining a ref to the owning module. - self._module_obj = self.module - - def _delete(self): - # Called in subclass delete() methods. - self._module_obj = None - - def _get_linkage(self): - return _core.LLVMGetLinkage(self.ptr) - def _set_linkage(self, value): - _core.LLVMSetLinkage(self.ptr, value) - linkage = property(_get_linkage, _set_linkage) - - def _get_section(self): - return _core.LLVMGetSection(self.ptr) - def _set_section(self, value): - return _core.LLVMSetSection(self.ptr, value) - section = property(_get_section, _set_section) - - def _get_visibility(self): - return _core.LLVMGetVisibility(self.ptr) - def _set_visibility(self, value): - return _core.LLVMSetVisibility(self.ptr, value) - visibility = property(_get_visibility, _set_visibility) - - def _get_alignment(self): - return _core.LLVMGetAlignment(self.ptr) - def _set_alignment(self, value): - return _core.LLVMSetAlignment(self.ptr, value) - alignment = property(_get_alignment, _set_alignment) - - @property - def is_declaration(self): - return _core.LLVMIsDeclaration(self.ptr) != 0 - - @property - def module(self): - return Module(_core.LLVMGetGlobalParent(self.ptr)) - -class GlobalVariable(GlobalValue): - - @staticmethod - def new(module, ty, name, addrspace=0): - check_is_module(module) - check_is_type(ty) - return _make_value(_core.LLVMAddGlobalInAddressSpace(module.ptr, ty.ptr, name, addrspace)) - - @staticmethod - def get(module, name): - check_is_module(module) - ptr = _core.LLVMGetNamedGlobal(module.ptr, name) - if not ptr: - raise llvm.LLVMException("no global named `%s`" % name) - return _make_value(ptr) - - def delete(self): - self._delete() - _core.LLVMDeleteGlobal(self.ptr) - self.forget() - self.ptr = None - - def _get_initializer(self): - if _core.LLVMHasInitializer(self.ptr): - return _make_value(_core.LLVMGetInitializer(self.ptr)) - else: - return None - - def _set_initializer(self, const): - check_is_constant(const) - _core.LLVMSetInitializer(self.ptr, const.ptr) - - def _del_initializer(self): - check_is_constant(const) - - initializer = property(_get_initializer, _set_initializer) - - def _get_is_global_constant(self): - return _core.LLVMIsGlobalConstant(self.ptr) - - def _set_is_global_constant(self, value): - value = _to_int(value) - _core.LLVMSetGlobalConstant(self.ptr, value) - - global_constant = \ - property(_get_is_global_constant, _set_is_global_constant) - - def _get_thread_local(self): - return bool(_core.LLVMIsThreadLocal(self.ptr)) - def _set_thread_local(self, value): - value = _to_int(value) - _core.LLVMSetThreadLocal(self.ptr, value) - - thread_local = property(_get_thread_local, _set_thread_local) - -class Argument(Value): - - def add_attribute(self, attr): - _core.LLVMAddAttribute(self.ptr, attr) - - def remove_attribute(self, attr): - _core.LLVMRemoveAttribute(self.ptr, attr) - - def _set_alignment(self, align): - _core.LLVMSetParamAlignment(self.ptr, align) - - def _get_alignment(self): - return _core.LLVMGetParamAlignment(self.ptr) - - alignment = \ - property(_get_alignment, _set_alignment) - - -class Function(GlobalValue): - - @staticmethod - def new(module, func_ty, name): - check_is_module(module) - check_is_type(func_ty) - return _make_value(_core.LLVMAddFunction(module.ptr, name, - func_ty.ptr)) - - @staticmethod - def get_or_insert(module, func_ty, name): - check_is_module(module) - check_is_type(func_ty) - return _make_value(_core.LLVMModuleGetOrInsertFunction(module.ptr, - name, func_ty.ptr)) - - @staticmethod - def get(module, name): - check_is_module(module) - ptr = _core.LLVMGetNamedFunction(module.ptr, name) - if not ptr: - raise llvm.LLVMException("no function named `%s`" % name) - return _make_value(ptr) - - @staticmethod - def intrinsic(module, intrinsic_id, types): - check_is_module(module) - ptrs = unpack_types(types) - return _make_value( - _core.LLVMGetIntrinsic(module.ptr, intrinsic_id, ptrs)) - - def delete(self): - self._delete() - _core.LLVMDeleteFunction(self.ptr) - self.forget() - self.ptr = None - - @property - def intrinsic_id(self): - return _core.LLVMGetIntrinsicID(self.ptr) - - def _get_cc(self): return _core.LLVMGetFunctionCallConv(self.ptr) - def _set_cc(self, value): _core.LLVMSetFunctionCallConv(self.ptr, value) - calling_convention = property(_get_cc, _set_cc) - - def _get_coll(self): return _core.LLVMGetGC(self.ptr) - def _set_coll(self, value): _core.LLVMSetGC(self.ptr, value) - collector = property(_get_coll, _set_coll) - - # the nounwind attribute: - def _get_does_not_throw(self): return _core.LLVMGetDoesNotThrow(self.ptr) - def _set_does_not_throw(self,value): _core.LLVMSetDoesNotThrow(self.ptr, value) - does_not_throw = property(_get_does_not_throw, _set_does_not_throw) - - @property - def args(self): - return _util.wrapiter(_core.LLVMGetFirstParam, - _core.LLVMGetNextParam, self.ptr, _make_value) - - @property - def basic_block_count(self): - return _core.LLVMCountBasicBlocks(self.ptr) - - @property - def entry_basic_block(self): - if self.basic_block_count == 0: - return None - return _make_value(_core.LLVMGetEntryBasicBlock(self.ptr)) - - def get_entry_basic_block(self): - """Deprecated, use entry_basic_block property.""" - return self.entry_basic_block - - def append_basic_block(self, name): - return _make_value(_core.LLVMAppendBasicBlock(self.ptr, name)) - - @property - def basic_blocks(self): - return _util.wrapiter(_core.LLVMGetFirstBasicBlock, - _core.LLVMGetNextBasicBlock, self.ptr, _make_value) - - def viewCFG(self): - return _core.LLVMViewFunctionCFG(self.ptr) - - def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self.ptr, attr) - - def remove_attribute(self, attr): - _core.LLVMRemoveFunctionAttr(self.ptr, attr) - - def viewCFGOnly(self): - return _core.LLVMViewFunctionCFGOnly(self.ptr) - - def verify(self): - # Although we're just asking LLVM to return the success or - # failure, it appears to print result to stderr and abort. - - # Note: LLVM has a bug in preverifier that will always abort - # the process upon failure. - return _core.LLVMVerifyFunction(self.ptr) != 0 - -#===----------------------------------------------------------------------=== -# InlineAsm -#===----------------------------------------------------------------------=== - -class InlineAsm(Value): - @staticmethod - def get(functype, asm, constrains, side_effect=False, - align_stack=False, dialect=0): - assert dialect == 0, "LLVM 3.1 does not implement dialect selection" - check_is_type(functype) - pycap = _core.LLVMGetFunctionFromInlineAsm(functype.ptr, asm, - constrains, int(side_effect), - int(align_stack), dialect) - return _make_value(pycap) - -#===----------------------------------------------------------------------=== -# MetaData -#===----------------------------------------------------------------------=== - -class MetaData(Value): - @staticmethod - def get(module, values): - ''' - values -- must be an iterable of Constant or None. None is treated as "null". - ''' - vs = unpack_values_or_none(values) - ptr = _core.LLVMMetaDataGet(module.ptr, vs) - return MetaData(ptr) - - @staticmethod - def get_named_operands(module, name): - lst = _core.LLVMGetNamedMetadataOperands(module.ptr, name) - return [MetaData(ptr) for ptr in lst] - - @staticmethod - def add_named_operand(module, name, operand): - _core.LLVMAddNamedMetadataOperand(module.ptr, name, operand.ptr) - - @property - def operand_count(self): - return _core.LLVMMetaDataGetNumOperands(self.ptr) - - @property - def operands(self): - """Yields operands of this metadata.""" - return [self._get_operand(i) for i in range(self.operand_count)] - - def _get_operand(self, i): - val = _core.LLVMMetaDataGetOperand(self.ptr, i) - if val: # metadata operands can be None - return _make_value(val) - -class MetaDataString(Value): - @staticmethod - def get(module, s): - ptr = _core.LLVMMetaDataStringGet(module.ptr, s) - return MetaDataString(ptr) - - @property - def string(self): - '''Same as MDString::getString''' - return self.name - -class NamedMetaData(llvm.Cacheable): - @staticmethod - def get_or_insert(mod, name): - return mod.get_or_insert_named_metadata(name) - - @staticmethod - def get(mod, name): - return mod.get_named_metadata(name) - - def __init__(self, ptr): - self.ptr = ptr - - def delete(self): - _core.LLVMEraseNamedMetaData(self.ptr) - - @property - def name(self): - return _core.LLVMNamedMetaDataGetName(self.ptr) - - def __str__(self): - return _core.LLVMDumpNamedMDToString(self.ptr) - - def add(self, operand): - _core.LLVMNamedMetaDataAddOperand(self.ptr, operand.ptr) - -#===----------------------------------------------------------------------=== -# Instruction -#===----------------------------------------------------------------------=== - -class Instruction(User): - - @property - def basic_block(self): - return _make_value(_core.LLVMGetInstructionParent(self.ptr)) - - @property - def is_terminator(self): - return _core.LLVMInstIsTerminator(self.ptr) != 0 - - @property - def is_binary_op(self): - return _core.LLVMInstIsBinaryOp(self.ptr) != 0 - - @property - def is_shift(self): - return _core.LLVMInstIsShift(self.ptr) != 0 - - @property - def is_cast(self): - return _core.LLVMInstIsCast(self.ptr) != 0 - - @property - def is_logical_shift(self): - return _core.LLVMInstIsLogicalShift(self.ptr) != 0 - - @property - def is_arithmetic_shift(self): - return _core.LLVMInstIsArithmeticShift(self.ptr) != 0 - - @property - def is_associative(self): - return _core.LLVMInstIsAssociative(self.ptr) != 0 - - @property - def is_commutative(self): - return _core.LLVMInstIsCommutative(self.ptr) != 0 - - @property - def is_volatile(self): - """True if this is a volatile load or store.""" - return _core.LLVMInstIsVolatile(self.ptr) != 0 - - def set_volatile(self, flag): - return _core.LLVMSetVolatile(self.ptr, int(bool(flag))) - - def set_metadata(self, kind, metadata): - return _core.LLVMInstSetMetaData(self.ptr, kind, metadata.ptr) - - @property - def opcode(self): - return _core.LLVMInstGetOpcode(self.ptr) - - @property - def opcode_name(self): - return _core.LLVMInstGetOpcodeName(self.ptr) - - def erase_from_parent(self): - return _core.LLVMInstructionEraseFromParent(self.ptr) - -class CallOrInvokeInstruction(Instruction): - - def _get_cc(self): return _core.LLVMGetInstructionCallConv(self.ptr) - def _set_cc(self, value): _core.LLVMSetInstructionCallConv(self.ptr, value) - calling_convention = property(_get_cc, _set_cc) - - def add_parameter_attribute(self, idx, attr): - _core.LLVMAddInstrAttribute(self.ptr, idx, attr) - - def remove_parameter_attribute(self, idx, attr): - _core.LLVMRemoveInstrAttribute(self.ptr, idx, attr) - - def set_parameter_alignment(self, idx, align): - _core.LLVMSetInstrParamAlignment(self.ptr, idx, align) - - def _get_called_function(self): - function = _core.LLVMInstGetCalledFunction(self.ptr) - if function: # Return value can be None on indirect call/invoke - return _make_value(function) - - def _set_called_function(self, function): - _core.LLVMInstSetCalledFunction(self.ptr, function.ptr) - - called_function = property(_get_called_function, _set_called_function) - - # tail call is valid only for 'call', not 'invoke' - # disabled for now - #def _get_tc(self): return _core.LLVMIsTailCall(self.ptr) - #def _set_tc(self, value): _core.LLVMSetTailCall(self.ptr, value) - #tail_call = property(_get_tc, _set_tc) - - -class PHINode(Instruction): - - @property - def incoming_count(self): - return _core.LLVMCountIncoming(self.ptr) - - def add_incoming(self, value, block): - check_is_value(value) - check_is_basic_block(block) - _core.LLVMAddIncoming1(self.ptr, value.ptr, block.ptr) - - def get_incoming_value(self, idx): - return _make_value(_core.LLVMGetIncomingValue(self.ptr, idx)) - - def get_incoming_block(self, idx): - return _make_value(_core.LLVMGetIncomingBlock(self.ptr, idx)) - - -class SwitchInstruction(Instruction): - - def add_case(self, const, bblk): - check_is_constant(const) # and has to be an int too - check_is_basic_block(bblk) - _core.LLVMAddCase(self.ptr, const.ptr, bblk.ptr) - - -class CompareInstruction(Instruction): - - @property - def predicate(self): - return _core.LLVMCmpInstGetPredicate(self.ptr) - - -#===----------------------------------------------------------------------=== -# Basic block -#===----------------------------------------------------------------------=== - -class BasicBlock(Value): - - def insert_before(self, name): - return _make_value(_core.LLVMInsertBasicBlock(self.ptr, name)) - - def delete(self): - _core.LLVMDeleteBasicBlock(self.ptr) - self.forget() - self.ptr = None - - @property - def function(self): - func_ptr = _core.LLVMGetBasicBlockParent(self.ptr) - return _make_value(func_ptr) - - @property - def instructions(self): - return _util.wrapiter(_core.LLVMGetFirstInstruction, - _core.LLVMGetNextInstruction, self.ptr, _make_value) - - -#===----------------------------------------------------------------------=== -# Value factory method -#===----------------------------------------------------------------------=== - -# value ID -> class map -__class_for_valueid = { - VALUE_ARGUMENT : Argument, - VALUE_BASIC_BLOCK : BasicBlock, - VALUE_FUNCTION : Function, - VALUE_GLOBAL_ALIAS : GlobalValue, - VALUE_GLOBAL_VARIABLE : GlobalVariable, - VALUE_UNDEF_VALUE : UndefValue, - VALUE_CONSTANT_EXPR : ConstantExpr, - VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, - VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, - VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, - VALUE_CONSTANT_INT : ConstantInt, - VALUE_CONSTANT_FP : ConstantFP, - VALUE_CONSTANT_ARRAY : ConstantArray, - VALUE_CONSTANT_STRUCT : ConstantStruct, - VALUE_CONSTANT_VECTOR : ConstantVector, - VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, - VALUE_MD_NODE : MetaData, - VALUE_MD_STRING : MetaDataString, - VALUE_INLINE_ASM : InlineAsm, - VALUE_INSTRUCTION + OPCODE_PHI : PHINode, - VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, - VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, - VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, - VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, - VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction -} - -def _make_value(ptr): - kind = _core.LLVMValueGetID(ptr) - # based on kind, create one of the Value subclasses - class_obj = __class_for_valueid.get(kind) - if class_obj: - return class_obj(ptr) - elif kind > VALUE_INSTRUCTION: - # "generic" instruction - return Instruction(ptr) - else: - # "generic" value - return Value(ptr) - - -#===----------------------------------------------------------------------=== -# Builder -#===----------------------------------------------------------------------=== - -class Builder(object): - - @staticmethod - def new(basic_block): - check_is_basic_block(basic_block) - b = Builder(_core.LLVMCreateBuilder()) - b.position_at_end(basic_block) - return b - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeBuilder(self.ptr) - - def position_at_beginning(self, bblk): - """Position the builder at the beginning of the given block. - - Next instruction inserted will be first one in the block.""" - check_is_basic_block(bblk) - # Avoids using "blk.instructions", which will fetch all the - # instructions into a list. Don't try this at home, though. - inst_ptr = _core.LLVMGetFirstInstruction(bblk.ptr) - if inst_ptr: - # Issue #10: inst_ptr can be None if b/b has no insts. - inst = _make_value(inst_ptr) - self.position_before(inst) - - def position_at_end(self, bblk): - """Position the builder at the end of the given block. - - Next instruction inserted will be last one in the block.""" - _core.LLVMPositionBuilderAtEnd(self.ptr, bblk.ptr) - - def position_before(self, instr): - """Position the builder before the given instruction. - - The instruction can belong to a basic block other than the - current one.""" - _core.LLVMPositionBuilderBefore(self.ptr, instr.ptr) - - @property - def block(self): - """Deprecated, use basic_block property instead.""" - return _make_value(_core.LLVMGetInsertBlock(self.ptr)) - - @property - def basic_block(self): - """The basic block where the builder is positioned.""" - return _make_value(_core.LLVMGetInsertBlock(self.ptr)) - - # terminator instructions - - def ret_void(self): - return _make_value(_core.LLVMBuildRetVoid(self.ptr)) - - def ret(self, value): - check_is_value(value) - return _make_value(_core.LLVMBuildRet(self.ptr, value.ptr)) - - def ret_many(self, values): - vs = unpack_values(values) - return _make_value(_core.LLVMBuildRetMultiple(self.ptr, vs)) - - def branch(self, bblk): - check_is_basic_block(bblk) - if __debug__: - for instr in self.basic_block.instructions: - assert not instr.is_terminator, "BasicBlock can only have one terminator" - return _make_value(_core.LLVMBuildBr(self.ptr, bblk.ptr)) - - def cbranch(self, if_value, then_blk, else_blk): - check_is_value(if_value) - check_is_basic_block(then_blk) - check_is_basic_block(else_blk) - return _make_value( - _core.LLVMBuildCondBr(self.ptr, - if_value.ptr, then_blk.ptr, else_blk.ptr)) - - def switch(self, value, else_blk, n=10): - check_is_value(value) # value has to be of any 'int' type - check_is_basic_block(else_blk) - return _make_value( - _core.LLVMBuildSwitch(self.ptr, value.ptr, else_blk.ptr, n)) - - def invoke(self, func, args, then_blk, catch_blk, name=""): - check_is_callable(func) - check_is_basic_block(then_blk) - check_is_basic_block(catch_blk) - args2 = unpack_values(args) - return _make_value( - _core.LLVMBuildInvoke(self.ptr, func.ptr, args2, - then_blk.ptr, catch_blk.ptr, name)) - - def unreachable(self): - return _make_value(_core.LLVMBuildUnreachable(self.ptr)) - - # arithmethic, bitwise and logical - - def add(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildAdd(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fadd(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFAdd(self.ptr, lhs.ptr, rhs.ptr, name)) - - def sub(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildSub(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fsub(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFSub(self.ptr, lhs.ptr, rhs.ptr, name)) - - def mul(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildMul(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fmul(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFMul(self.ptr, lhs.ptr, rhs.ptr, name)) - - def udiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildUDiv(self.ptr, lhs.ptr, rhs.ptr, name)) - - def sdiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildSDiv(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fdiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFDiv(self.ptr, lhs.ptr, rhs.ptr, name)) - - def urem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildURem(self.ptr, lhs.ptr, rhs.ptr, name)) - - def srem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildSRem(self.ptr, lhs.ptr, rhs.ptr, name)) - - def frem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFRem(self.ptr, lhs.ptr, rhs.ptr, name)) - - def shl(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildShl(self.ptr, lhs.ptr, rhs.ptr, name)) - - def lshr(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildLShr(self.ptr, lhs.ptr, rhs.ptr, name)) - - def ashr(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildAShr(self.ptr, lhs.ptr, rhs.ptr, name)) - - def and_(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildAnd(self.ptr, lhs.ptr, rhs.ptr, name)) - - def or_(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildOr(self.ptr, lhs.ptr, rhs.ptr, name)) - - def xor(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildXor(self.ptr, lhs.ptr, rhs.ptr, name)) - - def neg(self, val, name=""): - check_is_value(val) - return _make_value(_core.LLVMBuildNeg(self.ptr, val.ptr, name)) - - def not_(self, val, name=""): - check_is_value(val) - return _make_value(_core.LLVMBuildNot(self.ptr, val.ptr, name)) - - # memory - - def malloc(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildMalloc(self.ptr, ty.ptr, name)) - - def malloc_array(self, ty, size, name=""): - check_is_type(ty) - check_is_value(size) - return _make_value( - _core.LLVMBuildArrayMalloc(self.ptr, ty.ptr, size.ptr, name)) - - def alloca(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildAlloca(self.ptr, ty.ptr, name)) - - def alloca_array(self, ty, size, name=""): - check_is_type(ty) - check_is_value(size) - return _make_value( - _core.LLVMBuildArrayAlloca(self.ptr, ty.ptr, size.ptr, name)) - - def free(self, ptr): - check_is_value(ptr) - return _make_value(_core.LLVMBuildFree(self.ptr, ptr.ptr)) - - def load(self, ptr, name="", align=0, volatile=False, invariant=False): - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name)) - if align: - _core.LLVMLdSetAlignment(inst.ptr, align) - if volatile: - inst.set_volatile(volatile) - if invariant: - mod = self.basic_block.function.module - md = MetaData.get(mod, []) # empty metadata node - inst.set_metadata('invariant.load', md) - return inst - - def store(self, value, ptr, align=0, volatile=False): - check_is_value(value) - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr)) - if align: - _core.LLVMStSetAlignment(inst.ptr, align) - if volatile: - inst.set_volatile(volatile) - return inst - - def gep(self, ptr, indices, name="", inbounds=False): - check_is_value(ptr) - index_ptrs = unpack_values(indices) - if inbounds: - ret = _core.LLVMBuildInBoundsGEP(self.ptr, ptr.ptr, index_ptrs, name) - else: - ret = _core.LLVMBuildGEP(self.ptr, ptr.ptr, index_ptrs, name) - return _make_value(ret) - - # casts and extensions - - def trunc(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) - - def zext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildZExt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def sext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildSExt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fptoui(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPToUI(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fptosi(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPToSI(self.ptr, value.ptr, dest_ty.ptr, name)) - - def uitofp(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildUIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) - - def sitofp(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildSIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fptrunc(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fpext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPExt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def ptrtoint(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildPtrToInt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def inttoptr(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildIntToPtr(self.ptr, value.ptr, dest_ty.ptr, name)) - - def bitcast(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildBitCast(self.ptr, value.ptr, dest_ty.ptr, name)) - - # comparisons - - def icmp(self, ipred, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildICmp(self.ptr, ipred, lhs.ptr, rhs.ptr, name)) - - def fcmp(self, rpred, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFCmp(self.ptr, rpred, lhs.ptr, rhs.ptr, name)) - - # misc - - def extract_value(self, retval, idx, name=""): - check_is_value(retval) - return _make_value( - _core.LLVMBuildGetResult(self.ptr, retval.ptr, idx, name)) - - # obsolete synonym for extract_value - getresult = extract_value - - def insert_value(self, retval, rhs, idx, name=""): - check_is_value(retval) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildInsertValue(self.ptr, retval.ptr, rhs.ptr, idx, - name)) - - def phi(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildPhi(self.ptr, ty.ptr, name)) - - def call(self, fn, args, name=""): - check_is_callable(fn) - - err_template = 'Argument type mismatch: expected %s but got %s' - for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): - if t != v.type: - raise TypeError(err_template % (t, v.type)) - arg_ptrs = unpack_values(args) - return _make_value( - _core.LLVMBuildCall(self.ptr, fn.ptr, arg_ptrs, name)) - - def select(self, cond, then_value, else_value, name=""): - check_is_value(cond) - check_is_value(then_value) - check_is_value(else_value) - return _make_value( - _core.LLVMBuildSelect(self.ptr, cond.ptr, - then_value.ptr, else_value.ptr, name)) - - def vaarg(self, list_val, ty, name=""): - check_is_value(list_val) - check_is_type(ty) - return _make_value( - _core.LLVMBuildVAArg(self.ptr, list_val.ptr, ty.ptr, name)) - - def extract_element(self, vec_val, idx_val, name=""): - check_is_value(vec_val) - check_is_value(idx_val) - return _make_value( - _core.LLVMBuildExtractElement(self.ptr, vec_val.ptr, - idx_val.ptr, name)) - - def insert_element(self, vec_val, elt_val, idx_val, name=""): - check_is_value(vec_val) - check_is_value(elt_val) - check_is_value(idx_val) - return _make_value( - _core.LLVMBuildInsertElement(self.ptr, vec_val.ptr, - elt_val.ptr, idx_val.ptr, name)) - - def shuffle_vector(self, vecA, vecB, mask, name=""): - check_is_value(vecA) - check_is_value(vecB) - check_is_value(mask) - return _make_value( - _core.LLVMBuildShuffleVector(self.ptr, - vecA.ptr, vecB.ptr, mask.ptr, name)) - - # atomics - - def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): - check_is_value(ptr) - check_is_value(old) - check_is_value(new) - inst = _core.LLVMBuildAtomicCmpXchg(self.ptr, ptr.ptr, old.ptr, new.ptr, - ordering.lower(), - int(bool(crossthread))) - return _make_value(inst) - - def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): - check_is_value(ptr) - check_is_value(val) - inst = _core.LLVMBuildAtomicRMW(self.ptr, op.lower(), ptr.ptr, val.ptr, - ordering.lower(), int(bool(crossthread))) - return _make_value(inst) - - def atomic_xchg(self, *args, **kwargs): - return self.atomic_rmw('xchg', *args, **kwargs) - - def atomic_add(self, *args, **kwargs): - return self.atomic_rmw('add', *args, **kwargs) - - def atomic_sub(self, *args, **kwargs): - return self.atomic_rmw('sub', *args, **kwargs) - - def atomic_and(self, *args, **kwargs): - return self.atomic_rmw('and', *args, **kwargs) - - def atomic_nand(self, *args, **kwargs): - return self.atomic_rmw('nand', *args, **kwargs) - - def atomic_or(self, *args, **kwargs): - return self.atomic_rmw('or', *args, **kwargs) - - def atomic_xor(self, *args, **kwargs): - return self.atomic_rmw('xor', *args, **kwargs) - - def atomic_max(self, *args, **kwargs): - return self.atomic_rmw('max', *args, **kwargs) - - def atomic_min(self, *args, **kwargs): - return self.atomic_rmw('min', *args, **kwargs) - - def atomic_umax(self, *args, **kwargs): - return self.atomic_rmw('umax', *args, **kwargs) - - def atomic_umin(self, *args, **kwargs): - return self.atomic_rmw('umin', *args, **kwargs) - - - def atomic_load(self, ptr, ordering, align=1, crossthread=True, - volatile=False, name=""): - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildAtomicLoad( - self.ptr, ptr.ptr, int(align), - ordering.lower(), int(bool(crossthread)))) - if volatile: - inst.set_volatile(volatile) - if inst: - inst.name = name - return inst - - def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, - volatile=False): - check_is_value(value) - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildAtomicStore( - self.ptr, ptr.ptr, value.ptr, int(align), - ordering.lower(), int(bool(crossthread)))) - if volatile: - inst.set_volatile(volatile) - return inst - - def fence(self, ordering, crossthread=True): - inst = _make_value(_core.LLVMBuildFence(self.ptr, ordering.lower(), - int(bool(crossthread)))) - return inst - -#===----------------------------------------------------------------------=== -# Memory buffer -#===----------------------------------------------------------------------=== - -class MemoryBuffer(object): - - @staticmethod - def from_file(fname): - ret = _core.LLVMCreateMemoryBufferWithContentsOfFile(fname) - if isinstance(ret, str): - return (None, ret) - else: - obj = MemoryBuffer(ret) - return (obj, "") - - @staticmethod - def from_stdin(): - ret = _core.LLVMCreateMemoryBufferWithSTDIN() - if isinstance(ret, str): - return (None, ret) - else: - obj = MemoryBuffer(ret) - return (obj, "") - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeMemoryBuffer(self.ptr) - - -#===----------------------------------------------------------------------=== -# Misc -#===----------------------------------------------------------------------=== - -def load_library_permanently(filename): - """Load a shared library. - - Load the given shared library (filename argument specifies the full - path of the .so file) using LLVM. Symbols from these are available - from the execution engine thereafter.""" - - ret = _core.LLVMLoadLibraryPermanently(filename) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - -def inline_function(call): - check_is_value(call) - return bool(_core.LLVMInlineFunction(call.ptr)) - -def parse_environment_options(progname, envname): - _core.LLVMParseEnvOpts(progname, envname) - -#===----------------------------------------------------------------------=== -# Initialization -#===----------------------------------------------------------------------=== -if _core.LLVMInitializeNativeTarget(): - raise llvm.LLVMException("No native target!?") -if _core.LLVMInitializeNativeTargetAsmPrinter(): - # should this be an optional feature? - # should user trigger the initialization? - raise llvm.LLVMException("No native asm printer!?") - - -HAS_PTX = HAS_NVPTX = False -if True: # use PTX? - try: - _core.LLVMInitializePTXTarget() - _core.LLVMInitializePTXTargetInfo() - _core.LLVMInitializePTXTargetMC() - _core.LLVMInitializePTXAsmPrinter() - HAS_PTX = True - except AttributeError: - try: - _core.LLVMInitializeNVPTXTarget() - _core.LLVMInitializeNVPTXTargetInfo() - _core.LLVMInitializeNVPTXTargetMC() - _core.LLVMInitializeNVPTXAsmPrinter() - HAS_NVPTX = True - except AttributeError: - pass - + \ No newline at end of file diff --git a/llvm/debuginfo.py b/llvm/debuginfo.py deleted file mode 100644 index 0f18b33..0000000 --- a/llvm/debuginfo.py +++ /dev/null @@ -1,398 +0,0 @@ -""" -Support for debug info metadata. -""" - -import functools - -import llvm.core -from llvm import _dwarf - -#---------------------------------------------------------------------------- -# Some types and type checking functions -#---------------------------------------------------------------------------- - -int32_t = llvm.core.Type.int(32) -bool_t = llvm.core.Type.int(1) -p_int32_t = llvm.core.Type.pointer(int32_t) -null = llvm.core.Constant.null(p_int32_t) - -i32 = functools.partial(llvm.core.Constant.int, int32_t) -i1 = functools.partial(llvm.core.Constant.int, bool_t) - -def is_md(value): - return isinstance(value, (llvm.core.MetaData, llvm.core.NamedMetaData, - llvm.core.Value)) - -def is_mdstr(value): - return isinstance(value, (llvm.core.MetaDataString, llvm.core.Value)) - -#---------------------------------------------------------------------------- -# Callbacks for debug type descriptors -#---------------------------------------------------------------------------- - -def get_i32(llvm_module, value): - return i32(value) - -def get_i1(llvm_module, value): - return i1(value) - -def get_md(llvm_module, value): - if is_md(value): - return value - return value.get_metadata(llvm_module) - -def get_mdstr(llvm_module, value): - if is_mdstr(value): - return value - return llvm.core.MetaDataString.get(llvm_module, value) - -def get_mdlist(llvm_module, value): - if isinstance(value, list): - value = MDList([value]) - return get_md(llvm_module, value) - -def get_lfunc(llvm_module, lfunc): - assert lfunc.module is llvm_module - return lfunc - -#---------------------------------------------------------------------------- -# Debug descriptors that generate LLVM Metadata -#---------------------------------------------------------------------------- - -class desc(object): - """ - Descriptor of a debug field. - - field_name: - name of the field (keyword argument name) - build_metadata: - metadata callback :: (llvm_module, Python value) -> LLVM Value - default: - default value for this field - """ - - def __init__(self, field_name, build_metadata, default=None): - self.field_name = field_name - self.build_metadata = build_metadata - self.default = default - - -def build_operand_list(type_descriptors, idx2name, operands, kwargs): - """ - Build the list of operands from the positional and keyword arguments - to a DebugInfoDescriptor. - - E.g. FileDescriptor("foo.c", "/path/to/file", compile_unit=compile_unit) - - idx2name: {0 : 'source_filename', - 1 : 'source_filedir', - 2 : 'compile_unit' } - operands: ["foo.c", "/path/to/file"] - kwargs: { 'compile_unit' : compile_unit } - """ - for i in range(len(operands), len(type_descriptors)): - name = idx2name[i] - if name in kwargs: - op = kwargs[name] - else: - typedesc = type_descriptors[i] - assert typedesc.default is not None, ( - "No value found for field %s" % typedesc.field_name) - op = typedesc.default - - operands.append(op) - - return operands - - -class DebugInfoDescriptor(object): - """ - Base class to describe a debug info descriptor. - - See http://llvm.org/docs/SourceLevelDebugging.html - """ - - type_descriptors = None # [desc(...)] - idx2name = None # { "field_idx" : field_name } - name2idx = None # { "field_name" : field_idx } - - # Whether the debug descriptor is allowed to be incomplete - # The policy seems unclear ? - accept_optional_data = False - - def __init__(self, *args, **kwargs): - self.class_init() - self.metadata_cache = {} - - operands = list(args) - if kwargs or not self.accept_optional_data: - operands = build_operand_list(self.type_descriptors, - self.idx2name, operands, kwargs) - - self.operands = operands - self.operands_dict = dict( - (typedesc.field_name, operand) - for typedesc, operand in zip(self.type_descriptors, operands)) - - @classmethod - def class_init(cls): - if cls.idx2name is None and cls.type_descriptors is not None: - cls.name2idx = {} - cls.idx2name = {} - - for i, typedesc in enumerate(cls.type_descriptors): - cls.name2idx[typedesc.field_name] = i - cls.idx2name[i] = typedesc.field_name - - def add_metadata(self, metadata_name, metadata): - """ - Replace a metadata value in the operand list. - """ - idx = self.name2idx[metadata_name] - self.operands[idx] = metadata - - #------------------------------------------------------------------------ - # Define metadata in a module - #------------------------------------------------------------------------ - - def get_metadata(self, llvm_module): - """ - Get an existing metadata node for the given LLVM module, or build - one from this instance. - """ - if llvm_module in self.metadata_cache: - node = self.metadata_cache[llvm_module] - else: - node = self.build_metadata(llvm_module) - self.metadata_cache[llvm_module] = node - - return node - - def build_metadata(self, llvm_module): - "Build a metadata node for the given LLVM module" - mdops = [] - for type_desc, operand in zip(self.type_descriptors, self.operands): - try: - field_value = type_desc.build_metadata(llvm_module, operand) - except Exception, e: - if type_desc.build_metadata is get_md: - raise - - raise ValueError("Invalid value for field %r: %s" % ( - type_desc.field_name, e)) - - mdops.append(field_value) - - return llvm.core.MetaData.get(llvm_module, mdops) - - def define(self, llvm_module): - """ - Define this debug descriptor as named debug metadata for the module. - """ - md = self.get_metadata(llvm_module) - llvm.core.MetaData.add_named_operand(llvm_module, "dbg", md) - -#---------------------------------------------------------------------------- -# Convenience descriptors -#---------------------------------------------------------------------------- - -class MDList(DebugInfoDescriptor): - """ - [MetaData] - """ - - def __init__(self, operands): - self.type_descriptors = [desc("op", get_md)] * len(operands) - super(MDList, self).__init__(*operands) - -empty = MDList([]) - -#---------------------------------------------------------------------------- -# Dwarf Debug descriptors -#---------------------------------------------------------------------------- - -class CompileUnitDescriptor(DebugInfoDescriptor): - """ - !0 = metadata !{ - i32, ;; Tag = 17 + LLVMDebugVersion (DW_TAG_compile_unit) - i32, ;; Unused field. - i32, ;; DWARF language identifier (ex. DW_LANG_C89) - metadata, ;; Source file name - metadata, ;; Source file directory (includes trailing slash) - metadata ;; Producer (ex. "4.0.1 LLVM (LLVM research group)") - i1, ;; True if this is a main compile unit. - i1, ;; True if this is optimized. - metadata, ;; Flags - i32 ;; Runtime version - metadata ;; List of enums types - metadata ;; List of retained types - metadata ;; List of subprograms - metadata ;; List of global variables - } - """ - - accept_optional_data = True - - type_descriptors = [ - desc("tag", get_i32), - desc("unused", get_i32), - - # Positional argument list starts here: - desc("langid", get_i32), - desc("source_filename", get_mdstr), - desc("source_filedir", get_mdstr), - desc("producer", get_mdstr), - desc("is_main", get_i1, default=False), - desc("is_optimized", get_i1, default=False), - desc("compile_flags", get_mdstr, default=""), - desc("runtime_version", get_i32, default=0), - desc("enum_types", get_mdlist, default=empty), - desc("retained_types", get_mdlist, default=empty), - desc("subprograms", get_mdlist, default=empty), - desc("global_vars", get_mdlist, default=empty), - ] - - def __init__(self, *args, **kwargs): - super(CompileUnitDescriptor, self).__init__( - _dwarf.DW_TAG_compile_unit + _dwarf.LLVMDebugVersion, # tag - 0, # unused - *args, **kwargs) - - def define(self, llvm_module): - """ - Define this debug descriptor as named debug metadata for the module. - """ - md = self.get_metadata(llvm_module) - llvm.core.MetaData.add_named_operand(llvm_module, "llvm.dbg.cu", md) - - -class FileDescriptor(DebugInfoDescriptor): - """ - !0 = metadata !{ - i32, ;; Tag = 41 + LLVMDebugVersion (DW_TAG_file_type) - metadata, ;; Source file name - metadata, ;; Source file directory (includes trailing slash) - metadata ;; Unused - } - """ - - type_descriptors = [ - desc("tag", get_i32), - - # Positional argument list starts here: - desc("source_filename", get_mdstr), - desc("source_filedir", get_mdstr), - desc("compile_unit", get_md, default=null), - ] - - def __init__(self, *args, **kwargs): - super(FileDescriptor, self).__init__( - _dwarf.DW_TAG_file_type + _dwarf.LLVMDebugVersion, # Tag - *args, **kwargs) - - @classmethod - def from_compileunit(cls, compile_unit_descriptor): - return cls(compile_unit_descriptor.operands_dict["source_filename"], - compile_unit_descriptor.operands_dict["source_filedir"], - compile_unit_descriptor) - - -class SubprogramDescriptor(DebugInfoDescriptor): - """ - !2 = metadata !{ - i32, ;; Tag = 46 + LLVMDebugVersion (DW_TAG_subprogram) - i32, ;; Unused field. - metadata, ;; Reference to context descriptor - metadata, ;; Name - metadata, ;; Display name (fully qualified C++ name) - metadata, ;; MIPS linkage name (for C++) - metadata, ;; Reference to file where defined - i32, ;; Line number where defined - metadata, ;; Reference to type descriptor - i1, ;; True if the global is local to compile unit (static) - i1, ;; True if the global is defined in the compile unit (not extern) - i32, ;; Line number where the scope of the subprogram begins - i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual - i32, ;; Index into a virtual function - metadata, ;; indicates which base type contains the vtable pointer for the - ;; derived class - i32, ;; Flags - Artifical, Private, Protected, Explicit, Prototyped. - i1, ;; isOptimized - Function * , ;; Pointer to LLVM function - metadata, ;; Lists function template parameters - metadata, ;; Function declaration descriptor - metadata ;; List of function variables - } - """ - - accept_optional_data = True - - type_descriptors = [ - desc("tag", get_i32), - desc("unused", get_i32), - - # Positional argument list starts here: - desc("file_desc", get_md), - desc("name", get_mdstr), - desc("display_name", get_mdstr), - desc("mips_linkage_name", get_mdstr), - desc("source_file_ref", get_md), - desc("line_number", get_i32), - desc("signature", get_md), - desc("is_local", get_i1, default=False), - desc("is_definition", get_i1, default=True), - desc("virtual_attribute", get_i32, default=0), - desc("virtual_index", get_i32, default=0), - desc("virttab", get_i32, default=0), - desc("flags", get_i32, default=0), - desc("is_optimized", get_i1, default=False), - desc("llvm_func", get_lfunc), - # Template params - # Func decl - # Func vars - ] - - def __init__(self, *args, **kwargs): - super(SubprogramDescriptor, self).__init__( - _dwarf.DW_TAG_subprogram + _dwarf.LLVMDebugVersion, # Tag - 0, # Unused - *args, **kwargs) - -class BlockDescriptor(DebugInfoDescriptor): - """ - !3 = metadata !{ - i32, ;; Tag = 11 + LLVMDebugVersion (DW_TAG_lexical_block) - metadata,;; Reference to context descriptor - i32, ;; Line number - i32 ;; Column number - } - """ - - type_descriptors = [ - desc("tag", get_i32), - - # Positional argument list starts here: - desc("context_descr", get_md), # FileDescr | BlockDescr | - # SubprogDescr | ComputeUnit - desc("line_number", get_i32), - desc("col_number", get_i32), - ] - - def __init__(self, *args, **kwargs): - super(BlockDescriptor, self).__init__( - _dwarf.DW_TAG_lexical_block + _dwarf.LLVMDebugVersion, - *args, **kwargs) - -class PositionInfoDescriptor(DebugInfoDescriptor): - """ - line number, column number, scope, and original scope - """ - - type_descriptors = [ - desc("line_number", get_i32), - desc("col_number", get_i32), - desc("context_descr", get_md), # Scope of instruction - # (FileDescr etc) - desc("original_context_descr", get_md, # The original scope if inlined - default=null), - ] diff --git a/llvm/ee.py b/llvm/ee.py index e5d6ef1..e69de29 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -1,392 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Execution Engine and related classes. - -""" - -import llvm # top-level, for common stuff -import llvm.core as core # module, function etc. -import llvm._core as _core # C wrappers -import llvm._util as _util # utility functions -import logging -import os - -logger = logging.getLogger(__name__) - - -# re-export TargetData for backward compatibility. -from llvm.passes import TargetData - -def _detect_avx_support(): - '''FIXME: This is a workaround for AVX support. - ''' - disable_avx_detect = int(os.environ.get('LLVMPY_DISABLE_AVX_DETECT', 0)) - if disable_avx_detect: - return False # enable AVX if user disable AVX detect - force_disable_avx = int(os.environ.get('LLVMPY_FORCE_DISABLE_AVX', 0)) - if force_disable_avx: - return True # force disable AVX - # auto-detect avx - try: - for line in open('/proc/cpuinfo'): - if line.lstrip().startswith('flags') and 'avx' in line.split(): - # enable AVX if flags contain AVX - return False - except IOError: - pass # disable AVX if no /proc/cpuinfo is found - return True # disable AVX if flags does not have AVX - -FORCE_DISABLE_AVX = _detect_avx_support() - -#===----------------------------------------------------------------------=== -# Enumerations -#===----------------------------------------------------------------------=== - -BO_BIG_ENDIAN = 0 -BO_LITTLE_ENDIAN = 1 - -# CodeModel -CM_DEFAULT = 0 -CM_JITDEFAULT = 1 -CM_SMALL = 2 -CM_KERNEL = 3 -CM_MEDIUM = 4 -CM_LARGE = 5 - -#===----------------------------------------------------------------------=== -# Generic value -#===----------------------------------------------------------------------=== - -class GenericValue(object): - - @staticmethod - def int(ty, intval): - core.check_is_type(ty) - ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 0) - return GenericValue(ptr) - - @staticmethod - def int_signed(ty, intval): - core.check_is_type(ty) - ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 1) - return GenericValue(ptr) - - @staticmethod - def real(ty, floatval): - core.check_is_type(ty) # only float or double - ptr = _core.LLVMCreateGenericValueOfFloat(ty.ptr, floatval) - return GenericValue(ptr) - - @staticmethod - def pointer(*args): - ''' - One argument version takes (addr). - Two argument version takes (ty, addr). [Deprecated] - - `ty` is unused. - `addr` is an integer representing an address. - - TODO: remove two argument version. - ''' - if len(args)==2: - logger.warning("Deprecated: Two argument version of " - "GenericValue.pointer() is deprecated.") - addr = args[1] - elif len(args)!=1: - raise TypeError("pointer() takes 1 or 2 arguments.") - else: - addr = args[0] - ptr = _core.LLVMCreateGenericValueOfPointer(addr) - return GenericValue(ptr) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeGenericValue(self.ptr) - - def as_int(self): - return _core.LLVMGenericValueToInt(self.ptr, 0) - - def as_int_signed(self): - return _core.LLVMGenericValueToInt(self.ptr, 1) - - def as_real(self, ty): - core.check_is_type(ty) # only float or double - return _core.LLVMGenericValueToFloat(ty.ptr, self.ptr) - - def as_pointer(self): - return _core.LLVMGenericValueToPointer(self.ptr) - - -# helper functions for generic value objects -def check_is_generic_value(obj): _util.check_gen(obj, GenericValue) -def _unpack_generic_values(objlist): - return _util.unpack_gen(objlist, check_is_generic_value) - - -#===----------------------------------------------------------------------=== -# Engine builder -#===----------------------------------------------------------------------=== - -class EngineBuilder(object): - @staticmethod - def new(module): - core.check_is_module(module) - _util.check_is_unowned(module) - obj = _core.LLVMCreateEngineBuilder(module.ptr) - return EngineBuilder(obj, module) - - def __init__(self, ptr, module): - self.ptr = ptr - self._module = module - self.__has_mattrs = False - - def __del__(self): - _core.LLVMDisposeEngineBuilder(self.ptr) - - def force_jit(self): - _core.LLVMEngineBuilderForceJIT(self.ptr) - return self - - def force_interpreter(self): - _core.LLVMEngineBuilderForceInterpreter(self.ptr) - return self - - def opt(self, level): - ''' - level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] - ''' - assert level in range(4) - _core.LLVMEngineBuilderSetOptLevel(self.ptr, level) - return self - - def mattrs(self, string): - '''set machine attributes as a comma/space separated string - - e.g: +sse,-3dnow - ''' - self.__has_mattrs = True - if FORCE_DISABLE_AVX: - if 'avx' not in map(lambda x: x.strip(), string.split(',')): - # User did not override - string += ',-avx' - _core.LLVMEngineBuilderSetMAttrs(self.ptr, string.replace(',', ' ')) - return self - - def create(self, tm=None): - ''' - tm --- Optional. Provide a TargetMachine. Ownership is transfered - to the returned execution engine. - ''' - if not self.__has_mattrs and FORCE_DISABLE_AVX: - self.mattrs('-avx') - - if tm: - _util.check_is_unowned(tm) - ret = _core.LLVMEngineBuilderCreateTM(self.ptr, tm.ptr) - else: - ret = _core.LLVMEngineBuilderCreate(self.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - engine = ExecutionEngine(ret, self._module) - if tm: - tm._own(owner=llvm.DummyOwner) - return engine - - def select_target(self): - '''get the corresponding target machine - ''' - ptr = _core.LLVMTargetMachineFromEngineBuilder(self.ptr) - return TargetMachine(ptr) - -#===----------------------------------------------------------------------=== -# Execution engine -#===----------------------------------------------------------------------=== - -class ExecutionEngine(object): - - @staticmethod - def new(module, force_interpreter=False): - eb = EngineBuilder.new(module) - if force_interpreter: - eb.force_interpreter() - return eb.create() - - def __init__(self, ptr, module): - self.ptr = ptr - module._own(self) - - def __del__(self): - _core.LLVMDisposeExecutionEngine(self.ptr) - - def disable_lazy_compilation(self, disabled=True): - _core.LLVMExecutionEngineDisableLazyCompilation(self.ptr, - int(bool(disabled))) - - def run_function(self, fn, args): - core.check_is_function(fn) - ptrs = _unpack_generic_values(args) - gvptr = _core.LLVMRunFunction2(self.ptr, fn.ptr, ptrs) - return GenericValue(gvptr) - - def get_pointer_to_function(self, fn): - core.check_is_function(fn) - return _core.LLVMGetPointerToFunction(self.ptr,fn.ptr) - - def get_pointer_to_global(self, val): - core.check_is_global_value(val) - return _core.LLVMGetPointerToGlobal(self.ptr, val.ptr) - - def add_global_mapping(self, gvar, addr): - assert addr >= 0, "Address cannot not be negative" - _core.LLVMAddGlobalMapping(self.ptr, gvar.ptr, addr) - - def run_static_ctors(self): - _core.LLVMRunStaticConstructors(self.ptr) - - def run_static_dtors(self): - _core.LLVMRunStaticDestructors(self.ptr) - - def free_machine_code_for(self, fn): - core.check_is_function(fn) - _core.LLVMFreeMachineCodeForFunction(self.ptr, fn.ptr) - - def add_module(self, module): - core.check_is_module(module) - _core.LLVMAddModule(self.ptr, module.ptr) - module._own(self) - - def remove_module(self, module): - core.check_is_module(module) - if module.owner != self: - raise llvm.LLVMException("module is not owned by self") - ret = _core.LLVMRemoveModule2(self.ptr, module.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - return core.Module(ret) - - @property - def target_data(self): - td = TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr)) - td._own(self) - return td - - -#===----------------------------------------------------------------------=== -# Target machine -#===----------------------------------------------------------------------=== - -def print_registered_targets(): - ''' - Note: print directly to stdout - ''' - _core.LLVMPrintRegisteredTargetsForVersion() - -def get_host_cpu_name(): - '''return the string name of the host CPU - ''' - return _core.LLVMGetHostCPUName() - -def get_default_triple(): - '''return the target triple of the host in str-rep - ''' - return _core.LLVMDefaultTargetTriple() - - -class TargetMachine(llvm.Ownable): - - @staticmethod - def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT): - if not triple and not cpu: - triple = get_default_triple() - cpu = get_host_cpu_name() - ptr = _core.LLVMCreateTargetMachine(triple, cpu, features, opt, cm) - return TargetMachine(ptr) - - @staticmethod - def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): - '''create a targetmachine given an architecture name - - For a list of architectures, - use: `llc -help` - - For a list of available CPUs, - use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help` - - For a list of available attributes (features), - use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` - ''' - ptr = _core.LLVMTargetMachineLookup(arch, cpu, features, opt, cm) - return TargetMachine(ptr) - - def __init__(self, ptr): - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetMachine) - - def emit_assembly(self, module): - '''returns byte string of the module as assembly code of the target machine - ''' - return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, True) - - def emit_object(self, module): - '''returns byte string of the module as native code of the target machine - ''' - return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, False) - - @property - def target_data(self): - '''get target data of this machine - ''' - ptr = _core.LLVMTargetMachineGetTargetData(self.ptr) - td = TargetData(ptr) - td._own(self) - return td - - @property - def target_name(self): - return _core.LLVMTargetMachineGetTargetName(self.ptr) - - @property - def target_short_description(self): - return _core.LLVMTargetMachineGetTargetShortDescription(self.ptr) - - @property - def triple(self): - return _core.LLVMTargetMachineGetTriple(self.ptr) - - @property - def cpu(self): - return _core.LLVMTargetMachineGetCPU(self.ptr) - - @property - def feature_string(self): - return _core.LLVMTargetMachineGetFS(self.ptr) - diff --git a/llvm/extra.cpp b/llvm/extra.cpp deleted file mode 100644 index 7b6c064..0000000 --- a/llvm/extra.cpp +++ /dev/null @@ -1,1361 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * These are some "extra" functions not available in the standard LLVM-C - * bindings, but are required / good-to-have inorder to implement the - * Python bindings. - */ - -// standard includes -#include -#include -#include -#include -#include - -// LLVM includes -#include "llvm/LLVMContext.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Casting.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalVariable.h" -//#include "llvm/TypeSymbolTable.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Host.h" - -#include "llvm/IntrinsicInst.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/PassManager.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/DomPrinter.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Linker.h" -#include "llvm/Support/SourceMgr.h" -#include -#include -#include - - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #include "llvm/DataLayout.h" -#else - #include "llvm/Target/TargetData.h" -#endif - -// LLVM-C includes -#include "llvm-c/Core.h" -#include "llvm-c/ExecutionEngine.h" - -// our includes -#include "extra.h" -#include "llvm_c_extra.h" - -namespace llvm{ -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(NamedMDNode, LLVMNamedMDRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) - -template -inline T **unwrap(LLVMTypeRef *Tys, unsigned Length) { - (void)Length; - return reinterpret_cast(Tys); -} - -} - -/* - * For use in LLVMDumpPasses to dump passes. - */ -class PassRegistryPrinter : public llvm::PassRegistrationListener{ -public: - std::ostringstream stringstream; - - inline virtual void passEnumerate(const llvm::PassInfo * pass_info){ - stringstream << pass_info->getPassArgument() - << "\t" - << pass_info->getPassName() - << "\n"; - } -}; - - -/* Helper method for LLVMDumpXXXToString() methods. */ -template -char *do_print(W obj) -{ - std::string s; - llvm::raw_string_ostream buf(s); - UW *p = llvm::unwrap(obj); - assert(p); - p->print(buf); - return strdup(buf.str().c_str()); -} - -namespace { -using namespace llvm; -const CodeGenOpt::Level OptLevelMap[] = { - CodeGenOpt::None, - CodeGenOpt::Less, - CodeGenOpt::Default, - CodeGenOpt::Aggressive, -}; - -const CodeModel::Model CodeModelMap[] = { - CodeModel::Default, - CodeModel::JITDefault, - CodeModel::Small, - CodeModel::Kernel, - CodeModel::Medium, - CodeModel::Large, -}; - - -} // end anony namespace - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -LLVMPassRef LLVMCreateTargetTransformInfo(LLVMTargetMachineRef tmref){ - using namespace llvm; - TargetMachine * tm = unwrap(tmref); - Pass * tti = new TargetTransformInfo(tm->getScalarTargetTransformInfo(), - tm->getVectorTargetTransformInfo()); - return wrap(tti); -} -#endif - -LLVMPassRef LLVMCreateTargetLibraryInfo(const char * triple){ - using namespace llvm; - Pass * tli = new TargetLibraryInfo(Triple(triple)); - return wrap(tli); -} - -const char * LLVMDefaultTargetTriple(){ - return strdup(llvm::sys::getDefaultTargetTriple().c_str()); -} - -LLVMPassRef LLVMCreatePassByName(const char *name){ - using namespace llvm; - const PassInfo * pi = Pass::lookupPassInfo(StringRef(name)); - if (pi) { - return wrap(pi->createPass()); - } else { // cannot find pass - return NULL; - } -} - -void LLVMDisposePass(LLVMPassRef passref){ - using namespace llvm; - delete unwrap(passref); -} - -const char * LLVMGetPassName(LLVMPassRef passref){ - using namespace llvm; - return unwrap(passref)->getPassName(); -} - -void LLVMPassDump(LLVMPassRef passref){ - using namespace llvm; - return unwrap(passref)->dump(); -} - -void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref){ - using namespace llvm; - unwrap(pmref)->add(unwrap(passref)); -} - -LLVMValueRef LLVMGetFunctionFromInlineAsm(LLVMTypeRef funcType, - const char inlineAsm[], - const char constrains[], - bool hasSideEffect, - bool isAlignStack, - int asmDialect) -{ - using namespace llvm; - FunctionType *fnty = unwrap(funcType); - // asmDialect does not exist for LLVM 3.1 - InlineAsm *inlineasmobj = InlineAsm::get(fnty, inlineAsm, constrains, - hasSideEffect, isAlignStack); - return wrap(inlineasmobj); -} - -LLVMModuleRef LLVMCloneModule(LLVMModuleRef mod) -{ - using namespace llvm; - return wrap(CloneModule(unwrap(mod))); -} - -const char * LLVMDumpNamedMDToString(LLVMNamedMDRef nmd) -{ - using namespace llvm; - std::string s; - llvm::raw_string_ostream buf(s); - unwrap(nmd)->print(buf, NULL); - return strdup(buf.str().c_str()); -} - -const char * LLVMNamedMetaDataGetName(LLVMNamedMDRef nmd) -{ - using namespace llvm; - return unwrap(nmd)->getName().data(); -} - -void LLVMNamedMetaDataAddOperand(LLVMNamedMDRef nmd, LLVMValueRef md) -{ - using namespace llvm; - unwrap(nmd)->addOperand(unwrap(md)); -} - -void LLVMEraseNamedMetaData(LLVMNamedMDRef nmd) -{ - using namespace llvm; - unwrap(nmd)->eraseFromParent(); -} - -LLVMNamedMDRef LLVMModuleGetOrInsertNamedMetaData(LLVMModuleRef mod, const char *name) -{ - using namespace llvm; - return wrap(unwrap(mod)->getOrInsertNamedMetadata(name)); -} - -LLVMNamedMDRef LLVMModuleGetNamedMetaData(LLVMModuleRef mod, const char *name) -{ - using namespace llvm; - return wrap(unwrap(mod)->getNamedMetadata(name)); -} - -void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, - LLVMValueRef metaref) -{ - using namespace llvm; - unwrap(instref)->setMetadata(mdkind, unwrap(metaref)); -} - -LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, - unsigned valct) -{ - using namespace llvm; - LLVMContext & context = unwrap(modref)->getContext(); - MDNode * const node = MDNode::get( - context, - makeArrayRef(unwrap(valrefs, valct), valct)); - return wrap(node); -} - -LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index) -{ - return wrap(llvm::unwrap(mdref)->getOperand(index)); -} - -unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref) -{ - return llvm::unwrap(mdref)->getNumOperands(); -} - -LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s) -{ - LLVMContext & context = unwrap(modref)->getContext(); - MDString * const mdstring = MDString::get(context, s); - return wrap(mdstring); -} - -const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst) -{ - return llvm::unwrap(inst)->getOpcodeName(); -} - -unsigned LLVMGetConstExprOpcode(LLVMValueRef inst) -{ - return llvm::unwrap(inst)->getOpcode(); -} - -void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align) -{ - return llvm::unwrap(inst)->setAlignment(align); -} - -void LLVMStSetAlignment(LLVMValueRef inst, unsigned align) -{ - return llvm::unwrap(inst)->setAlignment(align); -} - -const char * LLVMGetHostCPUName() -{ - return strdup(llvm::sys::getHostCPUName().c_str()); -} - -const char * LLVMGetHostCPUFeatures() -{ - // placeholder - // TODO not implemented even in LLVM3.2svn - // llvm::sys::getHostCPUFeatures - return NULL; -} - -int LLVMInitializeNativeTargetAsmPrinter() -{ - return llvm::InitializeNativeTargetAsmPrinter(); -} - - -LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt, - int codemodel, - std::string &error) -{ - using namespace llvm; - Triple TheTriple; - - // begin borrow from LLVM 3.2 code - // because we don't have 3 argument version of lookup() in 3.1 - const Target * TheTarget = NULL; - - const std::string ArchName(arch); - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - if (ArchName == it->getName()) { - TheTarget = &*it; - break; - } - } - - if (!TheTarget) { - error = "Unknown arch"; - return NULL; - } - - Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); - - if (Type != Triple::UnknownArch){ - TheTriple.setArch(Type); - } - // end borrow from LLVM 3.2 code - - if (!TheTarget->hasTargetMachine()){ - error = "No target machine for the arch"; - return NULL; - } - - TargetOptions no_target_options; - TargetMachine * tm = TheTarget->createTargetMachine(TheTriple.str(), cpu, - features, - no_target_options, - Reloc::Default, - CodeModelMap[codemodel], - OptLevelMap[opt]); - - if (!tm){ - error = "Cannot create target machine"; - return NULL; - } - return wrap(tm); -} - -LLVMTargetMachineRef LLVMCreateTargetMachine(const char *triple, - const char *cpu, - const char *features, - int opt, - int codemodel, - std::string &error) -{ - using namespace llvm; - - std::string TheTriple = triple; - const Target * TheTarget = TargetRegistry::lookupTarget(TheTriple, error); - if (!TheTarget) return NULL; - - TargetOptions no_target_options; - TargetMachine * tm = TheTarget->createTargetMachine(TheTriple, cpu, features, - no_target_options, - Reloc::Default, - CodeModelMap[codemodel], - OptLevelMap[opt]); - if (!tm) { - error = "Cannot create target machine"; - return NULL; - } - return wrap(tm); -} - -LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - TargetMachine * tm = unwrap(eb)->selectTarget(); - return wrap(tm); -} - -void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm){ - delete llvm::unwrap(tm); -} - - -unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, - LLVMModuleRef modref, - int assembly, size_t * lenp, - std::string &error) -{ - using namespace llvm; - assert(lenp); - - Module *modulep = unwrap(modref); - assert(modulep); - - // get objectcode into a string - std::string s; - raw_string_ostream buf(s); - - formatted_raw_ostream fso(buf); - - TargetMachine * tm = unwrap(tmref); - - PassManager pm; -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - if (!tm->getDataLayout()){ - error = "No target data in target machine"; - return NULL; - } - pm.add(new DataLayout(*tm->getDataLayout())); -#else - if (!tm->getTargetData()){ - error = "No target data in target machine"; - return NULL; - } - pm.add(new TargetData(*tm->getTargetData())); -#endif - - - - bool failed; - if( assembly ) { - failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_AssemblyFile); - } else { - failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_ObjectFile); - } - - if ( failed ) { - error = "No support for emit file"; - return NULL; - } - - pm.run(*modulep); - - // flush all streams - fso.flush(); - buf.flush(); - - const std::string& bc = buf.str(); - - // and then into a new buffer - size_t bclen = bc.size(); - unsigned char *bytes = new unsigned char[bclen]; - memcpy(bytes, bc.data(), bclen); - - /* return */ - *lenp = bclen; - return bytes; -} - -const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTarget().getName()); -} - -const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTarget().getShortDescription()); -} - -const char* LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetTriple().str().c_str()); -} - -const char* LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetCPU().str().c_str()); -} - -const char* LLVMTargetMachineGetFS(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetFeatureString().str().c_str()); -} - -void LLVMPrintRegisteredTargetsForVersion(){ - llvm::TargetRegistry::printRegisteredTargetsForVersion(); -} - - - -LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm) -{ - using namespace llvm; -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - return wrap(new DataLayout(*unwrap(tm)->getDataLayout())); -#else - return wrap(new TargetData(*unwrap(tm)->getTargetData())); -#endif -} - -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - size_t * lenp, std::string &error) -{ - using namespace llvm; - assert(lenp); - - Module *modulep = unwrap(module); - assert(modulep); - - // select native default machine - TargetMachine * tm = EngineBuilder(modulep).selectTarget(); - - return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp, error); -} - -static -llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering) -{ - using namespace llvm; - - if ( strcmp(ordering, "unordered") == 0 ) - return Unordered; - else if ( strcmp(ordering, "monotonic") == 0 ) - return Monotonic; - else if ( strcmp(ordering, "acquire") == 0 ) - return Acquire; - else if ( strcmp(ordering, "release") == 0 ) - return Release; - else if ( strcmp(ordering, "acq_rel") == 0 ) - return AcquireRelease; - else if ( strcmp(ordering, "seq_cst") == 0 ) - return SequentiallyConsistent; - else - return NotAtomic; -} - -static -llvm::SynchronizationScope sync_scope_from_int(int crossthread) -{ - if( crossthread ) - return llvm::CrossThread; - else - return llvm::SingleThread; -} - -LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateFence(atomic_order, sync_scope); - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname, - LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread) -{ - using namespace llvm; - - AtomicRMWInst::BinOp op; - - if( strcmp(opname, "xchg") == 0 ) - op = AtomicRMWInst::Xchg; - else if( strcmp(opname, "add") == 0 ) - op = AtomicRMWInst::Add; - else if( strcmp(opname, "sub") == 0 ) - op = AtomicRMWInst::Sub; - else if( strcmp(opname, "and") == 0 ) - op = AtomicRMWInst::And; - else if( strcmp(opname, "nand") == 0 ) - op = AtomicRMWInst::Nand; - else if( strcmp(opname, "or") == 0 ) - op = AtomicRMWInst::Or; - else if( strcmp(opname, "xor") == 0 ) - op = AtomicRMWInst::Xor; - else if( strcmp(opname, "max") == 0 ) - op = AtomicRMWInst::Max; - else if( strcmp(opname, "min") == 0 ) - op = AtomicRMWInst::Min; - else if( strcmp(opname, "umax") == 0 ) - op = AtomicRMWInst::UMax; - else if( strcmp(opname, "umin") == 0 ) - op = AtomicRMWInst::UMin; - else - op = AtomicRMWInst::BAD_BINOP; - - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateAtomicRMW(op, unwrap(ptr), unwrap(val), - atomic_order, sync_scope); - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - unsigned align, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - LoadInst * inst = unwrap(builder)->CreateLoad(unwrap(ptr)); - - inst->setAtomic(atomic_order, sync_scope); - inst->setAlignment(align); - - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, - LLVMValueRef ptr, LLVMValueRef val, - unsigned align, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr)); - - inst->setAtomic(atomic_order, sync_scope); - inst->setAlignment(align); - - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, - LLVMValueRef cmp, LLVMValueRef val, - const char* ordering, int crossthread) -{ - using namespace llvm; - - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateAtomicCmpXchg( - unwrap(ptr), unwrap(cmp), unwrap(val), - atomic_order, sync_scope); - return wrap(inst); -} - -LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod) -{ - return llvm::wrap(new EngineBuilder(unwrap(mod))); -} - -void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb) -{ - delete llvm::unwrap(eb); -} - -void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - unwrap(eb)->setEngineKind(EngineKind::JIT); -} - -void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - unwrap(eb)->setEngineKind(EngineKind::Interpreter); -} - -void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level) -{ - unwrap(eb)->setOptLevel(OptLevelMap[level]); -} - -void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu) -{ // TODO add test when llvm3.2 releases - unwrap(eb)->setMCPU(mcpu); // does not work in llvm3.1 -} - -void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs) -{ // TODO add test when llvm3.2 releases - std::vector tokenized; - std::istringstream iss(mattrs); - std::string buf; - while ( iss >> buf ){ - tokenized.push_back(buf); - } - unwrap(eb)->setMAttrs(tokenized); // does not work in llvm3.1 -} - -LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, std::string & error) -{ - using namespace llvm; - LLVMExecutionEngineRef ret; - - ret = wrap(unwrap(eb)->setErrorStr(&error).create()); - - if ( !error.empty() ) { // error string is set - return NULL; - } else { - return ret; - } -} - -LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef eb, - LLVMTargetMachineRef tm, - std::string & error) -{ - using namespace llvm; - LLVMExecutionEngineRef ret; - - ret = wrap(unwrap(eb)->setErrorStr(&error).create(unwrap(tm))); - - if ( !error.empty() ) { // error string is set - return NULL; - } else { - return ret; - } -} - -int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->OptLevel; -} - -int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->SizeLevel; -} - -void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag) -{ - llvm::unwrap(pmb)->Vectorize = flag; -} - -int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb){ - return llvm::unwrap(pmb)->Vectorize; -} - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -void LLVMPassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef pmb, - int flag) -{ - llvm::unwrap(pmb)->LoopVectorize = flag; -} - -int LLVMPassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef pmb){ - return llvm::unwrap(pmb)->LoopVectorize; -} -#endif // llvm-3.2 - - -int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableUnitAtATime; -} - -int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableUnrollLoops; -} - -int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableSimplifyLibCalls; -} - - -int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name) -{ - using namespace llvm; - const PassInfo * pi = Pass::lookupPassInfo(StringRef(name)); - if (pi){ - unwrap(pm)->add(pi->createPass()); - return 1; // success - } else { - return 0; // fail -- cannot find pass - } -} - -void LLVMInitializePasses(){ - using namespace llvm; - PassRegistry ®istry = *PassRegistry::getPassRegistry(); - initializeCore(registry); - initializeScalarOpts(registry); - initializeVectorization(registry); - initializeIPO(registry); - initializeAnalysis(registry); - initializeIPA(registry); - initializeTransformUtils(registry); - initializeInstCombine(registry); - initializeInstrumentation(registry); - initializeTarget(registry); -} - -const char * LLVMDumpPasses() -{ - using namespace llvm; - PassRegistry ®istry = *PassRegistry::getPassRegistry(); - PassRegistryPrinter prp; - registry.enumerateWith(&prp); - return strdup(prp.stringstream.str().c_str()); -} - - -int LLVMIsLiteralStruct(LLVMTypeRef type) -{ - return llvm::unwrap(type)->isLiteral(); -} - -LLVMTypeRef LLVMStructTypeIdentified(const char * name) -{ - using namespace llvm; - return wrap(StructType::create(getGlobalContext(), name)); -} - -void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, - unsigned elemct, int is_packed) -{ - using namespace llvm; - ArrayRef elemtys_aryref(unwrap(elemtys), elemct); - unwrap(type)->setBody(elemtys_aryref, is_packed); -} - -void LLVMSetStructName(LLVMTypeRef type, const char * name) -{ - llvm::StructType *st = llvm::unwrap(type); - st->setName(name); -} - -char *LLVMGetModuleIdentifier(LLVMModuleRef module) -{ - return strdup(llvm::unwrap(module)->getModuleIdentifier().c_str()); -} - -void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name) -{ - llvm::unwrap(module)->setModuleIdentifier(name); -} - -char *LLVMDumpModuleToString(LLVMModuleRef module) -{ - std::string s; - llvm::raw_string_ostream buf(s); - llvm::Module *p = llvm::unwrap(module); - assert(p); - p->print(buf, NULL); - return strdup(buf.str().c_str()); -} - -void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name) -{ - llvm::Module *M = llvm::unwrap(module); - llvm::StringRef namestr = llvm::StringRef(name); - M->addLibrary(namestr); - return; -} - -char *LLVMDumpTypeToString(LLVMTypeRef type) -{ - return do_print(type); -} - -char *LLVMDumpValueToString(LLVMValueRef value) -{ - return do_print(value); -} - -unsigned LLVMModuleGetPointerSize(LLVMModuleRef module) -{ - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - llvm::Module::PointerSize p = modulep->getPointerSize(); - if (p == llvm::Module::Pointer32) - return 32; - else if (p == llvm::Module::Pointer64) - return 64; - return 0; -} - -LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module, - const char *name, LLVMTypeRef function_type) -{ - assert(name); - - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - llvm::FunctionType *ftp = llvm::unwrap(function_type); - assert(ftp); - - llvm::Constant *f = modulep->getOrInsertFunction(name, ftp); - return wrap(f); -} - -int LLVMHasInitializer(LLVMValueRef global_var) -{ - llvm::GlobalVariable *gvp = llvm::unwrap(global_var); - assert(gvp); - - return gvp->hasInitializer(); -} - -#define inst_checkfn(ourfn, llvmfn) \ -unsigned ourfn (LLVMValueRef v) { \ - llvm::Instruction *ip = llvm::unwrap(v); \ - assert(ip); \ - return ip-> llvmfn () ? 1 : 0; \ -} - -inst_checkfn(LLVMInstIsTerminator, isTerminator) -inst_checkfn(LLVMInstIsBinaryOp, isBinaryOp) -inst_checkfn(LLVMInstIsShift, isShift) -inst_checkfn(LLVMInstIsCast, isCast) -inst_checkfn(LLVMInstIsLogicalShift, isLogicalShift) -inst_checkfn(LLVMInstIsArithmeticShift, isArithmeticShift) -inst_checkfn(LLVMInstIsAssociative, isAssociative) -inst_checkfn(LLVMInstIsCommutative, isCommutative) - -unsigned LLVMInstIsVolatile(LLVMValueRef v) -{ - using namespace llvm; - Instruction *ip = unwrap(v); - assert(ip); - return ((isa(*ip) && cast(*ip).isVolatile()) || - (isa(*ip) && cast(*ip).isVolatile()) ); -} - -const char *LLVMInstGetOpcodeName(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - assert(instp); - return instp->getOpcodeName(); -} - -unsigned LLVMInstGetOpcode(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - assert(instp); - return instp->getOpcode(); -} - -unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst) -{ - llvm::CmpInst *instp = llvm::unwrap(cmpinst); - assert(instp); - return instp->getPredicate(); -} - -LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - return llvm::wrap(CallSite(instp).getCalledFunction()); -} - -void LLVMInstSetCalledFunction(LLVMValueRef inst, LLVMValueRef fn) -{ - using namespace llvm; - Instruction *instp = unwrap(inst); - CallSite(instp).setCalledFunction(unwrap(fn)); -} - -///* llvm::unwrap a set of `n' wrapped objects starting at `values', -// * into a vector of pointers to llvm::unwrapped objects `out'. */ -//template -//void unwrap_vec(W *values, unsigned n, std::vector& out) -//{ -// out.clear(); -// out.reserve(n); -// while (n--) { -// UW *p = llvm::unwrap(*values); -// assert(p); -// out.push_back(p); -// ++values; -// } -//} - -///* Same as llvm::unwrap_vec, but use a vector of const pointers. */ -//template -//void unwrap_cvec(W *values, unsigned n, std::vector& out) -//{ -// out.clear(); - -// while (n--) { -// UW *p = llvm::unwrap(*values); -// assert(p); -// out.push_back(p); -// ++values; -// } -//} - - -LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef builder, - LLVMValueRef *values, unsigned n_values) -{ - using namespace llvm; - assert(values); - - IRBuilder<> *builderp = unwrap(builder); - assert(builderp); - - return wrap(builderp->CreateAggregateRet(unwrap(values, n_values), n_values)); -} - -LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, - LLVMValueRef value, unsigned index, const char *name) -{ - assert(name); - - llvm::IRBuilder<> *builderp = llvm::unwrap(builder); - assert(builderp); - - return llvm::wrap(builderp->CreateExtractValue(llvm::unwrap(value), index, name)); -} - -unsigned LLVMValueGetID(LLVMValueRef value) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - return valuep->getValueID(); -} - - -unsigned LLVMValueGetNumUses(LLVMValueRef value) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - return valuep->getNumUses(); -} - - -unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - unsigned n = valuep->getNumUses(); - if (n == 0) - return 0; - - assert(refs); - LLVMValueRef *out = new LLVMValueRef[n]; - if (!out) - return 0; - *refs = out; - - memset(out, 0, sizeof(LLVMValueRef) * n); - llvm::Value::use_iterator it = valuep->use_begin(); - while (it != valuep->use_end()) { - *out++ = llvm::wrap(*it); - ++it; - } - - return n; -} - -void LLVMDisposeValueRefArray(LLVMValueRef *refs) -{ - assert(refs); - delete [] refs; -} - -unsigned LLVMUserGetNumOperands(LLVMValueRef user) -{ - llvm::User *userp = llvm::unwrap(user); - assert(userp); - return userp->getNumOperands(); -} - -LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx) -{ - llvm::User *userp = llvm::unwrap(user); - assert(userp); - llvm::Value *operand = userp->getOperand(idx); - return llvm::wrap(operand); -} - -unsigned LLVMGetDoesNotThrow(LLVMValueRef fn) -{ - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return fnp->doesNotThrow(); -} - -void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow) -{ - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - if ((bool)DoesNotThrow) - fnp->setDoesNotThrow(); -} - - -LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef module, int id, - LLVMTypeRef *types, unsigned n_types) -{ - using namespace llvm; - assert(types); - - Module *modulep = unwrap(module); - assert(modulep); - - Function *intfunc = Intrinsic::getDeclaration(modulep, Intrinsic::ID(id), - makeArrayRef(unwrap(types, n_types), - n_types)); - - return wrap(intfunc); -} - -LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtext, char **out) -{ - assert(asmtext); - assert(out); - - llvm::Module *modulep; - llvm::SMDiagnostic error; - if (!(modulep = llvm::ParseAssemblyString(asmtext, NULL, error, - llvm::getGlobalContext()))) { - std::string s; - llvm::raw_string_ostream buf(s); - error.print("llvm-py", buf); - *out = strdup(buf.str().c_str()); - return NULL; - } - - return wrap(modulep); -} - -LLVMModuleRef LLVMGetModuleFromBitcode(const char *bitcode, unsigned bclen, - char **out) -{ - assert(bitcode); - assert(out); - - llvm::StringRef as_str(bitcode, bclen); - - llvm::MemoryBuffer *mbp; - if (!(mbp = llvm::MemoryBuffer::getMemBufferCopy(as_str))) - return NULL; - - std::string msg; - llvm::Module *modulep; - if (!(modulep = llvm::ParseBitcodeFile(mbp, llvm::getGlobalContext(), - &msg))) - *out = strdup(msg.c_str()); - - delete mbp; - return wrap(modulep); -} - -#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2 -// Shamelessly copy from LLVM-3.2 -unsigned LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - int Mode, char **OutMessages) { - std::string Messages; - unsigned Result = Linker::LinkModules(unwrap(Dest), unwrap(Src), Mode, - OutMessages? &Messages : 0); - if (OutMessages) - *OutMessages = strdup(Messages.c_str()); - return Result; -} -#endif - -unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, size_t *lenp) -{ - assert(lenp); - - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - /* get bc into a string */ - std::string s; - llvm::raw_string_ostream buf(s); - llvm::WriteBitcodeToFile(modulep, buf); - const std::string& bc = buf.str(); - - /* and then into a new()-ed block */ - size_t bclen = bc.size(); - unsigned char *bytes = new unsigned char[bclen]; - memcpy(bytes, bc.data(), bclen); - - /* return */ - *lenp = bclen; - return bytes; -} - -/* Return 0 on failure (with errmsg filled in), 1 on success. */ -unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg) -{ - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@1"); - assert(filename); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2"); - assert(errmsg); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@3"); - - /* Note: the LLVM API returns true on failure. Don't ask why. */ - std::string msg; - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@4"); - if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename, &msg)) { - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5"); - *errmsg = strdup(msg.c_str()); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@6"); - return 0; - } - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7"); - return 1; -} - -void LLVMExecutionEngineDisableLazyCompilation(LLVMExecutionEngineRef ee, int flag) -{ - llvm::unwrap(ee)->DisableLazyCompilation(flag); -} - -void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn) -{ - llvm::ExecutionEngine *eep = llvm::unwrap(ee); - assert(eep); - - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return eep->getPointerToFunction(fnp); -} - - -int LLVMInlineFunction(LLVMValueRef call) -{ - llvm::Value *callp = llvm::unwrap(call); - assert(callp); - - llvm::InlineFunctionInfo unused; - - llvm::Instruction *II = llvm::dyn_cast(callp); - if (II->getOpcode() == llvm::Instruction::Call) - return llvm::InlineFunction(static_cast(II), unused); - else if (II->getOpcode() == llvm::Instruction::Invoke) - return llvm::InlineFunction(static_cast(II), unused); - else - return 0; -} - -unsigned LLVMGetParamAlignment(LLVMValueRef arg) -{ - llvm::Argument *argp = llvm::unwrap(arg); - assert(argp); - - unsigned argno = argp->getArgNo(); - - return argp->getParent()->getParamAlignment(argno + 1); -} - - -/* Passes. A few passes (listed below) are used directly from LLVM-C, - * rest are defined here. - */ -/* -#define define_pass(P) \ -void LLVMAdd ## P ## Pass (LLVMPassManagerRef passmgr) { \ - using namespace llvm; \ - llvm::PassManagerBase *pmp = llvm::unwrap(passmgr); \ - assert(pmp); \ - pmp->add( create ## P ## Pass ()); \ -} - -define_pass( AAEval ) -define_pass( AliasAnalysisCounter ) -//define_pass( AlwaysInliner ) -//define_pass( BasicAliasAnalysis ) -define_pass( BlockPlacement ) -define_pass( BreakCriticalEdges ) -define_pass( CodeGenPrepare ) -define_pass( DbgInfoPrinter ) -define_pass( DeadCodeElimination ) -define_pass( DeadInstElimination ) -define_pass( DemoteRegisterToMemory ) -define_pass( DomOnlyPrinter ) -define_pass( DomOnlyViewer ) -define_pass( DomPrinter ) -define_pass( DomViewer ) -define_pass( EdgeProfiler ) -//define_pass( GEPSplitter ) -define_pass( GlobalsModRef ) -define_pass( InstCount ) -define_pass( InstructionNamer ) -define_pass( LazyValueInfo ) -define_pass( LCSSA ) -//define_pass( LiveValues ) -define_pass( LoopDependenceAnalysis ) -define_pass( LoopExtractor ) -define_pass( LoopSimplify ) -define_pass( LoopStrengthReduce ) -define_pass( LowerInvoke ) -define_pass( LowerSwitch ) -define_pass( MergeFunctions ) -define_pass( NoAA ) -define_pass( NoProfileInfo ) -define_pass( OptimalEdgeProfiler ) -define_pass( PartialInlining ) -//define_pass( PartialSpecialization ) -define_pass( PostDomOnlyPrinter ) -define_pass( PostDomOnlyViewer ) -define_pass( PostDomPrinter ) -define_pass( PostDomViewer ) -define_pass( ProfileEstimator ) -define_pass( ProfileLoader ) -define_pass( ProfileVerifier ) -define_pass( ScalarEvolutionAliasAnalysis ) -//define_pass( SimplifyHalfPowrLibCalls ) -define_pass( SingleLoopExtractor ) -define_pass( StripNonDebugSymbols ) -//define_pass( StructRetPromotion ) -//define_pass( TailDuplication ) -define_pass( UnifyFunctionExitNodes ) -*/ -/* we support only internalize(true) */ -/* -llvm::ModulePass *createInternalize2Pass() { return llvm::createInternalizePass(true); } -define_pass( Internalize2 ) -*/ diff --git a/llvm/extra.h b/llvm/extra.h deleted file mode 100644 index b734f1b..0000000 --- a/llvm/extra.h +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * These are some "extra" functions not available in the standard LLVM-C - * bindings, but are required / good-to-have inorder to implement the - * Python bindings. - */ - -#ifndef LLVM_PY_EXTRA_H -#define LLVM_PY_EXTRA_H - -// select PTX or NVPTX - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #define LLVM_HAS_NVPTX 1 -#else - #define LLVM_HAS_NVPTX 0 -#endif - -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm_c_extra.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -/* - * Wraps new TargetTransformInfo( - * TargetMachine::getScalarTargetTransformInfo, - * TargetMachine::getVectorTargetTransformInfo) - */ -LLVMPassRef LLVMCreateTargetTransformInfo(LLVMTargetMachineRef tmref); -#endif - -/* - * Wraps new TargetLibraryInfo - */ -LLVMPassRef LLVMCreateTargetLibraryInfo(const char * triple); - -/* - * Wraps llvm::getDefaultTargetTriple - */ -const char * LLVMDefaultTargetTriple(); - -/* - * Wraps Pass::lookupPassInfo and PassInfo::createPass - */ -LLVMPassRef LLVMCreatePassByName(const char *name); - -/* - * Wraps operator delete (Pass*) - */ -void LLVMDisposePass(LLVMPassRef passref); - -/* - * Wraps Pass::getPassName - */ -const char * LLVMGetPassName(LLVMPassRef passref); - -/* - * Wraps PassManager::add - */ -void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref); - -/* - * Wraps Pass::dump - */ -void LLVMPassDump(LLVMPassRef passref); - -/* - * Wraps llvm:InlineAsm::get - */ -LLVMValueRef LLVMGetFunctionFromInlineAsm(LLVMTypeRef funcType, - const char inlineAsm[], - const char constrains[], - bool hasSideEffect, - bool isAlignStack, - int asmDialect); - -/* - * Wraps llvm::CloneModule - */ -LLVMModuleRef LLVMCloneModule(LLVMModuleRef mod); - - -/* - * Wraps NamedMDNode::print() - */ -const char * LLVMDumpNamedMDToString(LLVMNamedMDRef nmd); - -/* - * Wraps NamedMDNode::getName() - */ -const char * LLVMNamedMetaDataGetName(LLVMNamedMDRef nmd); - -/* - * Wraps NamedMDNode::addOperand() - */ -void LLVMNamedMetaDataAddOperand(LLVMNamedMDRef nmd, LLVMValueRef md); - -/* - * Wraps NamedMDNode::eraseFromParent() - */ -void LLVMEraseNamedMetaData(LLVMNamedMDRef nmd); - -/* - * Wraps Module::getOrInsertNamedMetadata - */ -LLVMNamedMDRef LLVMModuleGetOrInsertNamedMetaData(LLVMModuleRef mod, const char *name); - -/* - * Wraps Module::getNamedMetadata - */ -LLVMNamedMDRef LLVMModuleGetNamedMetaData(LLVMModuleRef mod, const char *name); - -/* - * Wraps Instruction::setMetadata() - */ -void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, - LLVMValueRef metaref); - -/* - * Wraps MDNode::get() - */ -LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, - unsigned valct); - -/* - * Wraps MDNode::getOperand() - */ -LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index); - -/* - * Wraps MDNode::getNumOperands() - */ -unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref); - -/* - * Wraps MDString::get() - */ -LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s); - -/* - * Wraps ConstantExpr::getOpcodeName() - */ -const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst); - -/* - * Wraps ConstantExpr::getOpcode() - */ -unsigned LLVMGetConstExprOpcode(LLVMValueRef inst); - -/* - * Wraps LoadInst::SetAlignment - */ -void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align); - -/* - * Wraps StoreInst::SetAlignment - */ -void LLVMStSetAlignment(LLVMValueRef inst, unsigned align); - -const char * LLVMGetHostCPUName(); - -int LLVMInitializeNativeTargetAsmPrinter(); - - -LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt, - int codemodel, std::string &error); - -LLVMTargetMachineRef LLVMCreateTargetMachine(const char *arch, const char *cpu, - const char *features, int opt, - int codemodel, - std::string &error); - -/* - * Wraps EngineBuilder::selectTarget - */ -LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb); - -/* - * Wraps operator delete - */ -void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::addPassesToEmitFile - */ -unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, - LLVMModuleRef modref, - int assembly, size_t * lenp, - std::string &error); - -/* - * Wraps TargetMachine::getTargetData - */ -LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTarget().getName() - */ -const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTarget().getShortDescription() - */ -const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetTriple - */ -const char * LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetCPU - */ -const char * LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetFeatureString - */ -const char * LLVMTargetMachineGetFS(LLVMTargetMachineRef tm); - -/* - * Wraps TargetRegister::printRegisteredTargetsForVersion - */ -void LLVMPrintRegisteredTargetsForVersion(); - -/* - * Wraps TargetMachine::addPassesToEmitFile - */ -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - size_t * lenp, std::string &error); - -/* - * Wraps IRBuilder::CreateFence - */ -LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, - int crossthread); - -/* - * Wraps IRBuilder::CreateLoad, LoadInst::setAtomic - */ -LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - unsigned align, const char* ordering, - int crossthread); -/* - * Wraps IRBuilder::CreateStore, StoreInst::setAtomic - */ -LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, - LLVMValueRef ptr, LLVMValueRef val, - unsigned align, const char* ordering, - int crossthread); - -/* - * Wraps IRBuilder::CreateAtomicRMW - */ -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * op, - LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread); - -/* - * Wraps IRBuilder::CreateAtomicCmpXchg - */ -LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, - LLVMValueRef cmp, LLVMValueRef val, - const char* ordering, int crossthread); - -/* - * Wraps new EngineBuilder - */ -LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod); - -/* - * Wraps delete EngineBuilder - */ -void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb); - - -/* - * Wraps EngineBuilder::setEngineKind(EngineKind::JIT) - */ -void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb); - -/* - * Wraps EngineBuilder::setEngineKind(EngineKind::Interpreter) - */ -void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb); - - -/* - * Wraps EngineBuilder::setOptLevel - */ -void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level); - -/* - * Wraps EngineBuilder::setMCPU - */ -void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu); - -/* - * Wraps EngineBuilder::setMAttrs - */ -void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs); - -/* - * Wraps EngineBuilder::setErrorStr and EngineBuilder::create - */ -LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, - std::string &error); - -/* - * Wraps EngineBuilder::create(TargetMachine*) - */ -LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef ebref, - LLVMTargetMachineRef tmref, - std::string & error); - - -/* - * Wraps PassManagerBuilder::OptLevel - */ -int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::SizeLevel - */ -int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::Vectorize - */ -void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag); - -/* - * Wraps PassManagerBuilder::Vectorize - */ -int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb); - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -/* - * Wraps PassManagerBuilder::LoopVectorize - */ -void LLVMPassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef pmb, - int flag); - -/* - * Wraps PassManagerBuilder::LoopVectorize - */ -int LLVMPassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef pmb); -#endif // llvm-3.2 - -/* - * Wraps PassManagerBuilder::DisableUnitAtATime - */ -int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableUnrollLoops - */ -int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableSimplifyLibCalls - */ -int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManager::add - */ -int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name); - -/* - * Wraps initialize* - */ -void LLVMInitializePasses(void); - -/* - * Wraps PassRegistry::enumerateWith() - * Returns a '\n' separated string of all passes available to `opt`. - */ -const char * LLVMDumpPasses(void); - -/* - * Wraps StructType::isLiteral() - */ -int LLVMIsLiteralStruct(LLVMTypeRef type); - -/* - * Wraps StructType::create() - */ -LLVMTypeRef LLVMStructTypeIdentified(const char * name); - -/* - * StructType::setBody() - */ -void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed); - -/* - * Wraps llvm::StructType::setName() - */ -void LLVMSetStructName(LLVMTypeRef type, const char * name); - - -/* - * Wraps llvm::Module::getModuleIdentifier() - */ -char *LLVMGetModuleIdentifier(LLVMModuleRef module); - -/* - * Wraps llvm::Module::setModuleIdentifier() - */ -void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name); - -/* Notes: - * - Some returned strings must be disposed of by LLVMDisposeMessage. These are - * indicated in the comments. Where it is not indicated, DO NOT call dispose. - */ - -/* Wraps llvm::Module::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpModuleToString(LLVMModuleRef module); - -/* Wraps llvm::Module::addLibrary(name). */ -void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name); - -/* Wraps llvm::Type::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpTypeToString(LLVMTypeRef type); - -/* Wraps llvm::Value::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpValueToString(LLVMValueRef Val); - -/* Wraps llvm::IRBuilder::CreateRet(). */ -LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef bulder, LLVMValueRef *values, - unsigned n_values); - -/* Wraps llvm::IRBuilder::CreateGetResult(). */ -LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, LLVMValueRef value, - unsigned index, const char *name); - -/* Wraps llvm::Value::getValueID(). */ -unsigned LLVMValueGetID(LLVMValueRef value); - -/* Wraps llvm::Value::getNumUses(). */ -unsigned LLVMValueGetNumUses(LLVMValueRef value); - -/* Wraps llvm::Value::use_{begin,end}. Allocates LLVMValueRef's as - * required. Number of objects are returned as return value. If that is - * greater than zero, the pointer given out must be freed by a - * subsequent call to LLVMDisposeValueRefArray(). */ -unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs); - -/* See above. */ -void LLVMDisposeValueRefArray(LLVMValueRef *refs); - -/* Wraps llvm:User::getNumOperands(). */ -unsigned LLVMUserGetNumOperands(LLVMValueRef user); - -/* Wraps llvm:User::getOperand(). */ -LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx); - -/* Wraps llvm::ConstantExpr::getVICmp(). */ -LLVMValueRef LLVMConstVICmp(LLVMIntPredicate predicate, LLVMValueRef lhs, - LLVMValueRef rhs); - -/* Wraps llvm::ConstantExpr::getVFCmp(). */ -LLVMValueRef LLVMConstVFCmp(LLVMRealPredicate predicate, LLVMValueRef lhs, - LLVMValueRef rhs); - -/* Wraps llvm::IRBuilder::CreateVICmp(). */ -LLVMValueRef LLVMBuildVICmp(LLVMBuilderRef builder, LLVMIntPredicate predicate, - LLVMValueRef lhs, LLVMValueRef rhs, const char *name); - -/* Wraps llvm::IRBuilder::CreateVFCmp(). */ -LLVMValueRef LLVMBuildVFCmp(LLVMBuilderRef builder, LLVMRealPredicate predicate, - LLVMValueRef lhs, LLVMValueRef rhs, const char *name); - -/* Wraps llvm::Intrinsic::getDeclaration(). */ -LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef builder, int id, - LLVMTypeRef *types, unsigned n_types); - -/* Wraps llvm::Function::doesNotThrow(). */ -unsigned LLVMGetDoesNotThrow(LLVMValueRef fn); - -/* Wraps llvm::Function::setDoesNotThrow(). */ -void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow); - -/* Wraps llvm::Module::getPointerSize(). */ -unsigned LLVMModuleGetPointerSize(LLVMModuleRef module); - -/* Wraps llvm::Module::getOrInsertFunction(). */ -LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module, - const char *name, LLVMTypeRef function_type); - -/* Wraps llvm::GlobalVariable::hasInitializer(). */ -int LLVMHasInitializer(LLVMValueRef global_var); - -/* The following functions wrap various llvm::Instruction::isXXX() functions. - * All of them take an instruction and return 0 (isXXX returned false) or 1 - * (isXXX returned false). */ -unsigned LLVMInstIsTerminator (LLVMValueRef inst); -unsigned LLVMInstIsBinaryOp (LLVMValueRef inst); -unsigned LLVMInstIsShift (LLVMValueRef inst); -unsigned LLVMInstIsCast (LLVMValueRef inst); -unsigned LLVMInstIsLogicalShift (LLVMValueRef inst); -unsigned LLVMInstIsArithmeticShift (LLVMValueRef inst); -unsigned LLVMInstIsAssociative (LLVMValueRef inst); -unsigned LLVMInstIsCommutative (LLVMValueRef inst); -unsigned LLVMInstIsTrapping (LLVMValueRef inst); - -/* As above, but these are wrap methods from subclasses of Instruction. */ -unsigned LLVMInstIsVolatile (LLVMValueRef inst); - -/* Wraps llvm::Instruction::getOpcodeName(). */ -const char *LLVMInstGetOpcodeName(LLVMValueRef inst); - -/* Wraps llvm::Instruction::getOpcode(). */ -unsigned LLVMInstGetOpcode(LLVMValueRef inst); - -/* Wraps llvm::CmpInst::getPredicate(). */ -unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst); - -/* Wraps llvm::CallSite::getCalledFunction. - */ -LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst); - -/* Wraps llvm::CallSite::setCalledFunction. - */ -void LLVMInstSetCalledFunction(LLVMValueRef inst, LLVMValueRef fn); - -/* Wraps llvm::ParseAssemblyString(). Returns a module reference or NULL (with - * `out' pointing to an error message). Dispose error message after use, via - * LLVMDisposeMessage(). */ -LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtxt, char **out); - -/* Wraps llvm::ParseBitcodeFile(). Returns a module reference or NULL (with - * `out' pointing to an error message). Dispose error message after use, via - * LLVMDisposeMessage(). */ -LLVMModuleRef LLVMGetModuleFromBitcode(const char *bc, unsigned bclen, - char **out); - -#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2 -/* Wraps llvm::Linker::LinkModules(). Returns 0 on failure (with errmsg - * filled in) and 1 on success. Dispose error message after use with - * LLVMDisposeMessage(). */ -unsigned LLVMLinkModules(LLVMModuleRef dest, LLVMModuleRef src, int mode, - char **errmsg); -#endif -/* Returns pointer to a heap-allocated block of `*len' bytes containing bit code - * for the given module. NULL on error. */ -unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, size_t *len); - -/* Wraps llvm::sys::DynamicLibrary::LoadLibraryPermanently(). Returns 0 on - * failure (with errmsg filled in) and 1 on success. Dispose error message after - * use, via LLVMDisposeMessage(). */ -unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg); - -/* Wraps llvm::ExecutionEngine::DisableLazyCompilation(bool) - */ -void LLVMExecutionEngineDisableLazyCompilation(LLVMExecutionEngineRef ee, - int flag); - -/* Wraps llvm::ExecutionEngine::getPointerToFunction(). Returns a pointer - * to the JITted function. */ -void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn); - -/* Wraps llvm::InlineFunction(). Inlines a function. C is the call - * instruction, created by LLVMBuildCall. Even if it fails, the Function - * containing the call is still in a proper state (not changed). - */ -int LLVMInlineFunction(LLVMValueRef call); - -/* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the - * already available LLVMSetParamAlignment(). */ -unsigned LLVMGetParamAlignment(LLVMValueRef arg); - -/* Passes. Some passes are used directly from LLVM-C, rest are declared - * here. */ - -/* -#define declare_pass(P) \ - void LLVMAdd ## P ## Pass (LLVMPassManagerRef PM); - -declare_pass( AAEval ) -declare_pass( AliasAnalysisCounter ) -declare_pass( AlwaysInliner ) -declare_pass( BasicAliasAnalysis ) -declare_pass( BlockPlacement ) -declare_pass( BreakCriticalEdges ) -declare_pass( CodeGenPrepare ) -declare_pass( DbgInfoPrinter ) -declare_pass( DeadCodeElimination ) -declare_pass( DeadInstElimination ) -declare_pass( DemoteRegisterToMemory ) -declare_pass( DomOnlyPrinter ) -declare_pass( DomOnlyViewer ) -declare_pass( DomPrinter ) -declare_pass( DomViewer ) -declare_pass( EdgeProfiler ) -//declare_pass( GEPSplitter ) -declare_pass( GlobalsModRef ) -declare_pass( InstCount ) -declare_pass( InstructionNamer ) -declare_pass( LazyValueInfo ) -declare_pass( LCSSA ) -//declare_pass( LiveValues ) -declare_pass( LoopDependenceAnalysis ) -declare_pass( LoopExtractor ) -declare_pass( LoopSimplify ) -declare_pass( LoopStrengthReduce ) -declare_pass( LowerInvoke ) -declare_pass( LowerSwitch ) -declare_pass( MergeFunctions ) -declare_pass( NoAA ) -declare_pass( NoProfileInfo ) -declare_pass( OptimalEdgeProfiler ) -declare_pass( PartialInlining ) -//declare_pass( PartialSpecialization ) -declare_pass( PostDomOnlyPrinter ) -declare_pass( PostDomOnlyViewer ) -declare_pass( PostDomPrinter ) -declare_pass( PostDomViewer ) -declare_pass( ProfileEstimator ) -declare_pass( ProfileLoader ) -declare_pass( ProfileVerifier ) -declare_pass( ScalarEvolutionAliasAnalysis ) -declare_pass( SimplifyHalfPowrLibCalls ) -declare_pass( SingleLoopExtractor ) -declare_pass( StripNonDebugSymbols ) -declare_pass( StructRetPromotion ) -declare_pass( TailDuplication ) -declare_pass( UnifyFunctionExitNodes ) - -declare_pass( Internalize2 ) -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LLVM_PY_EXTRA_H */ - diff --git a/llvm/llvm_c_extra.h b/llvm/llvm_c_extra.h deleted file mode 100644 index 5728875..0000000 --- a/llvm/llvm_c_extra.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LLVM_C_EXTRA_H_ -#define LLVM_C_EXTRA_H_ - -#include - - -#ifdef __cplusplus - extern "C" { -#endif - -// Resurrect from llvm-c/Core.h -#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ -inline ty *unwrap(ref P) { \ - return reinterpret_cast(P); \ -} \ - \ -inline ref wrap(const ty *P) { \ - return reinterpret_cast(const_cast(P)); \ -} - -typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef; -typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; -typedef struct LLVMOpaqueNamedMD *LLVMNamedMDRef; -typedef struct LLVMOpaquePass *LLVMPassRef; - -#ifdef __cplusplus - } -#endif - -#endif //LLVM_C_EXTRA_H_ - diff --git a/llvm/passes.py b/llvm/passes.py index 4d7efb4..e69de29 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -1,417 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Pass managers and passes. - -This module provides the LLVM pass managers and the passes themselves. -All transformation passes listed at http://www.llvm.org/docs/Passes.html -are available. -""" - -import llvm # top-level, for common stuff -import llvm.core as core # module, function etc. -import llvm._core as _core # C wrappers -import llvm._util as _util # Utility functions - -import warnings -#===----------------------------------------------------------------------=== -# Pass manager builder -#===----------------------------------------------------------------------=== - -class PassManagerBuilder(object): - @staticmethod - def new(): - return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate()) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMPassManagerBuilderDispose(self.ptr) - - def populate(self, pm): - if isinstance(pm, FunctionPassManager): - return _core.LLVMPassManagerBuilderPopulateFunctionPassManager( - self.ptr, pm.ptr) - else: - return _core.LLVMPassManagerBuilderPopulateModulePassManager( - self.ptr, pm.ptr) - - - def _set_opt_level(self, optlevel): - _core.LLVMPassManagerBuilderSetOptLevel(self.ptr, optlevel) - - def _get_opt_level(self): - return _core.LLVMPassManagerBuilderGetOptLevel(self.ptr) - - opt_level = property(_get_opt_level, _set_opt_level) - - def _set_size_level(self, sizelevel): - _core.LLVMPassManagerBuilderSetSizeLevel(self.ptr, sizelevel) - - def _get_size_level(self): - return _core.LLVMPassManagerBuilderGetSizeLevel(self.ptr) - - size_level = property(_get_size_level, _set_size_level) - - def _set_vectorize(self, enable): - _core.LLVMPassManagerBuilderSetVectorize(self.ptr, int(bool(enable))) - - def _get_vectorize(self): - return bool(_core.LLVMPassManagerBuilderGetVectorize(self.ptr)) - - vectorize = property(_get_vectorize, _set_vectorize) - - def _set_loop_vectorize(self, enable): - if llvm.version >= (3, 2): - _core.LLVMPassManagerBuilderSetLoopVectorize(self.ptr, - int(bool(enable))) - elif enable: - warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.") - - def _get_loop_vectorize(self): - try: - return bool(_core.LLVMPassManagerBuilderGetLoopVectorize(self.ptr)) - except AttributeError: - return False - - loop_vectorize = property(_get_loop_vectorize, _set_loop_vectorize) - - def _set_disable_unit_at_a_time(self, disable): - return _core.LLVMPassManagerBuilderSetDisableUnitAtATime( - self.ptr, disable) - - def _get_disable_unit_at_a_time(self): - return _core.LLVMPassManagerBuilderGetDisableUnitAtATime( - self.ptr) - - disable_unit_at_a_time = property(_get_disable_unit_at_a_time, - _set_disable_unit_at_a_time) - - def _set_disable_unroll_loops(self, disable): - return _core.LLVMPassManagerBuilderGetDisableUnrollLoops( - self.ptr, disable) - - def _get_disable_unroll_loops(self): - return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(self.ptr) - - disable_unroll_loops = property(_get_disable_unroll_loops, - _set_disable_unroll_loops) - - def _set_disable_simplify_lib_calls(self, disable): - return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls( - self.ptr, disable) - - def _get_disable_simplify_lib_calls(self): - return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(self.ptr) - - disable_simplify_lib_calls = property(_get_disable_simplify_lib_calls, - _set_disable_simplify_lib_calls) - - def use_inliner_with_threshold(self, threshold): - _core.LLVMPassManagerBuilderUseInlinerWithThreshold(self.ptr, threshold) - -#===----------------------------------------------------------------------=== -# Pass manager -#===----------------------------------------------------------------------=== - -class PassManager(object): - - @staticmethod - def new(): - return PassManager(_core.LLVMCreatePassManager()) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposePassManager(self.ptr) - - def add(self, pass_obj): - '''Add a pass to the pass manager. - - pass_obj --- Either a Pass instance, a string name of a pass - ''' - if isinstance(pass_obj, Pass): - _util.check_is_unowned(pass_obj) - _core.LLVMAddPass(self.ptr, pass_obj.ptr) - pass_obj._own(self) # PassManager owns the pass - elif _util.isstring(pass_obj): - self._add_pass(pass_obj) - else: - raise llvm.LLVMException("invalid pass_id (%s)" % pass_obj) - - def _add_pass(self, pass_name): - status = _core.LLVMAddPassByName(self.ptr, pass_name) - if not status: - assert pass_name not in PASSES, "Registered but not found?" - raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) - - def run(self, module): - core.check_is_module(module) - return _core.LLVMRunPassManager(self.ptr, module.ptr) - -class FunctionPassManager(PassManager): - - @staticmethod - def new(module): - core.check_is_module(module) - ptr = _core.LLVMCreateFunctionPassManagerForModule(module.ptr) - return FunctionPassManager(ptr) - - def __init__(self, ptr): - PassManager.__init__(self, ptr) - - def initialize(self): - _core.LLVMInitializeFunctionPassManager(self.ptr) - - def run(self, fn): - core.check_is_function(fn) - return _core.LLVMRunFunctionPassManager(self.ptr, fn.ptr) - - def finalize(self): - _core.LLVMFinalizeFunctionPassManager(self.ptr) - - - -#===----------------------------------------------------------------------=== -# Passes -#===----------------------------------------------------------------------=== - -class Pass(llvm.Ownable): - '''Pass Inferface - ''' - def __init__(self, ptr): - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass) - self.__name = '' - - @staticmethod - def new(name): - '''Create a new pass by name. - - Note: Not all pass has a default constructor. LLVM will kill - the process if an the pass requires arguments to construct. - The error cannot be caught. - ''' - ptr = _core.LLVMCreatePassByName(name) - p = Pass(ptr) - p.__name = name - return p - - @property - def name(self): - '''The name used in PassRegistry. - ''' - return self.__name - - @property - def description(self): - return _core.LLVMGetPassName(self.ptr) - - def dump(self): - return _core.LLVMPassDump(self.ptr) - - -#===----------------------------------------------------------------------=== -# Target data -#===----------------------------------------------------------------------=== - -class TargetData(Pass): - - @staticmethod - def new(strrep): - return TargetData(_core.LLVMCreateTargetData(strrep)) - - def clone(self): - return TargetData.new(str(self)) - - def __str__(self): - return _core.LLVMTargetDataAsString(self.ptr) - - @property - def byte_order(self): - return _core.LLVMByteOrder(self.ptr) - - @property - def pointer_size(self): - return _core.LLVMPointerSize(self.ptr) - - @property - def target_integer_type(self): - ptr = _core.LLVMIntPtrType(self.ptr); - return core.IntegerType(ptr, core.TYPE_INTEGER) - - def size(self, ty): - core.check_is_type(ty) - return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr) - - def store_size(self, ty): - core.check_is_type(ty) - return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr) - - def abi_size(self, ty): - core.check_is_type(ty) - return _core.LLVMABISizeOfType(self.ptr, ty.ptr) - - def abi_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr) - - def callframe_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr) - - def preferred_alignment(self, ty_or_gv): - if isinstance(ty_or_gv, core.Type): - return _core.LLVMPreferredAlignmentOfType(self.ptr, - ty_or_gv.ptr) - elif isinstance(ty_or_gv, core.GlobalVariable): - return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, - ty_or_gv.ptr) - else: - raise core.LLVMException("argument is neither a type nor a global variable") - - def element_at_offset(self, ty, ofs): - core.check_is_type_struct(ty) - ofs = int(ofs) # ofs is unsigned long long - return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) - - def offset_of_element(self, ty, el): - core.check_is_type_struct(ty) - el = int(el) # el should be an int - return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el) - - -#===----------------------------------------------------------------------=== -# Target Library Info -#===----------------------------------------------------------------------=== - -class TargetLibraryInfo(Pass): - @staticmethod - def new(triple): - ptr = _core.LLVMCreateTargetLibraryInfo(triple) - return TargetLibraryInfo(ptr) - - -#===----------------------------------------------------------------------=== -# Target Transform Info -#===----------------------------------------------------------------------=== - -class TargetTransformInfo(Pass): - @staticmethod - def new(targetmachine): - llvm.require_version_at_least(3, 2) - ptr = _core.LLVMCreateTargetTransformInfo(targetmachine.ptr) - return TargetTransformInfo(ptr) - - -#===----------------------------------------------------------------------=== -# Helpers -#===----------------------------------------------------------------------=== - -def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False, - inline_threshold=2000, pm=True, fpm=True, mod=None): - ''' - tm --- The TargetMachine for which the passes are optimizing for. - The TargetMachine must stay alive until the pass managers - are removed. - opt --- [0-3] Optimization level. Default to 2. - loop_vectorize --- [boolean] Whether to use loop-vectorizer. - vectorize --- [boolean] Whether to use basic-block vectorizer. - inline_threshold --- [int] Threshold for the inliner. - features --- [str] CPU feature string. - pm --- [boolean] Whether to build a module-level pass-manager. - fpm --- [boolean] Whether to build a function-level pass-manager. - mod --- [Module] The module object for the FunctionPassManager. - ''' - if pm: - pm = PassManager.new() - if fpm: - if not mod: - raise TypeError("Keyword 'mod' must be defined") - fpm = FunctionPassManager.new(mod) - - # Populate PassManagers with target specific passes - pmb = PassManagerBuilder.new() - pmb.opt_level = opt - pmb.vectorize = vectorize - pmb.loop_vectorize = loop_vectorize - if inline_threshold: - pmb.use_inliner_with_threshold(inline_threshold) - if pm: - pm.add(tm.target_data.clone()) - pm.add(TargetLibraryInfo.new(tm.triple)) - if llvm.version >= (3, 2): - pm.add(TargetTransformInfo.new(tm)) - pmb.populate(pm) - - if fpm: - fpm.add(tm.target_data) - fpm.add(TargetLibraryInfo.new(tm.triple)) - if llvm.version >= (3, 2): - fpm.add(TargetTransformInfo.new(tm)) - pmb.populate(fpm) - fpm.initialize() - - from collections import namedtuple - return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm) - - -#===----------------------------------------------------------------------=== -# Misc. -#===----------------------------------------------------------------------=== - -# Intialize passes -PASSES = None - -def _dump_all_passes(): - passes_sep_by_line = _core.LLVMDumpPasses() - strip = lambda S : S.strip() - for line in passes_sep_by_line.splitlines(): - passarg, passname = map(strip, line.split('\t', 1)) - if passarg: - yield passarg, passname - -def _initialize_passes(): - global PASSES - _core.LLVMInitializePasses() - PASSES = dict(_dump_all_passes()) - - # build globals - def transform(name): - return "PASS_%s" % (name.upper().replace('-', '_')) - - global_symbols = globals() - for i in PASSES: - assert i not in global_symbols - global_symbols[transform(i)] = i - -_initialize_passes() - diff --git a/llvm/py3k_update.diff b/llvm/py3k_update.diff deleted file mode 100644 index 2bb11a9..0000000 --- a/llvm/py3k_update.diff +++ /dev/null @@ -1,973 +0,0 @@ ---- .\setup-win32.py (original) -+++ .\setup-win32.py (refactored) -@@ -145,10 +145,10 @@ - - # get llvm config - llvm_dir, llvm_build_dir, is_good = get_llvm_config() -- print "Using llvm-dir=" + llvm_dir + " and llvm-build-dir=" + llvm_build_dir -+ print("Using llvm-dir=" + llvm_dir + " and llvm-build-dir=" + llvm_build_dir) - if not is_good: -- print "Cannot find llvm-dir or llvm-build-dir" -- print "Try again with --llvm-dir=/path/to/llvm-top-dir --llvm-build-dir=/path/to/llvm/cmake/dir." -+ print("Cannot find llvm-dir or llvm-build-dir") -+ print("Try again with --llvm-dir=/path/to/llvm-top-dir --llvm-build-dir=/path/to/llvm/cmake/dir.") - return 1 - - # setup ---- .\setup.py (original) -+++ .\setup.py (refactored) -@@ -120,10 +120,10 @@ - # get llvm config - llvm_config, is_good = get_llvm_config() - if is_good: -- print "Using llvm-config=" + llvm_config -+ print("Using llvm-config=" + llvm_config) - else: -- print "Cannot invoke llvm-config (tried '%s')." % llvm_config -- print "Try again with --llvm-config=/path/to/llvm-config." -+ print("Cannot invoke llvm-config (tried '%s')." % llvm_config) -+ print("Try again with --llvm-config=/path/to/llvm-config.") - return 1 - - # setup ---- .\llvm\__init__.py (original) -+++ .\llvm\__init__.py (refactored) -@@ -68,12 +68,12 @@ - - def _own(self, owner): - if self.owner: -- raise LLVMException, "object already owned" -+ raise LLVMException("object already owned") - self.owner = owner - - def _disown(self): - if not self.owner: -- raise LLVMException, "not owned" -+ raise LLVMException("not owned") - self.owner = None - - def __del__(self): -@@ -135,15 +135,13 @@ - # Cacheables - #===----------------------------------------------------------------------=== - --class Cacheable(object): -+class Cacheable(object, metaclass=_ObjectCache): - """Objects that can be cached. - - Objects that wrap a PyCObject are cached to avoid "aliasing", i.e., - two Python objects each containing a PyCObject which internally points - to the same C pointer.""" - -- __metaclass__ = _ObjectCache -- - def forget(self): - _ObjectCache.forget(self) - ---- .\llvm\_util.py (original) -+++ .\llvm\_util.py (refactored) -@@ -45,11 +45,11 @@ - if not isinstance(obj, typ): - typ_str = typ.__name__ - msg = "argument not an instance of llvm.core.%s" % typ_str -- raise TypeError, msg -+ raise TypeError(msg) - - def check_is_unowned(ownable): - if ownable.owner: -- raise llvm.LLVMException, "object is already owned" -+ raise llvm.LLVMException("object is already owned") - - - #===----------------------------------------------------------------------=== ---- .\llvm\core.py (original) -+++ .\llvm\core.py (refactored) -@@ -297,7 +297,7 @@ - if isinstance(typ, PointerType) and \ - isinstance(typ.pointee, FunctionType): - return -- raise TypeError, "argument is neither a function nor a function pointer" -+ raise TypeError("argument is neither a function nor a function pointer") - - def _to_int(v): - if v: -@@ -341,9 +341,9 @@ - data = fileobj.read() - ret = _core.LLVMGetModuleFromBitcode(data) - if not ret: -- raise llvm.LLVMException, "Unable to create module from bitcode" -+ raise llvm.LLVMException("Unable to create module from bitcode") - elif isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - else: - return Module(ret) - -@@ -355,10 +355,9 @@ - data = fileobj.read() - ret = _core.LLVMGetModuleFromAssembly(data) - if not ret: -- raise llvm.LLVMException, \ -- "Unable to create module from assembly" -+ raise llvm.LLVMException("Unable to create module from assembly") - elif isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - else: - return Module(ret) - -@@ -437,7 +436,7 @@ - other.forget() # remove it from object cache - ret = _core.LLVMLinkModules(self.ptr, other.ptr) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - # Do not try to destroy the other module's llvm::Module*. - other._own(llvm.DummyOwner()) - -@@ -506,7 +505,7 @@ - error.""" - ret = _core.LLVMVerifyModule(self.ptr) - if ret != "": -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - - def to_bitcode(self, fileobj): - """Write bitcode representation of module to given file-like -@@ -514,7 +513,7 @@ - - data = _core.LLVMGetBitcodeFromModule(self.ptr) - if not data: -- raise llvm.LLVMException, "Unable to create bitcode" -+ raise llvm.LLVMException("Unable to create bitcode") - fileobj.write(data) - - -@@ -1236,7 +1235,7 @@ - check_is_module(module) - ptr = _core.LLVMGetNamedGlobal(module.ptr, name) - if not ptr: -- raise llvm.LLVMException, ("no global named `%s`" % name) -+ raise llvm.LLVMException("no global named `%s`" % name) - return _make_value(ptr) - - def delete(self): -@@ -1307,7 +1306,7 @@ - check_is_module(module) - ptr = _core.LLVMGetNamedFunction(module.ptr, name) - if not ptr: -- raise llvm.LLVMException, ("no function named `%s`" % name) -+ raise llvm.LLVMException("no function named `%s`" % name) - return _make_value(ptr) - - @staticmethod -@@ -2006,7 +2005,7 @@ - - ret = _core.LLVMLoadLibraryPermanently(filename) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - - def inline_function(call): - check_is_value(call) ---- .\llvm\ee.py (original) -+++ .\llvm\ee.py (refactored) -@@ -103,12 +103,11 @@ - return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, - ty_or_gv.ptr) - else: -- raise core.LLVMException, \ -- "argument is neither a type nor a global variable" -+ raise core.LLVMException("argument is neither a type nor a global variable") - - def element_at_offset(self, ty, ofs): - core.check_is_type_struct(ty) -- ofs = long(ofs) # ofs is unsigned long long -+ ofs = int(ofs) # ofs is unsigned long long - return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) - - def offset_of_element(self, ty, el): -@@ -185,7 +184,7 @@ - _util.check_is_unowned(module) - ret = _core.LLVMCreateExecutionEngine(module.ptr, int(force_interpreter)) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - return ExecutionEngine(ret, module) - - def __init__(self, ptr, module): -@@ -223,10 +222,10 @@ - def remove_module(self, module): - core.check_is_module(module) - if module.owner != self: -- raise llvm.LLVMException, "module is not owned by self" -+ raise llvm.LLVMException("module is not owned by self") - ret = _core.LLVMRemoveModule2(self.ptr, module.ptr) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - return core.Module(ret) - - @property ---- .\llvm\passes.py (original) -+++ .\llvm\passes.py (refactored) -@@ -245,8 +245,7 @@ - elif tgt_data_or_pass_id in _pass_creator: - self._add_pass(tgt_data_or_pass_id) - else: -- raise llvm.LLVMException, \ -- ("invalid pass_id (%s)" % str(tgt_data_or_pass_id)) -+ raise llvm.LLVMException("invalid pass_id (%s)" % str(tgt_data_or_pass_id)) - - def _add_target_data(self, tgt): - _core.LLVMAddTargetData(tgt.ptr, self.ptr) ---- .\test\JITTutorial1.py (original) -+++ .\test\JITTutorial1.py (refactored) -@@ -28,4 +28,4 @@ - - bldr.ret (tmp_2) - --print module -+print(module) ---- .\test\JITTutorial2.py (original) -+++ .\test\JITTutorial2.py (refactored) -@@ -47,4 +47,4 @@ - recur_2 = bldr.call (gcd, (x_sub_y, y,), "tmp") - bldr.ret (recur_2) - --print module -+print(module) ---- .\test\asm.py (original) -+++ .\test\asm.py (refactored) -@@ -9,9 +9,9 @@ - - # write it's assembly representation to a file - asm = str(m) --print >> file("/tmp/testasm.ll", "w"), asm -+print(asm, file=file("/tmp/testasm.ll", "w")) - - # read it back into a module - m2 = Module.from_assembly(file("/tmp/testasm.ll")) --print m2 -+print(m2) - ---- .\test\call-jit-ctypes.py (original) -+++ .\test\call-jit-ctypes.py (refactored) -@@ -42,7 +42,7 @@ - - if 0: - # print the created module -- print my_module -+ print(my_module) - - # compile the function - ee = ExecutionEngine.new(my_module) ---- .\test\example-jit.py (original) -+++ .\test\example-jit.py (refactored) -@@ -29,5 +29,5 @@ - retval = ee.run_function(f_sum, [arg1, arg2]) - - # The return value is also GenericValue. Let's print it. --print "returned", retval.as_int() -+print("returned", retval.as_int()) - ---- .\test\example.py (original) -+++ .\test\example.py (refactored) -@@ -41,5 +41,5 @@ - - # We've completed the definition now! Let's see the LLVM assembly - # language representation of what we've created: --print my_module -+print(my_module) - ---- .\test\intrinsic.py (original) -+++ .\test\intrinsic.py (refactored) -@@ -16,7 +16,7 @@ - val = Constant.int(Type.int(), 42) - bswap = Function.intrinsic(mod, INTR_BSWAP, [Type.int()]) - b.call(bswap, [val]) --print mod -+print(mod) - - # the output is: - # -@@ -50,7 +50,7 @@ - onemc2 = b.sub(one, cos2, "onemc2") - sin = b.call(sqrt, [onemc2], "sin") - b.ret(sin) --print mod -+print(mod) - - # - # ; ModuleID = 'test' ---- .\test\objcache.py (original) -+++ .\test\objcache.py (refactored) -@@ -4,17 +4,17 @@ - - def check(a, b): - if a is b: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - - def check_isnot(a, b): - if not (a is b): -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - --print "Testing module aliasing ..", -+print("Testing module aliasing ..", end=' ') - m1 = Module.new('a') - t = Type.int() - ft = Type.function(t, [t]) -@@ -22,75 +22,75 @@ - m2 = f1.module - check(m1, m2) - --print "Testing global vairable aliasing 1 .. ", -+print("Testing global vairable aliasing 1 .. ", end=' ') - gv1 = GlobalVariable.new(m1, t, "gv") - gv2 = GlobalVariable.get(m1, "gv") - check(gv1, gv2) - --print "Testing global vairable aliasing 2 .. ", -+print("Testing global vairable aliasing 2 .. ", end=' ') - gv3 = m1.global_variables[0] - check(gv1, gv3) - --print "Testing global vairable aliasing 3 .. ", -+print("Testing global vairable aliasing 3 .. ", end=' ') - gv2 = None - gv3 = None - gv1.delete() - gv4 = GlobalVariable.new(m1, t, "gv") - check_isnot(gv1, gv4) - --print "Testing function aliasing 1 ..", -+print("Testing function aliasing 1 ..", end=' ') - b1 = f1.append_basic_block('entry') - f2 = b1.function - check(f1, f2) - --print "Testing function aliasing 2 ..", -+print("Testing function aliasing 2 ..", end=' ') - f3 = m1.get_function_named("func") - check(f1, f3) - --print "Testing function aliasing 3 ..", -+print("Testing function aliasing 3 ..", end=' ') - f4 = Function.get_or_insert(m1, ft, "func") - check(f1, f4) - --print "Testing function aliasing 4 ..", -+print("Testing function aliasing 4 ..", end=' ') - f5 = Function.get(m1, "func") - check(f1, f5) - --print "Testing function aliasing 5 ..", -+print("Testing function aliasing 5 ..", end=' ') - f6 = m1.get_or_insert_function(ft, "func") - check(f1, f6) - --print "Testing function aliasing 6 ..", -+print("Testing function aliasing 6 ..", end=' ') - f7 = m1.functions[0] - check(f1, f7) - --print "Testing argument aliasing .. ", -+print("Testing argument aliasing .. ", end=' ') - a1 = f1.args[0] - a2 = f1.args[0] - check(a1, a2) - --print "Testing basic block aliasing 1 .. ", -+print("Testing basic block aliasing 1 .. ", end=' ') - b2 = f1.basic_blocks[0] - check(b1, b2) - --print "Testing basic block aliasing 2 .. ", -+print("Testing basic block aliasing 2 .. ", end=' ') - b3 = f1.get_entry_basic_block() - check(b1, b3) - --print "Testing basic block aliasing 3 .. ", -+print("Testing basic block aliasing 3 .. ", end=' ') - b31 = f1.entry_basic_block - check(b1, b31) - --print "Testing basic block aliasing 4 .. ", -+print("Testing basic block aliasing 4 .. ", end=' ') - bldr = Builder.new(b1) - b4 = bldr.basic_block - check(b1, b4) - --print "Testing basic block aliasing 5 .. ", -+print("Testing basic block aliasing 5 .. ", end=' ') - i1 = bldr.ret_void() - b5 = i1.basic_block - check(b1, b5) - --print "Testing instruction aliasing 1 .. ", -+print("Testing instruction aliasing 1 .. ", end=' ') - i2 = b5.instructions[0] - check(i1, i2) - -@@ -100,9 +100,9 @@ - v2 = phi.get_incoming_value(0) - b6 = phi.get_incoming_block(0) - --print "Testing PHI / basic block aliasing 5 .. ", -+print("Testing PHI / basic block aliasing 5 .. ", end=' ') - check(b1, b6) - --print "Testing PHI / value aliasing .. ", -+print("Testing PHI / value aliasing .. ", end=' ') - check(f1.args[0], v2) - ---- .\test\operands.py (original) -+++ .\test\operands.py (refactored) -@@ -28,9 +28,9 @@ - def __init__(self): pass - def read(self): return test_module - m = Module.from_assembly(strstream()) --print "-"*60 --print m --print "-"*60 -+print("-"*60) -+print(m) -+print("-"*60) - - test_func = m.get_function_named("test_func") - prod = m.get_function_named("prod") -@@ -38,16 +38,16 @@ - #===----------------------------------------------------------------------=== - # test operands - --print -+print() - i1 = test_func.basic_blocks[0].instructions[0] - i2 = test_func.basic_blocks[0].instructions[1] --print "Testing User.operand_count ..", -+print("Testing User.operand_count ..", end=' ') - if i1.operand_count == 3 and i2.operand_count == 2: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - --print "Testing User.operands ..", -+print("Testing User.operands ..", end=' ') - c1 = i1.operands[0] is prod - c2 = i1.operands[1] is test_func.args[0] - c3 = i1.operands[2] is test_func.args[1] -@@ -56,22 +56,22 @@ - c6 = len(i1.operands) == 3 - c7 = len(i2.operands) == 2 - if c1 and c2 and c3 and c5 and c6 and c7: -- print "OK" -+ print("OK") - else: -- print "FAIL" --print -+ print("FAIL") -+print() - - #===----------------------------------------------------------------------=== - # show test_function - --print "Examining test_function `test_test_func':" -+print("Examining test_function `test_test_func':") - idx = 1 - for inst in test_func.basic_blocks[0].instructions: -- print "Instruction #%d:" % (idx,) -- print " operand_count =", inst.operand_count -- print " operands:" -+ print("Instruction #%d:" % (idx,)) -+ print(" operand_count =", inst.operand_count) -+ print(" operands:") - oidx = 1 - for op in inst.operands: -- print " %d: %s" % (oidx, repr(op)) -+ print(" %d: %s" % (oidx, repr(op))) - oidx += 1 - idx += 1 ---- .\test\passes.py (original) -+++ .\test\passes.py (refactored) -@@ -36,8 +36,8 @@ - } - """ - m = Module.from_assembly(strstream(asm)) --print "-"*72 --print m -+print("-"*72) -+print(m) - - # Let's run a module-level inlining pass. First, create a pass manager. - pm = PassManager.new() -@@ -55,8 +55,8 @@ - del pm - - # Print the result. Note the change in @test2. --print "-"*72 --print m -+print("-"*72) -+print(m) - - - # Let's run a DCE pass on the the function 'test1' now. First create a -@@ -73,5 +73,5 @@ - fpm.run( m.get_function_named('test1') ) - - # Print the result. Note the change in @test1. --print "-"*72 --print m -+print("-"*72) -+print(m) ---- .\test\test.py (original) -+++ .\test\test.py (refactored) -@@ -69,7 +69,7 @@ - - # done - if gc.garbage: -- print "garbage = ", gc.garbage -+ print("garbage = ", gc.garbage) - - - main() ---- .\test\testall.py (original) -+++ .\test\testall.py (refactored) -@@ -15,12 +15,12 @@ - - - def do_llvmexception(): -- print " Testing class LLVMException" -+ print(" Testing class LLVMException") - e = LLVMException() - - - def do_ownable(): -- print " Testing class Ownable" -+ print(" Testing class Ownable") - o = Ownable(None, lambda x: None) - try: - o._own(None) -@@ -30,7 +30,7 @@ - - - def do_misc(): -- print " Testing miscellaneous functions" -+ print(" Testing miscellaneous functions") - try: - load_library_permanently("/usr/lib/libm.so") - except LLVMException: -@@ -42,14 +42,14 @@ - - - def do_llvm(): -- print " Testing module llvm" -+ print(" Testing module llvm") - do_llvmexception() - do_ownable() - do_misc() - - - def do_module(): -- print " Testing class Module" -+ print(" Testing class Module") - m = Module.new('test') - m.target = 'a' - a = m.target -@@ -101,7 +101,7 @@ - - - def do_type(): -- print " Testing class Type" -+ print(" Testing class Type") - for i in range(1,100): - Type.int(i) - Type.float() -@@ -151,14 +151,14 @@ - - - def do_typehandle(): -- print " Testing class TypeHandle" -+ print(" Testing class TypeHandle") - th = TypeHandle.new(Type.opaque()) - ts = Type.struct([ Type.int(), Type.pointer(th.type) ]) - th.type.refine(ts) - - - def do_value(): -- print " Testing class Value" -+ print(" Testing class Value") - k = Constant.int(ti, 42) - k.name = 'a' - s = k.name -@@ -186,7 +186,7 @@ - - - def do_constant(): -- print " Testing class Constant" -+ print(" Testing class Constant") - Constant.null(ti) - Constant.all_ones(ti) - Constant.undef(ti) -@@ -231,7 +231,7 @@ - - - def do_global_value(): -- print " Testing class GlobalValue" -+ print(" Testing class GlobalValue") - m = Module.new('a') - gv = GlobalVariable.new(m, Type.int(), 'b') - s = gv.is_declaration -@@ -247,7 +247,7 @@ - - - def do_global_variable(): -- print " Testing class GlobalVariable" -+ print(" Testing class GlobalVariable") - m = Module.new('a') - gv = GlobalVariable.new(m, Type.int(), 'b') - gv = GlobalVariable.get(m, 'b') -@@ -260,7 +260,7 @@ - - - def do_argument(): -- print " Testing class Argument" -+ print(" Testing class Argument") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -272,7 +272,7 @@ - - - def do_function(): -- print " Testing class Function" -+ print(" Testing class Function") - ft = Type.function(ti, [ti]*20) - zz = Function.new(Module.new('z'), ft, 'foobar') - del zz -@@ -307,7 +307,7 @@ - - - def do_instruction(): -- print " Testing class Instruction" -+ print(" Testing class Instruction") - m = Module.new('a') - ft = Type.function(ti, [ti]*20) - f = Function.new(m, ft, 'func') -@@ -320,7 +320,7 @@ - - - def do_callorinvokeinstruction(): -- print " Testing class CallOrInvokeInstruction" -+ print(" Testing class CallOrInvokeInstruction") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -337,7 +337,7 @@ - - - def do_phinode(): -- print " Testing class PhiNode" -+ print(" Testing class PhiNode") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -354,7 +354,7 @@ - - - def do_switchinstruction(): -- print " Testing class SwitchInstruction" -+ print(" Testing class SwitchInstruction") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -365,7 +365,7 @@ - - - def do_basicblock(): -- print " Testing class BasicBlock" -+ print(" Testing class BasicBlock") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -395,7 +395,7 @@ - - - def do_builder(): -- print " Testing class Builder" -+ print(" Testing class Builder") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -488,7 +488,7 @@ - - - def do_llvm_core(): -- print " Testing module llvm.core" -+ print(" Testing module llvm.core") - do_module() - do_type() - do_typehandle() -@@ -508,7 +508,7 @@ - - - def do_targetdata(): -- print " Testing class TargetData" -+ print(" Testing class TargetData") - t = TargetData.new('') - v = str(t) - v = t.byte_order -@@ -530,7 +530,7 @@ - - - def do_genericvalue(): -- print " Testing class GenericValue" -+ print(" Testing class GenericValue") - v = GenericValue.int(ti, 1) - v = GenericValue.int_signed(ti, 1) - v = GenericValue.real(Type.float(), 3.14) -@@ -540,7 +540,7 @@ - - - def do_executionengine(): -- print " Testing class ExecutionEngine" -+ print(" Testing class ExecutionEngine") - m = Module.new('a') - ee = ExecutionEngine.new(m, True) - ft = Type.function(ti, []) -@@ -567,14 +567,14 @@ - - - def do_llvm_ee(): -- print " Testing module llvm.ee" -+ print(" Testing module llvm.ee") - do_targetdata() - do_genericvalue() - do_executionengine() - - - def do_passmanager(): -- print " Testing class PassManager" -+ print(" Testing class PassManager") - pm = PassManager.new() - pm.add(TargetData.new('')) - for i in [getattr(llvm.passes, x) for x in \ -@@ -586,7 +586,7 @@ - - - def do_functionpassmanager(): -- print " Testing class FunctionPassManager" -+ print(" Testing class FunctionPassManager") - m = Module.new('a') - ft = Type.function(ti, []) - f = m.add_function(ft, 'func') -@@ -602,13 +602,13 @@ - - - def do_llvm_passes(): -- print " Testing module llvm.passes" -+ print(" Testing module llvm.passes") - do_passmanager() - do_functionpassmanager() - - - def main(): -- print "Testing package llvm" -+ print("Testing package llvm") - do_llvm() - do_llvm_core() - do_llvm_ee() ---- .\test\testattrs.py (original) -+++ .\test\testattrs.py (refactored) -@@ -1,7 +1,7 @@ - #!/usr/bin/env python - - from llvm.core import * --from cStringIO import StringIO -+from io import StringIO - - - def make_module(): ---- .\test\typehandle.py (original) -+++ .\test\typehandle.py (refactored) -@@ -16,4 +16,4 @@ - m.add_type_name("struct.node", th.type) - - # show what we created --print m -+print(m) ---- .\test\uses.py (original) -+++ .\test\uses.py (refactored) -@@ -13,11 +13,11 @@ - tmp3 = bld.add(tmp1, f.args[2], "tmp3") - bld.ret(tmp3) - --print "-"*60 --print m --print "-"*60 -+print("-"*60) -+print(m) -+print("-"*60) - --print "Testing use count ..", -+print("Testing use count ..", end=' ') - c1 = f.args[0].use_count == 1 - c2 = f.args[1].use_count == 1 - c3 = f.args[2].use_count == 1 -@@ -25,11 +25,11 @@ - c5 = tmp2.use_count == 0 - c6 = tmp3.use_count == 1 - if c1 and c2 and c3 and c4 and c5 and c6: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - --print "Testing uses ..", -+print("Testing uses ..", end=' ') - c1 = f.args[0].uses[0] is tmp1 - c2 = len(f.args[0].uses) == 1 - c3 = f.args[1].uses[0] is tmp2 -@@ -40,6 +40,6 @@ - c8 = len(tmp2.uses) == 0 - c9 = len(tmp3.uses) == 1 - if c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8 and c9: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") ---- .\tools\intrgen.py (original) -+++ .\tools\intrgen.py (refactored) -@@ -26,7 +26,7 @@ - idx = 1 - for i in intr: - s = 'INTR_' + i.upper() -- print '%s = %d' % (s.ljust(maxw), idx) -+ print('%s = %d' % (s.ljust(maxw), idx)) - idx += 1 - - gen(sys.argv[1]) ---- .\tools\intrs_for_doc.py (original) -+++ .\tools\intrs_for_doc.py (refactored) -@@ -21,5 +21,5 @@ - outf = open(OUTF, 'wt') - i = 0 - while i < len(intrs): -- print >>outf, "`" + "`,`".join(intrs[i:min(i+NCOLS,len(intrs)+1)]) + "`" -+ print("`" + "`,`".join(intrs[i:min(i+NCOLS,len(intrs)+1)]) + "`", file=outf) - i += NCOLS ---- .\www\makeweb.py (original) -+++ .\www\makeweb.py (refactored) -@@ -52,7 +52,7 @@ - - - def _rmtree_warn(fn, path, excinfo): -- print "** WARNING **: error while doing %s on %s" % (fn, path) -+ print("** WARNING **: error while doing %s on %s" % (fn, path)) - - - def _can_skip(opts, infile, outfile): -@@ -67,14 +67,14 @@ - cmd = cmdfn(opts, infile, outfile_actual) - if _can_skip(opts, infile, outfile_actual): - if opts.verbose >= 2: -- print "up to date %s -> %s" % (infile, outfile_actual) -+ print("up to date %s -> %s" % (infile, outfile_actual)) - return - if cmd: - # do cmd - if opts.verbose: -- print "process %s -> %s" % (infile, outfile_actual) -+ print("process %s -> %s" % (infile, outfile_actual)) - if opts.verbose >= 3: -- print "command is [%s]" % cmd -+ print("command is [%s]" % cmd) - if not opts.dryrun: - os.system(cmd) - # else if cmd is None, do nothing -@@ -83,7 +83,7 @@ - # nothing matched, default action is to copy - if not _can_skip(opts, infile, outfile): - if opts.verbose: -- print "copying %s -> %s" % (infile, outfile) -+ print("copying %s -> %s" % (infile, outfile)) - if not opts.dryrun: - shutil.copy(infile, outfile) - -@@ -95,14 +95,14 @@ - - # if it exists, it must be a dir! - if odexists and not os.path.isdir(outdir): -- print "** WARNING **: output dir '%s' exists but is " \ -- "not a dir, skipping" % outdir -+ print("** WARNING **: output dir '%s' exists but is " \ -+ "not a dir, skipping" % outdir) - return - - # make outdir if not existing - if not odexists: - if opts.verbose: -- print "creating %s" % outdir -+ print("creating %s" % outdir) - if not opts.dryrun: - os.mkdir(outdir) - -@@ -114,8 +114,8 @@ - # process files - if os.path.isfile(inp): - if os.path.exists(outp) and not os.path.isfile(outp): -- print "** WARNING **: output '%s' corresponding to " \ -- "input '%s' is not a file, skipping" % (outp, inp) -+ print("** WARNING **: output '%s' corresponding to " \ -+ "input '%s' is not a file, skipping" % (outp, inp)) - else: - process_file(opts, inp, outp) - -@@ -124,15 +124,15 @@ - # if dir is in skip list, silently ignore - if elem in DIR_SKIP_TBL: - if opts.verbose >= 3: -- print "skipping %s" % inp -+ print("skipping %s" % inp) - continue - # just recurse - make(opts, inp, outp) - - # neither a file nor a dir - else: -- print "** WARNING **: input '%s' is neither file nor " \ -- "dir, skipping" % inp -+ print("** WARNING **: input '%s' is neither file nor " \ -+ "dir, skipping" % inp) - - - def get_opts(): -@@ -173,14 +173,14 @@ - def main(): - opts, src, dest = get_opts() - if opts.verbose >= 3: -- print ("running with options:\nsrc = [%s]\ndest = [%s]\nverbose = [%d]\n" +\ -+ print(("running with options:\nsrc = [%s]\ndest = [%s]\nverbose = [%d]\n" +\ - "dry-run = [%d]\nclean-first = [%d]\nforce = [%d]") %\ -- (src, dest, opts.verbose, opts.dryrun, opts.clean, opts.force) -+ (src, dest, opts.verbose, opts.dryrun, opts.clean, opts.force)) - if opts.dryrun and opts.verbose == 0: - opts.verbose = 1 - if opts.clean: - if opts.dryrun or opts.verbose: -- print "removing tree %s" % dest -+ print("removing tree %s" % dest) - if not opts.dryrun: - os.rmtree(dest, True, _rmtree_warn) - make(opts, src, dest) diff --git a/llvm/py3k_update.output b/llvm/py3k_update.output deleted file mode 100644 index 4ea51a4..0000000 --- a/llvm/py3k_update.output +++ /dev/null @@ -1,62 +0,0 @@ -C:\Users\AndrewBC\src\llvm-py>python "C:\Program Files\Python27\Tools\Scripts\2to3.py" -w -f all -f idioms . > llvm/py3k_update.diff -RefactoringTool: Skipping implicit fixer: buffer -RefactoringTool: Skipping implicit fixer: set_literal -RefactoringTool: Skipping implicit fixer: ws_comma -RefactoringTool: Refactored .\setup-win32.py -RefactoringTool: Refactored .\setup.py -RefactoringTool: Refactored .\llvm\__init__.py -RefactoringTool: Refactored .\llvm\_util.py -RefactoringTool: Refactored .\llvm\core.py -RefactoringTool: Refactored .\llvm\ee.py -RefactoringTool: Refactored .\llvm\passes.py -RefactoringTool: Refactored .\test\JITTutorial1.py -RefactoringTool: Refactored .\test\JITTutorial2.py -RefactoringTool: Refactored .\test\asm.py -RefactoringTool: Refactored .\test\call-jit-ctypes.py -RefactoringTool: Refactored .\test\example-jit.py -RefactoringTool: Refactored .\test\example.py -RefactoringTool: Refactored .\test\intrinsic.py -RefactoringTool: Refactored .\test\objcache.py -RefactoringTool: Refactored .\test\operands.py -RefactoringTool: Refactored .\test\passes.py -RefactoringTool: Refactored .\test\test.py -RefactoringTool: Refactored .\test\testall.py -RefactoringTool: Refactored .\test\testattrs.py -RefactoringTool: Refactored .\test\typehandle.py -RefactoringTool: Refactored .\test\uses.py -RefactoringTool: Refactored .\tools\intrgen.py -RefactoringTool: Refactored .\tools\intrs_for_doc.py -RefactoringTool: Refactored .\www\makeweb.py -RefactoringTool: Can't parse .\www\src\examples\JITTutorial1.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) -RefactoringTool: Can't parse .\www\src\examples\JITTutorial2.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) -RefactoringTool: Files that need to be modified: -RefactoringTool: .\setup-win32.py -RefactoringTool: .\setup.py -RefactoringTool: .\llvm\__init__.py -RefactoringTool: .\llvm\_util.py -RefactoringTool: .\llvm\core.py -RefactoringTool: .\llvm\ee.py -RefactoringTool: .\llvm\passes.py -RefactoringTool: .\test\JITTutorial1.py -RefactoringTool: .\test\JITTutorial2.py -RefactoringTool: .\test\asm.py -RefactoringTool: .\test\call-jit-ctypes.py -RefactoringTool: .\test\example-jit.py -RefactoringTool: .\test\example.py -RefactoringTool: .\test\intrinsic.py -RefactoringTool: .\test\objcache.py -RefactoringTool: .\test\operands.py -RefactoringTool: .\test\passes.py -RefactoringTool: .\test\test.py -RefactoringTool: .\test\testall.py -RefactoringTool: .\test\testattrs.py -RefactoringTool: .\test\typehandle.py -RefactoringTool: .\test\uses.py -RefactoringTool: .\tools\intrgen.py -RefactoringTool: .\tools\intrs_for_doc.py -RefactoringTool: .\www\makeweb.py -RefactoringTool: There were 2 errors: -RefactoringTool: Can't parse .\www\src\examples\JITTutorial1.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) -RefactoringTool: Can't parse .\www\src\examples\JITTutorial2.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) - -C:\Users\AndrewBC\src\llvm-py> \ No newline at end of file diff --git a/llvm/tbaa.py b/llvm/tbaa.py deleted file mode 100644 index b510ce2..0000000 --- a/llvm/tbaa.py +++ /dev/null @@ -1,51 +0,0 @@ -from llvm.core import * - -class TBAABuilder(object): - '''Simplify creation of TBAA metadata. - - Each TBAABuidler object operates on a module. - User can create multiple TBAABuilder on a module - ''' - - def __init__(self, module, rootid): - ''' - module --- the module to use. - root --- string name to identify the TBAA root. - ''' - self.__module = module - self.__rootid = rootid - self.__rootmd = self.__new_md(rootid) - - @classmethod - def new(cls, module, rootid): - return cls(module, rootid) - - def get_node(self, name, parent=None, const=False): - '''Returns a MetaData object representing a TBAA node. - - Use loadstore_instruction.set_metadata('tbaa', node) to - bind a type to a memory. - ''' - parent = parent or self.root - const = Constant.int(Type.int(), int(bool(const))) - return self.__new_md(name, parent, const) - - @property - def module(self): - return self.__module - - @property - def root(self): - return self.__rootmd - - @property - def root_name(self): - return self.__rootid - - def __new_md(self, *args): - contents = list(args) - for i, v in enumerate(contents): - if isinstance(v, str): - contents[i] = MetaDataString.get(self.module, v) - return MetaData.get(self.module, contents) - diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py deleted file mode 100644 index 05b7d72..0000000 --- a/llvm/test_llvmpy.py +++ /dev/null @@ -1,1249 +0,0 @@ -""" -LLVM tests -""" -import os -import sys -import math -import shutil -import unittest -import subprocess -import tempfile -import contextlib - -is_py3k = bool(sys.version_info[0] == 3) -BITS = tuple.__itemsize__ * 8 - -if is_py3k: - from io import StringIO -else: - from cStringIO import StringIO - - -import llvm -from llvm.core import (Module, Type, GlobalVariable, Function, Builder, - Constant, MetaData, MetaDataString, inline_function) -from llvm.ee import EngineBuilder -import llvm.core as lc -import llvm.passes as lp -import llvm.ee as le - - -tests = [] - - -# --------------------------------------------------------------------------- - -if sys.version_info[:2] <= (2, 6): - # create custom TestCase - class TestCase(unittest.TestCase): - def assertIn(self, item, container): - self.assertTrue(item in container) - - def assertNotIn(self, item, container): - self.assertFalse(item in container) - - def assertLess(self, a, b): - self.assertTrue(a < b) - - def assertIs(self, a, b): - self.assertTrue(a is b) - - @contextlib.contextmanager - def assertRaises(self, exc): - try: - yield - except exc: - pass - else: - raise self.failureException("Did not raise %s" % exc) - -else: - TestCase = unittest.TestCase - - -# --------------------------------------------------------------------------- - -class TestAsm(TestCase): - def setUp(self): - self.tmpdir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.tmpdir) - - def test_asm(self): - # create a module - m = Module.new('module1') - m.add_global_variable(Type.int(), 'i') - - # write it's assembly representation to a file - asm = str(m) - - testasm_ll = os.path.join(self.tmpdir, 'testasm.ll') - with open(testasm_ll, "w") as fout: - fout.write(asm) - - # read it back into a module - with open(testasm_ll) as fin: - m2 = Module.from_assembly(fin) - # The default `m.id` is ''. - m2.id = m.id # Copy the name from `m` - - self.assertEqual(str(m2).strip(), asm.strip()) - - def test_bitcode(self): - # create a module - m = Module.new('module1') - m.add_global_variable(Type.int(), 'i') - - # write it's assembly representation to a file - asm = str(m) - - testasm_bc = os.path.join(self.tmpdir, 'testasm.bc') - with open(testasm_bc, "wb") as fout: - m.to_bitcode(fout) - - # read it back into a module - with open(testasm_bc, "rb") as fin: - m2 = Module.from_bitcode(fin) - # The default `m.id` is ''. - m2.id = m.id # Copy the name from `m` - - self.assertEqual(str(m2).strip(), asm.strip()) - -tests.append(TestAsm) - -# --------------------------------------------------------------------------- - -class TestAttr(TestCase): - def make_module(self): - test_module = """ - define i32 @sum(i32, i32) { - entry: - %2 = add i32 %0, %1 - ret i32 %2 - } - """ - return Module.from_assembly(StringIO(test_module)) - - def test_align(self): - m = self.make_module() - f = m.get_function_named('sum') - f.args[0].alignment = 16 - self.assert_("align 16" in str(f)) - self.assertEqual(f.args[0].alignment, 16) - -tests.append(TestAttr) - -# --------------------------------------------------------------------------- - -class TestAtomic(TestCase): - orderings = ['unordered', 'monotonic', 'acquire', - 'release', 'acq_rel', 'seq_cst'] - - atomic_op = ['xchg', 'add', 'sub', 'and', 'nand', 'or', 'xor', - 'max', 'min', 'umax', 'umin'] - - def test_atomic_cmpxchg(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - old = bldr.load(ptr) - new = Constant.int(Type.int(), 1234) - - for ordering in self.orderings: - inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) - self.assertEqual(ordering, str(inst).strip().split(' ')[-1]) - - inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) - self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) - - def test_atomic_rmw(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - old = bldr.load(ptr) - val = Constant.int(Type.int(), 1234) - - for ordering in self.orderings: - inst = bldr.atomic_rmw('xchg', ptr, val, ordering) - self.assertEqual(ordering, str(inst).split(' ')[-1]) - - for op in self.atomic_op: - inst = bldr.atomic_rmw(op, ptr, val, ordering) - self.assertEqual(op, str(inst).strip().split(' ')[3]) - - inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False) - self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) - - for op in self.atomic_op: - atomic_op = getattr(bldr, 'atomic_%s' % op) - inst = atomic_op(ptr, val, ordering) - self.assertEqual(op, str(inst).strip().split(' ')[3]) - - def test_atomic_ldst(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - val = Constant.int(Type.int(), 1234) - - for ordering in self.orderings: - loaded = bldr.atomic_load(ptr, ordering) - self.assert_('load atomic' in str(loaded)) - self.assertEqual(ordering, - str(loaded).strip().split(' ')[-3].rstrip(',')) - self.assert_('align 1' in str(loaded)) - - stored = bldr.atomic_store(loaded, ptr, ordering) - self.assert_('store atomic' in str(stored)) - self.assertEqual(ordering, - str(stored).strip().split(' ')[-3].rstrip(',')) - self.assert_('align 1' in str(stored)) - - fenced = bldr.fence(ordering) - self.assertEqual(['fence', ordering], - str(fenced).strip().split(' ')) - -tests.append(TestAtomic) - -# --------------------------------------------------------------------------- - -class TestConstExpr(TestCase): - - def test_constexpr_opcode(self): - mod = Module.new('test_constexpr_opcode') - func = mod.add_function(Type.function(Type.void(), []), name="foo") - builder = Builder.new(func.append_basic_block('entry')) - a = builder.inttoptr(Constant.int(Type.int(), 123), - Type.pointer(Type.int())) - self.assertTrue(isinstance(a, lc.ConstantExpr)) - self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) - self.assertEqual(a.opcode_name, "inttoptr") - -tests.append(TestConstExpr) - -# --------------------------------------------------------------------------- - -class TestOperands(TestCase): - # implement a test function - test_module = """ -define i32 @prod(i32, i32) { -entry: - %2 = mul i32 %0, %1 - ret i32 %2 -} - -define i32 @test_func(i32, i32, i32) { -entry: - %tmp1 = call i32 @prod(i32 %0, i32 %1) - %tmp2 = add i32 %tmp1, %2 - %tmp3 = add i32 %tmp2, 1 - %tmp4 = add i32 %tmp3, -1 - %tmp5 = add i64 -81985529216486895, 12297829382473034410 - ret i32 %tmp4 -} -""" - def test_operands(self): - m = Module.from_assembly(StringIO(self.test_module)) - - test_func = m.get_function_named("test_func") - prod = m.get_function_named("prod") - - # test operands - i1 = test_func.basic_blocks[0].instructions[0] - i2 = test_func.basic_blocks[0].instructions[1] - i3 = test_func.basic_blocks[0].instructions[2] - i4 = test_func.basic_blocks[0].instructions[3] - i5 = test_func.basic_blocks[0].instructions[4] - - self.assertEqual(i1.operand_count, 3) - self.assertEqual(i2.operand_count, 2) - - self.assertEqual(i3.operands[1].z_ext_value, 1) - self.assertEqual(i3.operands[1].s_ext_value, 1) - self.assertEqual(i4.operands[1].z_ext_value, 0xffffffff) - self.assertEqual(i4.operands[1].s_ext_value, -1) - self.assertEqual(i5.operands[0].s_ext_value, -81985529216486895) - self.assertEqual(i5.operands[1].z_ext_value, 12297829382473034410) - - self.assert_(i1.operands[-1] is prod) - self.assert_(i1.operands[0] is test_func.args[0]) - self.assert_(i1.operands[1] is test_func.args[1]) - self.assert_(i2.operands[0] is i1) - self.assert_(i2.operands[1] is test_func.args[2]) - self.assertEqual(len(i1.operands), 3) - self.assertEqual(len(i2.operands), 2) - - self.assert_(i1.called_function is prod) - -tests.append(TestOperands) - -# --------------------------------------------------------------------------- - -class TestPasses(TestCase): - # Create a module. - asm = """ - -define i32 @test() nounwind { - ret i32 42 -} - -define i32 @test1() nounwind { -entry: - %tmp = alloca i32 - store i32 42, i32* %tmp, align 4 - %tmp1 = load i32* %tmp, align 4 - %tmp2 = call i32 @test() - %tmp3 = load i32* %tmp, align 4 - %tmp4 = load i32* %tmp, align 4 - ret i32 %tmp1 -} - -define i32 @test2() nounwind { -entry: - %tmp = call i32 @test() - ret i32 %tmp -} -""" - def test_passes(self): - m = Module.from_assembly(StringIO(self.asm)) - - fn_test1 = m.get_function_named('test1') - fn_test2 = m.get_function_named('test2') - - original_test1 = str(fn_test1) - original_test2 = str(fn_test2) - - # Let's run a module-level inlining pass. First, create a pass manager. - pm = lp.PassManager.new() - - # Add the target data as the first "pass". This is mandatory. - pm.add(le.TargetData.new('')) - - # Add the inlining pass. - pm.add(lp.PASS_INLINE) - - # Run it! - pm.run(m) - - # Done with the pass manager. - del pm - - # Make sure test2 is inlined - self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) - - bb_entry = fn_test2.basic_blocks[0] - - self.assertEqual(len(bb_entry.instructions), 1) - self.assertEqual(bb_entry.instructions[0].opcode_name, 'ret') - - # Let's run a DCE pass on the the function 'test1' now. First create a - # function pass manager. - fpm = lp.FunctionPassManager.new(m) - - # Add the target data as first "pass". This is mandatory. - fpm.add(le.TargetData.new('')) - - # Add a DCE pass - fpm.add(lp.PASS_ADCE) - - # Run the pass on the function 'test1' - fpm.run(m.get_function_named('test1')) - - # Make sure test1 is modified - self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) - - def test_passes_with_pmb(self): - m = Module.from_assembly(StringIO(self.asm)) - - fn_test1 = m.get_function_named('test1') - fn_test2 = m.get_function_named('test2') - - original_test1 = str(fn_test1) - original_test2 = str(fn_test2) - - # Try out the PassManagerBuilder - - pmb = lp.PassManagerBuilder.new() - - self.assertEqual(pmb.opt_level, 2) # ensure default is level 2 - pmb.opt_level = 3 - self.assertEqual(pmb.opt_level, 3) # make sure it works - - self.assertEqual(pmb.size_level, 0) # ensure default is level 0 - pmb.size_level = 2 - self.assertEqual(pmb.size_level, 2) # make sure it works - - self.assertFalse(pmb.vectorize) # ensure default is False - pmb.vectorize = True - self.assertTrue(pmb.vectorize) # make sure it works - - # make sure the default is False - self.assertFalse(pmb.disable_unit_at_a_time) - self.assertFalse(pmb.disable_unroll_loops) - self.assertFalse(pmb.disable_simplify_lib_calls) - - # Do function pass - fpm = lp.FunctionPassManager.new(m) - pmb.populate(fpm) - fpm.run(fn_test1) - - # Make sure test1 has changed - self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) - - # Do module pass - pm = lp.PassManager.new() - pmb.populate(pm) - pm.run(m) - - # Make sure test2 has changed - self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) - - def test_dump_passes(self): - self.assertTrue(len(lp.PASSES)>0, msg="Cannot have no passes") - -tests.append(TestPasses) - -# --------------------------------------------------------------------------- - -class TestEngineBuilder(TestCase): - - def make_test_module(self): - module = Module.new("testmodule") - fnty = Type.function(Type.int(), []) - function = module.add_function(fnty, 'foo') - bb_entry = function.append_basic_block('entry') - builder = Builder.new(bb_entry) - builder.ret(Constant.int(Type.int(), 0xcafe)) - module.verify() - return module - - def run_foo(self, ee, module): - function = module.get_function_named('foo') - retval = ee.run_function(function, []) - self.assertEqual(retval.as_int(), 0xcafe) - - - def test_enginebuilder_basic(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).create() - - with self.assertRaises(llvm.LLVMException): - # Ensure the module is owned. - llvm._util.check_is_unowned(module) - - self.run_foo(ee, module) - - - def test_enginebuilder_with_tm(self): - tm = le.TargetMachine.new() - module = self.make_test_module() - ee = EngineBuilder.new(module).create(tm) - - with self.assertRaises(llvm.LLVMException): - # Ensure the targetmachine is owned. - llvm._util.check_is_unowned(tm) - - - with self.assertRaises(llvm.LLVMException): - # Ensure the module is owned. - llvm._util.check_is_unowned(module) - - self.run_foo(ee, module) - - def test_enginebuilder_force_jit(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).force_jit().create() - - self.run_foo(ee, module) - - def test_enginebuilder_force_interpreter(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).force_interpreter().create() - - self.run_foo(ee, module) - - def test_enginebuilder_opt(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).opt(3).create() - - self.run_foo(ee, module) - -tests.append(TestEngineBuilder) - -# --------------------------------------------------------------------------- - -class TestExecutionEngine(TestCase): - def test_get_pointer_to_global(self): - module = lc.Module.new(str(self)) - gvar = module.add_global_variable(Type.int(), 'hello') - X = 1234 - gvar.initializer = lc.Constant.int(Type.int(), X) - - ee = le.ExecutionEngine.new(module) - ptr = ee.get_pointer_to_global(gvar) - from ctypes import c_void_p, cast, c_int, POINTER - casted = cast(c_void_p(ptr), POINTER(c_int)) - self.assertEqual(X, casted[0]) - - def test_add_global_mapping(self): - module = lc.Module.new(str(self)) - gvar = module.add_global_variable(Type.int(), 'hello') - - fnty = lc.Type.function(Type.int(), []) - foo = module.add_function(fnty, name='foo') - bldr = lc.Builder.new(foo.append_basic_block('entry')) - bldr.ret(bldr.load(gvar)) - - ee = le.ExecutionEngine.new(module) - from ctypes import c_int, addressof, CFUNCTYPE - value = 0xABCD - value_ctype = c_int(value) - value_pointer = addressof(value_ctype) - - ee.add_global_mapping(gvar, value_pointer) - - foo_addr = ee.get_pointer_to_function(foo) - prototype = CFUNCTYPE(c_int) - foo_callable = prototype(foo_addr) - self.assertEqual(foo_callable(), value) - - - -tests.append(TestExecutionEngine) -# --------------------------------------------------------------------------- - -class TestObjCache(TestCase): - - def test_objcache(self): - # Testing module aliasing - m1 = Module.new('a') - t = Type.int() - ft = Type.function(t, [t]) - f1 = m1.add_function(ft, "func") - m2 = f1.module - self.assert_(m1 is m2) - - # Testing global vairable aliasing 1 - gv1 = GlobalVariable.new(m1, t, "gv") - gv2 = GlobalVariable.get(m1, "gv") - self.assert_(gv1 is gv2) - - # Testing global vairable aliasing 2 - gv3 = m1.global_variables[0] - self.assert_(gv1 is gv3) - - # Testing global vairable aliasing 3 - gv2 = None - gv3 = None - - gv1.delete() - gv4 = GlobalVariable.new(m1, t, "gv") - - self.assert_(gv1 is not gv4) - - # Testing function aliasing 1 - b1 = f1.append_basic_block('entry') - f2 = b1.function - self.assert_(f1 is f2) - - # Testing function aliasing 2 - f3 = m1.get_function_named("func") - self.assert_(f1 is f3) - - # Testing function aliasing 3 - f4 = Function.get_or_insert(m1, ft, "func") - self.assert_(f1 is f4) - - # Testing function aliasing 4 - f5 = Function.get(m1, "func") - self.assert_(f1 is f5) - - # Testing function aliasing 5 - f6 = m1.get_or_insert_function(ft, "func") - self.assert_(f1 is f6) - - # Testing function aliasing 6 - f7 = m1.functions[0] - self.assert_(f1 is f7) - - # Testing argument aliasing - a1 = f1.args[0] - a2 = f1.args[0] - self.assert_(a1 is a2) - - # Testing basic block aliasing 1 - b2 = f1.basic_blocks[0] - self.assert_(b1 is b2) - - # Testing basic block aliasing 2 - b3 = f1.get_entry_basic_block() - self.assert_(b1 is b3) - - # Testing basic block aliasing 3 - b31 = f1.entry_basic_block - self.assert_(b1 is b31) - - # Testing basic block aliasing 4 - bldr = Builder.new(b1) - b4 = bldr.basic_block - self.assert_(b1 is b4) - - # Testing basic block aliasing 5 - i1 = bldr.ret_void() - b5 = i1.basic_block - self.assert_(b1 is b5) - - # Testing instruction aliasing 1 - i2 = b5.instructions[0] - self.assert_(i1 is i2) - - # phi node - phi = bldr.phi(t) - phi.add_incoming(f1.args[0], b1) - v2 = phi.get_incoming_value(0) - b6 = phi.get_incoming_block(0) - - # Testing PHI / basic block aliasing 5 - self.assert_(b1 is b6) - - # Testing PHI / value aliasing - self.assert_(f1.args[0] is v2) - -tests.append(TestObjCache) - -# --------------------------------------------------------------------------- - -class TestTargetMachines(TestCase): - '''Exercise target machines - - Require PTX backend - ''' - def test_native(self): - m, _ = self._build_module() - tm = le.EngineBuilder.new(m).select_target() - - self.assertTrue(tm.target_name) - self.assertTrue(tm.target_data) - self.assertTrue(tm.target_short_description) - self.assertTrue(tm.triple) - self.assertIn('foo', tm.emit_assembly(m).decode('utf-8')) - self.assertTrue(le.get_host_cpu_name()) - - def test_ptx(self): - if lc.HAS_PTX: - arch = 'ptx64' - elif lc.HAS_NVPTX: - arch = 'nvptx64' - else: - return # skip this test - m, func = self._build_module() - func.calling_convention = lc.CC_PTX_KERNEL # set calling conv - ptxtm = le.TargetMachine.lookup(arch=arch, cpu='compute_20') - self.assertTrue(ptxtm.triple) - self.assertTrue(ptxtm.cpu) - ptxasm = ptxtm.emit_assembly(m).decode('utf-8') - self.assertIn('foo', ptxasm) - if lc.HAS_NVPTX: - self.assertIn('.address_size 64', ptxasm) - self.assertIn('compute_20', ptxasm) - - def _build_module(self): - m = Module.new('TestTargetMachines') - - fnty = Type.function(Type.void(), []) - func = m.add_function(fnty, name='foo') - - bldr = Builder.new(func.append_basic_block('entry')) - bldr.ret_void() - m.verify() - return m, func - - def _build_bad_archname(self): - with self.assertRaises(RuntimeError): - tm = TargetMachine.lookup("ain't no arch name") - -tests.append(TestTargetMachines) - -# --------------------------------------------------------------------------- - -class TestNative(TestCase): - def setUp(self): - self.tmpdir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.tmpdir) - - - def _make_module(self): - m = Module.new('module1') - m.add_global_variable(Type.int(), 'i') - - fty = Type.function(Type.int(), []) - f = m.add_function(fty, name='main') - - bldr = Builder.new(f.append_basic_block('entry')) - bldr.ret(Constant.int(Type.int(), 0xab)) - - return m - - def _compile(self, src): - dst = os.path.join(self.tmpdir, 'llvmobj.out') - s = subprocess.call(['cc', '-o', dst, src]) - if s != 0: - raise Exception("Cannot compile") - - s = subprocess.call([dst]) - self.assertEqual(s, 0xab) - - def test_assembly(self): - if sys.platform == 'darwin': - # skip this test on MacOSX for now - return - - m = self._make_module() - output = m.to_native_assembly() - - src = os.path.join(self.tmpdir, 'llvmasm.s') - with open(src, 'wb') as fout: - fout.write(output) - - self._compile(src) - - def test_object(self): - if sys.platform == 'darwin': - # skip this test on MacOSX for now - return - - m = self._make_module() - output = m.to_native_object() - - src = os.path.join(self.tmpdir, 'llvmobj.o') - with open(src, 'wb') as fout: - fout.write(output) - - self._compile(src) - -if sys.platform != 'win32': - tests.append(TestNative) - -# --------------------------------------------------------------------------- - -class TestNativeAsm(TestCase): - - def test_asm(self): - m = Module.new('module1') - - foo = m.add_function(Type.function(Type.int(), - [Type.int(), Type.int()]), - name="foo") - bldr = Builder.new(foo.append_basic_block('entry')) - x = bldr.add(foo.args[0], foo.args[1]) - bldr.ret(x) - - att_syntax = m.to_native_assembly() - os.environ["LLVMPY_OPTIONS"] = "-x86-asm-syntax=intel" - lc.parse_environment_options(sys.argv[0], "LLVMPY_OPTIONS") - intel_syntax = m.to_native_assembly() - - self.assertNotEqual(att_syntax, intel_syntax) - -tests.append(TestNativeAsm) - -# --------------------------------------------------------------------------- - -class TestUses(TestCase): - - def test_uses(self): - m = Module.new('a') - t = Type.int() - ft = Type.function(t, [t, t, t]) - f = m.add_function(ft, "func") - b = f.append_basic_block('entry') - bld = Builder.new(b) - tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1") - tmp2 = bld.add(tmp1, f.args[1], "tmp2") - tmp3 = bld.add(tmp1, f.args[2], "tmp3") - bld.ret(tmp3) - - # Testing use count - self.assertEqual(f.args[0].use_count, 1) - self.assertEqual(f.args[1].use_count, 1) - self.assertEqual(f.args[2].use_count, 1) - self.assertEqual(tmp1.use_count, 2) - self.assertEqual(tmp2.use_count, 0) - self.assertEqual(tmp3.use_count, 1) - - # Testing uses - self.assert_(f.args[0].uses[0] is tmp1) - self.assertEqual(len(f.args[0].uses), 1) - self.assert_(f.args[1].uses[0] is tmp2) - self.assertEqual(len(f.args[1].uses), 1) - self.assert_(f.args[2].uses[0] is tmp3) - self.assertEqual(len(f.args[2].uses), 1) - self.assertEqual(len(tmp1.uses), 2) - self.assertEqual(len(tmp2.uses), 0) - self.assertEqual(len(tmp3.uses), 1) - -tests.append(TestUses) - -# --------------------------------------------------------------------------- - -class TestMetaData(TestCase): - # test module metadata - def test_metadata(self): - m = Module.new('a') - t = Type.int() - metadata = MetaData.get(m, [Constant.int(t, 100), - MetaDataString.get(m, 'abcdef'), - None]) - MetaData.add_named_operand(m, 'foo', metadata) - self.assertEqual(MetaData.get_named_operands(m, 'foo'), [metadata]) - self.assertEqual(MetaData.get_named_operands(m, 'bar'), []) - self.assertEqual(len(metadata.operands), 3) - self.assertEqual(metadata.operands[0].z_ext_value, 100) - self.assertEqual(metadata.operands[1].string, 'abcdef') - self.assertTrue(metadata.operands[2] is None) - -tests.append(TestMetaData) - -# --------------------------------------------------------------------------- - -class TestInlining(TestCase): - def test_inline_call(self): - mod = Module.new(__name__) - callee = mod.add_function(Type.function(Type.int(), [Type.int()]), - name='bar') - - builder = Builder.new(callee.append_basic_block('entry')) - builder.ret(builder.add(callee.args[0], callee.args[0])) - - caller = mod.add_function(Type.function(Type.int(), []), - name='foo') - - builder = Builder.new(caller.append_basic_block('entry')) - callinst = builder.call(callee, [Constant.int(Type.int(), 1234)]) - builder.ret(callinst) - - pre_inlining = str(caller) - self.assertIn('call', pre_inlining) - - self.assertTrue(inline_function(callinst)) - - post_inlining = str(caller) - self.assertNotIn('call', post_inlining) - self.assertIn('2468', post_inlining) - -tests.append(TestInlining) - -# --------------------------------------------------------------------------- - -class TestIssue10(TestCase): - def test_issue10(self): - m = Module.new('a') - ti = Type.int() - tf = Type.function(ti, [ti, ti]) - - f = m.add_function(tf, "func1") - - bb = f.append_basic_block('entry') - - b = Builder.new(bb) - - # There are no instructions in bb. Positioning of the - # builder at beginning (or end) should succeed (trivially). - b.position_at_end(bb) - b.position_at_beginning(bb) - -tests.append(TestIssue10) - -# --------------------------------------------------------------------------- - -class TestOpaque(TestCase): - - def test_opaque(self): - # Create an opaque type - ts = Type.opaque('mystruct') - self.assertTrue('type opaque' in str(ts)) - self.assertTrue(ts.is_opaque) - self.assertTrue(ts.is_identified) - self.assertFalse(ts.is_literal) - #print(ts) - - # Create a recursive type - ts.set_body([Type.int(), Type.pointer(ts)]) - - self.assertEqual(ts.elements[0], Type.int()) - self.assertEqual(ts.elements[1], Type.pointer(ts)) - self.assertEqual(ts.elements[1].pointee, ts) - self.assertFalse(ts.is_opaque) # is not longer a opaque type - #print(ts) - - with self.assertRaises(llvm.LLVMException): - # Cannot redefine - ts.set_body([]) - - def test_opaque_with_no_name(self): - with self.assertRaises(llvm.LLVMException): - Type.opaque('') - -tests.append(TestOpaque) - -# --------------------------------------------------------------------------- -class TestCPUSupport(TestCase): - - def _build_test_module(self): - mod = Module.new('test') - - float = Type.double() - mysinty = Type.function( float, [float] ) - mysin = mod.add_function(mysinty, "mysin") - block = mysin.append_basic_block("entry") - b = Builder.new(block) - - sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) - cos = Function.intrinsic(mod, lc.INTR_COS, [float]) - - mysin.args[0].name = "x" - x = mysin.args[0] - one = Constant.real(float, "1") - cosx = b.call(cos, [x], "cosx") - cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") - onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub - sin = b.call(sqrt, [onemc2], "sin") - b.ret(sin) - return mod, mysin - - def _template(self, mattrs): - mod, func = self._build_test_module() - ee = self._build_engine(mod, mattrs=mattrs) - - arg = le.GenericValue.real(Type.double(), 1.234) - retval = ee.run_function(func, [arg]) - - golden = math.sin(1.234) - answer = retval.as_real(Type.double()) - self.assertTrue(abs(answer-golden)/golden < 1e-5) - - - def _build_engine(self, mod, mattrs): - if mattrs: - return EngineBuilder.new(mod).mattrs(mattrs).create() - else: - return EngineBuilder.new(mod).create() - - def test_cpu_support2(self): - features = 'sse3', 'sse41', 'sse42', 'avx' - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support3(self): - features = 'sse41', 'sse42', 'avx' - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support4(self): - features = 'sse42', 'avx' - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support5(self): - features = 'avx', - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support6(self): - features = [] - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - -tests.append(TestCPUSupport) - -# --------------------------------------------------------------------------- -class TestIntrinsicBasic(TestCase): - - def _build_module(self, float): - mod = Module.new('test') - functy = Type.function(float, [float]) - func = mod.add_function(functy, "mytest%s" % float) - block = func.append_basic_block("entry") - b = Builder.new(block) - return mod, func, b - - def _template(self, mod, func, pyfunc): - float = func.type.pointee.return_type - ee = le.ExecutionEngine.new(mod) - arg = le.GenericValue.real(float, 1.234) - retval = ee.run_function(func, [arg]) - golden = pyfunc(1.234) - answer = retval.as_real(float) - self.assertTrue(abs(answer - golden) / golden < 1e-7) - - def test_sqrt_f32(self): - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sqrt) - - def test_sqrt_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sqrt) - - def test_cos_f32(self): - if sys.platform == 'win32' and BITS == 32: - # float32 support is known to fail on 32-bit Windows - return - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_COS, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.cos) - - def test_cos_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_COS, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.cos) - - def test_sin_f32(self): - if sys.platform == 'win32' and BITS == 32: - # float32 support is known to fail on 32-bit Windows - return - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sin) - - def test_sin_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sin) - - def test_powi_f32(self): - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) - b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) - self._template(mod, func, lambda x: x**2) - - def test_powi_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) - b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) - self._template(mod, func, lambda x: x**2) - - - -tests.append(TestIntrinsicBasic) - -# --------------------------------------------------------------------------- - -class TestIntrinsic(TestCase): - def test_bswap(self): - # setup a function and a builder - mod = Module.new('test') - functy = Type.function(Type.int(), []) - func = mod.add_function(functy, "showme") - block = func.append_basic_block("entry") - b = Builder.new(block) - - # let's do bswap on a 32-bit integer using llvm.bswap - val = Constant.int(Type.int(), 0x42) - bswap = Function.intrinsic(mod, lc.INTR_BSWAP, [Type.int()]) - - bswap_res = b.call(bswap, [val]) - b.ret(bswap_res) - - # logging.debug(mod) - - # the output is: - # - # ; ModuleID = 'test' - # - # define void @showme() { - # entry: - # %0 = call i32 @llvm.bswap.i32(i32 42) - # ret i32 %0 - # } - - # let's run the function - ee = le.ExecutionEngine.new(mod) - retval = ee.run_function(func, []) - self.assertEqual(retval.as_int(), 0x42000000) - - def test_mysin(self): - if sys.platform == 'win32' and BITS == 32: - # float32 support is known to fail on 32-bit Windows - return - - # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) - mod = Module.new('test') - - float = Type.float() - mysinty = Type.function( float, [float] ) - mysin = mod.add_function(mysinty, "mysin") - block = mysin.append_basic_block("entry") - b = Builder.new(block) - - sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) - cos = Function.intrinsic(mod, lc.INTR_COS, [float]) - - mysin.args[0].name = "x" - x = mysin.args[0] - one = Constant.real(float, "1") - cosx = b.call(cos, [x], "cosx") - cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") - onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub - sin = b.call(sqrt, [onemc2], "sin") - b.ret(sin) - #logging.debug(mod) - -# ; ModuleID = 'test' -# -# define void @showme() { -# entry: -# call i32 @llvm.bswap.i32( i32 42 ) ; :0 [#uses -# } -# -# declare i32 @llvm.bswap.i32(i32) nounwind readnone -# -# define float @mysin(float %x) { -# entry: -# %cosx = call float @llvm.cos.f32( float %x ) ; [#uses -# %sin = call float @llvm.sqrt.f32( float %onemc2 ) -# ret float %sin -# } -# -# declare float @llvm.sqrt.f32(float) nounwind readnone -# -# declare float @llvm.powi.f32(float, i32) nounwind readnone -# -# declare float @llvm.cos.f32(float) nounwind readnone - - # let's run the function - ee = le.ExecutionEngine.new(mod) - arg = le.GenericValue.real(Type.float(), 1.234) - retval = ee.run_function(mysin, [arg]) - - golden = math.sin(1.234) - answer = retval.as_real(Type.float()) - self.assertTrue(abs(answer-golden)/golden < 1e-5) - -tests.append(TestIntrinsic) - -# --------------------------------------------------------------------------- - -class TestVolatile(TestCase): - - def test_volatile(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - # test load inst - val = bldr.load(ptr) - self.assertFalse(val.is_volatile, "default must be non-volatile") - val.set_volatile(True) - self.assertTrue(val.is_volatile, "fail to set volatile") - val.set_volatile(False) - self.assertFalse(val.is_volatile, "fail to unset volatile") - - # test store inst - store_inst = bldr.store(val, ptr) - self.assertFalse(store_inst.is_volatile, "default must be non-volatile") - store_inst.set_volatile(True) - self.assertTrue(store_inst.is_volatile, "fail to set volatile") - store_inst.set_volatile(False) - self.assertFalse(store_inst.is_volatile, "fail to unset volatile") - - def test_volatile_another(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - # test load inst - val = bldr.load(ptr, volatile=True) - self.assertTrue(val.is_volatile, "volatile kwarg does not work") - val.set_volatile(False) - self.assertFalse(val.is_volatile, "fail to unset volatile") - val.set_volatile(True) - self.assertTrue(val.is_volatile, "fail to set volatile") - - # test store inst - store_inst = bldr.store(val, ptr, volatile=True) - self.assertTrue(store_inst.is_volatile, "volatile kwarg does not work") - store_inst.set_volatile(False) - self.assertFalse(store_inst.is_volatile, "fail to unset volatile") - store_inst.set_volatile(True) - self.assertTrue(store_inst.is_volatile, "fail to set volatile") - -tests.append(TestVolatile) - -# --------------------------------------------------------------------------- - -class TestNamedMetaData(TestCase): - def test_named_md(self): - m = Module.new('test_named_md') - nmd = m.get_or_insert_named_metadata('something') - md = MetaData.get(m, [Constant.int(Type.int(), 0xbeef)]) - nmd.add(md) - self.assertTrue(str(nmd).startswith('!something')) - ir = str(m) - self.assertTrue('!something' in ir) - -tests.append(TestNamedMetaData) - -# --------------------------------------------------------------------------- - -def run(verbosity=1): - print('llvmpy is installed in: ' + os.path.dirname(__file__)) - print('llvmpy version: ' + llvm.__version__) - print(sys.version) - - suite = unittest.TestSuite() - for cls in tests: - suite.addTest(unittest.makeSuite(cls)) - - # The default stream fails in IPython qtconsole on Windows, - # so just using sys.stdout - runner = unittest.TextTestRunner(verbosity=verbosity, stream=sys.stdout) - return runner.run(suite) - - -if __name__ == '__main__': - run() diff --git a/llvm/wrap.cpp b/llvm/wrap.cpp deleted file mode 100644 index 6702ade..0000000 --- a/llvm/wrap.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "wrap.h" - -const char PYCAP_OBJECT_NAME[] = "llvm.wrap.h"; - -/*===----------------------------------------------------------------------===*/ -/* Type ctor/dtor */ -/*===----------------------------------------------------------------------===*/ - - -/*===----------------------------------------------------------------------===*/ -/* Helper functions */ -/*===----------------------------------------------------------------------===*/ - -void *get_object_arg(PyObject *args) -{ - PyObject *o; - - if (!PyArg_ParseTuple(args, "O", &o)) - throw py_exception(); - - return pycap_get(o); -} - -// must delete [] returned array -void **make_array_from_list(PyObject *list, int n) -{ - void **arr = new void*[n] ; - - int i; - for (i=0; i(e); - } - } - - return arr; -} diff --git a/llvm/wrap.h b/llvm/wrap.h deleted file mode 100644 index ce2dd88..0000000 --- a/llvm/wrap.h +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * Functions and macros to aid in wrapping. - */ - -#ifndef LLVM_PY_WRAP_H -#define LLVM_PY_WRAP_H - - -/* python includes */ -#include -// #include //unused? - -//// For pre-2.7 compatbility, use the following include, which provides -//// alias for PyCapsule. -//// See http://docs.python.org/py3k/howto/cporting.html -#include "capsulethunk.h" // pre-2.7 compatibility for PyCapsule - - -/* llvm includes */ -#include "llvm-c/Core.h" -#include "llvm-c/Analysis.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" - -// workaround missing bool type -#define bool int -#include "llvm-c/Transforms/PassManagerBuilder.h" -#undef bool - -#include "llvm_c_extra.h" - -#include -#include - -class py_exception: public std::exception{}; - -#define LLVMPY_TRY \ - try { - -#define LLVMPY_CATCH_ALL \ - } catch (const std::bad_alloc&) { \ - return PyErr_NoMemory(); \ - } catch (const py_exception &) { \ - return NULL; \ - } catch (const std::exception& e) { \ - PyErr_SetString(PyExc_RuntimeError, e.what()); \ - return NULL; \ - } catch (...) { \ - std::ostringstream oss; \ - oss << "Unknown exception " << __FILE__ << ":" << __LINE__; \ - PyErr_SetString(PyExc_RuntimeError, oss.str().c_str()); \ - return NULL; \ - } - -/*===----------------------------------------------------------------------===*/ -/* Typedefs */ -/*===----------------------------------------------------------------------===*/ - -typedef unsigned long long llvmwrap_ull; -typedef long long llvmwrap_ll; - -/*===----------------------------------------------------------------------===*/ -/* Type ctor/dtor */ -/*===----------------------------------------------------------------------===*/ - -extern const char PYCAP_OBJECT_NAME[] ; - -// Cast python object to aTYPE -template -aTYPE pycap_get( PyObject* obj ) -{ - void *p = PyCapsule_GetPointer(obj, PYCAP_OBJECT_NAME); - if (!p){ - throw py_exception(); - } - return static_cast (p); -} - -// Contruct python object to hold aTYPE pointer -template -PyObject* pycap_new( aTYPE p ) -{ - if (p){ - return PyCapsule_New(p, PYCAP_OBJECT_NAME, NULL); - } - Py_RETURN_NONE; -} - -/*===----------------------------------------------------------------------===*/ -/* Helper methods */ -/*===----------------------------------------------------------------------===*/ - -/** - * Accept a single object argument of type PyCObject and return the - * opaque pointer contained in it. - */ -void *get_object_arg(PyObject *args); - -template -aTYPE get_object_arg( PyObject* obj ) -{ - return static_cast ( get_object_arg(obj) ); -} - -/** - * Given a PyList object (list) having n (= PyList_Size(list)) elements, - * each list object being a PyCObject, return a new()-ed array of - * opaque pointers from the PyCObjects. The 'n' is passed explicitly - * since the caller will have to query it once anyway, and we can avoid - * a second call internally. - */ -void **make_array_from_list(PyObject *list, int n); - -template -LLTYPE make_array_from_list(PyObject *list, int n) -{ - LLTYPE p = reinterpret_cast(make_array_from_list(list, n)) ; - if ( !p ) throw py_exception(); - return p; -} - -template -PyObject* make_list( aTYPE p[], size_t n ) -{ - PyObject *list = PyList_New(n); - - if (!list) - return NULL; - - size_t i; - for (i=0; i( p[i] ); - PyList_SetItem(list, i, elem); - } - - return list; -} - -/*===----------------------------------------------------------------------===*/ -/* Wrapper macros */ -/*===----------------------------------------------------------------------===*/ - -/* The following wrapper macros define functions that wrap over LLVM-C APIs - * of various signatures. Though they look hairy, they all follow some - * conventions. - */ - - -/****************************************************************************** - ****************************************************************************** - *** PyCapsule Calls - ****************************************************************************** - *****************************************************************************/ - -#define _wrap_none2none(func) \ -static PyObject * \ -_w ## func(PyObject * self, PyObject * args) \ -{ \ - LLVMPY_TRY \ - if (!PyArg_ParseTuple(args, "")) \ - return NULL; \ - func(); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1) - */ -#define _wrap_obj2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype1 arg1 = get_object_arg(args); \ - \ - return pycap_new( func( arg1 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(int arg1) - */ -#define _wrap_int2obj(func, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - int arg1; \ - \ - if (!PyArg_ParseTuple(args, "i", &arg1)) \ - return NULL; \ - \ - return pycap_new( func( arg1 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2) - */ -#define _wrap_objobj2obj(func, intype1, intype2, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - \ - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, intype2 arg2) - */ -#define _wrap_objobj2none(func, intype1, intype2) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - \ - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) \ - return NULL; \ - \ - intype1 arg1 = pycap_get< intype1 > (obj1); \ - intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, arg2) - */ -#define _wrap_objint2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - size_t arg2; \ - \ - if (!PyArg_ParseTuple(args, "OI", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - return pycap_new( func( arg1, arg2 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_objobjobj2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_objobjobj2none(func, intype1, intype2, intype3) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - func (arg1, arg2, arg3); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func( arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_intobjobj2obj(func, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - size_t arg1; \ - PyObject *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "IOO", &arg1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(enum_intype1 arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_enumobjobj2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype1 arg1; \ - PyObject *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "IOO", &arg1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(const char *s) - */ -#define _wrap_str2obj(func, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - const char *arg1; \ - \ - if (!PyArg_ParseTuple(args, "s", &arg1)) \ - return NULL; \ - \ - return pycap_new( func( arg1 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func() - */ -#define _wrap_none2obj(func, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - if (!PyArg_ParseTuple(args, "")) \ - return NULL; \ - \ - return pycap_new( func() ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * const char * func() - */ - #define _wrap_none2str(func) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - if (!PyArg_ParseTuple(args, "")) \ - return NULL; \ - return PyUnicode_FromString(func()); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * const char *func(intype1 arg1) - */ -#define _wrap_obj2str(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - const intype1 arg1 = get_object_arg(args) ; \ - return PyUnicode_FromString( func (arg1)); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1) - */ -#define _wrap_obj2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - const intype1 arg1 = get_object_arg(args) ; \ - func (arg1); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, const char *arg2) - */ -#define _wrap_objstr2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "Os", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char *arg2) - */ -#define _wrap_objstr2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "Os", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - return pycap_new( func( arg1, arg2 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, arg2) - */ -#define _wrap_objint2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2; \ - \ - if (!PyArg_ParseTuple(args, "Oi", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, enum_intype2 arg2) - */ -#define _wrap_objenum2none(func, intype1, intype2) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype2 arg2; \ - PyObject *obj1; \ - \ - if (!PyArg_ParseTuple(args, "Oi", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, const char *arg3) - */ -#define _wrap_objobjstr2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - const char *arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOs", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new ( func (arg1, arg2, arg3)); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, int arg3) - */ -#define _wrap_objobjint2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, unsigned long long arg3) - */ -#define _wrap_objobjull2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - unsigned long long arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOK", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, arg2, arg3) - */ -#define _wrap_objintint2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2, arg3; \ - \ - if (!PyArg_ParseTuple(args, "Oii", &obj1, &arg2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - func (arg1, arg2, arg3); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, arg2, enum_intype3 arg3) - */ -#define _wrap_objintenum2none(func, intype1, intype3) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2; \ - intype3 arg3; \ - \ - if (!PyArg_ParseTuple(args, "Oii", &obj1, &arg2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - \ - func (arg1, arg2, arg3); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char *arg2, intype3 arg3) - */ -#define _wrap_objstrobj2obj(func, intype1, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "OsO", &obj1, &arg2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, const char *arg2, intype3 arg3) - */ -#define _wrap_objstrobj2none(func, intype1, intype3) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "OsO", &obj1, &arg2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - func(arg1, arg2, arg3); \ - \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, int arg3, const char *arg4) - */ -#define _wrap_objobjintstr2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - const char *arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOis", &obj1, &obj2, &arg3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3, int arg3, const char *arg4) - */ -#define _wrap_objobjobjintstr2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - int arg4; \ - const char *arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOOis", &obj1, &obj2, &obj3, &arg4, \ - &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, const char *arg4) - */ -#define _wrap_objobjobjstr2obj(func, intype1, intype2, intype3, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - const char *arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOOs", &obj1, &obj2, &obj3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, const char *arg3, arg4) - */ -#define _wrap_objobjstrint2obj(func, intype1, intype2, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - const char *arg3; \ - int arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOsi", &obj1, &obj2, &arg3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ); \ - LLVMPY_CATCH_ALL \ -} - - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, arg3, const char *arg4, arg5) - */ -#define _wrap_objobjintstrint2obj(func, intype1, intype2, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - const char *arg4; \ - int arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOisi", &obj1, &obj2, &arg3, &arg4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char *arg2, arg3) - */ -#define _wrap_objstrint2obj(func, intype1, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - const char *arg2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "Osi", &obj1, &arg2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3, const char *arg4, arg5) - */ -#define _wrap_objobjobjstrint2obj(func, intype1, intype2, intype3, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - const char *arg4; \ - int arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOOsi", &obj1, &obj2, &obj3, &arg4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ); \ - LLVMPY_CATCH_ALL \ -} - - - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3, arg4, const char *arg5, arg6) - */ -#define _wrap_objobjobjintstrint2obj(func, intype1, intype2, intype3, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - int arg4; \ - const char *arg5; \ - int arg6; \ - \ - if (!PyArg_ParseTuple(args, "OOOisi", &obj1, &obj2, &obj3, &arg4, &arg5, &arg6)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5, arg6 ) );\ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype4, const char *arg5, arg6) - */ -#define _wrap_objobjobjobjstrint2obj(func, intype1, intype2, intype3, intype4, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3, *obj4; \ - const char *arg5; \ - int arg6; \ - \ - if (!PyArg_ParseTuple(args, "OOOOsi", &obj1, &obj2, &obj3, &obj4, &arg5, &arg6)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5, arg6 ) ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char* arg2, intype3 arg3, intype4, const char *arg5, arg6) - */ -#define _wrap_objstrobjobjstrint2obj(func, intype1, intype3, intype4, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3, *obj4; \ - const char *arg2; \ - const char *arg5; \ - int arg6; \ - \ - if (!PyArg_ParseTuple(args, "OsOOsi", &obj1, &arg2, &obj3, &obj4, &arg5, &arg6)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5, arg6 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, arg4) - */ -#define _wrap_objobjobjint2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - int arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOOi", &obj1, &obj2, &obj3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype arg4) - */ -#define _wrap_objobjobjobj2obj(func, intype1, intype2, intype3, \ - intype4, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3, *obj4; \ - \ - if (!PyArg_ParseTuple(args, "OOOO", &obj1, &obj2, &obj3, &obj4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) );\ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype arg4, const char *arg5) - */ -#define _wrap_objobjobjobjstr2obj(func, intype1, intype2, intype3, \ - intype4, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3, *obj4; \ - const char *arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOOOs", &obj1, &obj2, &obj3, &obj4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) );\ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, enum_intype2 arg2, intype3 arg3, intype4 arg4, const char *arg5) - */ -#define _wrap_objenumobjobjstr2obj(func, intype1, intype2, intype3, \ - intype4, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3, *obj4; \ - intype2 arg2 ; \ - const char *arg5; \ - \ - if (!PyArg_ParseTuple(args, "OiOOs", &obj1, &arg2, &obj3, &obj4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 *arg2v, unsigned arg2n) - * where arg2v is an array of intype2 elements, arg2n in length. - */ -#define _wrap_objlist2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - \ - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg2n = PyList_Size(obj2); \ - intype2 *arg2v = make_array_from_list< intype2 *>(obj2, arg2n); \ - \ - outtype ret = func (arg1, arg2v, arg2n); \ - delete [] arg2v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 *arg1v, unsigned arg1n, int arg2) - * where arg1v is an array of intype1 elements, arg1n in length. - */ -#define _wrap_listint2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2; \ - \ - if (!PyArg_ParseTuple(args, "Oi", &obj1, &arg2)) \ - return NULL; \ - \ - const size_t arg1n = PyList_Size(obj1); \ - intype1 *arg1v = make_array_from_list< intype1 *>(obj1, arg1n); \ - \ - outtype ret = func (arg1v, arg1n, arg2); \ - delete [] arg1v; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 *arg1v, unsigned arg1n) - * where arg1v is an array of intype1 elements, arg1n in length. - */ -#define _wrap_list2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - \ - if (!PyArg_ParseTuple(args, "O", &obj1)) \ - return NULL; \ - \ - const size_t arg1n = PyList_Size(obj1); \ - intype1 *arg1v = make_array_from_list< intype1 *>(obj1, arg1n); \ - \ - outtype ret = func (arg1v, arg1n); \ - delete [] arg1v; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 *arg2v, unsigned arg2n, int arg3) - * where arg2v is an array of intype2 elements, arg2n in length. - */ -#define _wrap_objlistint2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg2n = PyList_Size(obj2); \ - intype2 *arg2v = make_array_from_list< intype2 *>(obj2, arg2n); \ - \ - outtype ret = func (arg1, arg2v, arg2n, arg3); \ - delete [] arg2v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, intype2 *arg2v, unsigned arg2n, int arg3) - * where arg2v is an array of intype2 elements, arg2n in length. - */ -#define _wrap_objlistint2none(func, intype1, intype2) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg2n = PyList_Size(obj2); \ - intype2 *arg2v = make_array_from_list< intype2 *>(obj2, arg2n); \ - \ - func (arg1, arg2v, arg2n, arg3); \ - delete [] arg2v ; \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n) - * where arg3v is an array of intype3 elements, arg3n in length. - */ -#define _wrap_objintlist2obj(func, intype1, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3; \ - int arg2; \ - \ - if (!PyArg_ParseTuple(args, "OiO", &obj1, &arg2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg3n = PyList_Size(obj3); \ - intype3 *arg3v = make_array_from_list< intype3 *>(obj3, arg3n); \ - \ - outtype ret = func (arg1, arg2, arg3v, arg3n); \ - delete [] arg3v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 *arg3v, unsigned arg3n) - * where arg3v is an array of intype3 elements, arg3n in length. - */ -#define _wrap_objobjlist2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const size_t arg3n = PyList_Size(obj3); \ - intype3 *arg3v = make_array_from_list< intype3 *>(obj3, arg3n); \ - \ - outtype ret = func (arg1, arg2, arg3v, arg3n); \ - delete [] arg3v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 *arg3v, unsigned arg3n, const char *arg4) - * where arg3v is an array of intype3 elements, arg3n in length. - */ -#define _wrap_objobjliststr2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - const char *arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOOs", &obj1, &obj2, &obj3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const size_t arg3n = PyList_Size(obj3); \ - intype3 *arg3v = make_array_from_list< intype3 *>(obj3, arg3n); \ - \ - outtype ret = func (arg1, arg2, arg3v, arg3n, arg4); \ - delete [] arg3v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM dump-to-string functions of the type - * char *func(intype1) - * where the return value has to be disposed after use by calling - * LLVMDisposeMessage. - */ -#define _wrap_dumper(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype1 arg1 = get_object_arg(args); \ - \ - const char *val = func (arg1); \ - PyObject *ret = PyUnicode_FromString(val); \ - LLVMDisposeMessage(const_cast(val)); \ - return ret; \ - LLVMPY_CATCH_ALL \ -} - - -#endif /* LLVM_PY_WRAP_H */ From c98a1274d9cd80fc4bc3da38cc00230d5839e91b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 18:48:09 -0600 Subject: [PATCH 070/338] Add Linker and Assembly (IR) Parser --- newbinding/src/Assembly/Parser.py | 14 ++++++++ newbinding/src/Linker.py | 51 +++++++++++++++++++++++++++++ newbinding/src/Support/SourceMgr.py | 10 ++++++ 3 files changed, 75 insertions(+) create mode 100644 newbinding/src/Assembly/Parser.py create mode 100644 newbinding/src/Linker.py create mode 100644 newbinding/src/Support/SourceMgr.py diff --git a/newbinding/src/Assembly/Parser.py b/newbinding/src/Assembly/Parser.py new file mode 100644 index 0000000..1858bcd --- /dev/null +++ b/newbinding/src/Assembly/Parser.py @@ -0,0 +1,14 @@ +from binding import * +from ..namespace import llvm +from ..Module import Module +from ..LLVMContext import LLVMContext +from ..Support.SourceMgr import SMDiagnostic + +llvm.includes.add('llvm/Assembly/Parser.h') + +ParseAssemblyString = llvm.Function('ParseAssemblyString', + ptr(Module), + cast(str, ConstCharPtr), + ptr(Module), # can be None + ref(SMDiagnostic), + ref(LLVMContext)) diff --git a/newbinding/src/Linker.py b/newbinding/src/Linker.py new file mode 100644 index 0000000..0b846d6 --- /dev/null +++ b/newbinding/src/Linker.py @@ -0,0 +1,51 @@ +from binding import * +from namespace import llvm +from ADT.StringRef import StringRef +from Module import Module +from LLVMContext import LLVMContext + +llvm.includes.add('llvm/Linker.h') + +Linker = llvm.Class() + +@Linker +class Linker: + 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) + + _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) + + delete = Destructor() + + getModule = Method(ptr(Module)) + releaseModule = Method(ptr(Module)) + getLastError = Method(cast(ConstStdString, str)) + + LinkInModule = CustomMethod('Linker_LinkInModule', + PyObjectPtr, # boolean + ptr(Module), + PyObjectPtr, # errmsg + ) + + LinkModules = CustomStaticMethod('Linker_LinkModules', + PyObjectPtr, # boolean + ptr(Module), + ptr(Module), + LinkerMode, + PyObjectPtr, # errsg + ) + diff --git a/newbinding/src/Support/SourceMgr.py b/newbinding/src/Support/SourceMgr.py new file mode 100644 index 0000000..7dc75be --- /dev/null +++ b/newbinding/src/Support/SourceMgr.py @@ -0,0 +1,10 @@ +from binding import * +from ..namespace import llvm + +llvm.includes.add('llvm/Support/SourceMgr.h') + +@llvm.Class() +class SMDiagnostic: + new = Constructor() + delete = Destructor() + From 9c81fa1f63ba56c76b9a10009216e23667763c53 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 18:48:46 -0600 Subject: [PATCH 071/338] Add more functions to GlobalValue GlobalVariable, StructType and Module --- newbinding/include/llvm_binding/extra.h | 82 +++++++++++++++++++++++++ newbinding/src/GlobalValue.py | 18 ++++++ newbinding/src/GlobalVariable.py | 44 ++++++++++++- newbinding/src/Module.py | 26 +++++++- newbinding/src/Type.py | 27 +++++++- newbinding/src/Value.py | 14 +++-- 6 files changed, 201 insertions(+), 10 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 77b399d..fd4eb4e 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -8,6 +9,10 @@ #include #include #include +#include +#include + +#include "auto_pyobject.h" namespace extra{ using namespace llvm; @@ -496,3 +501,80 @@ PyObject* TargetMachine_addPassesToEmitFile( } } +static +PyObject* Linker_LinkInModule(llvm::Linker* Linker, + llvm::Module* Mod, + PyObject* ErrMsg) +{ + std::string errmsg; + bool failed = Linker->LinkInModule(Mod, &errmsg); + if (not failed) { + Py_RETURN_FALSE; + } else { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + Py_RETURN_TRUE; + } +} + +static +PyObject* Linker_LinkModules(llvm::Module* Dest, + llvm::Module* Src, + unsigned Mode, + PyObject* ErrMsg) +{ + std::string errmsg; + bool failed = llvm::Linker::LinkModules(Dest, Src, Mode, &errmsg); + if (not failed) { + Py_RETURN_FALSE; + } else { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + Py_RETURN_TRUE; + } +} + +static +PyObject* StructType_setBody(llvm::StructType* Self, + PyObject* Elems, + bool isPacked=false) +{ + using namespace llvm; + std::vector elements; + Py_ssize_t N = PySequence_Size(Elems); + elements.reserve(N); + for (Py_ssize_t i=0; i < N; ++i) { + auto_pyobject obj = PySequence_GetItem(Elems, i); + auto_pyobject capsule = PyObject_GetAttrString(*obj, "_ptr"); + if (!capsule) { + return NULL; + } + void * ptr = PyCapsule_GetPointer(*capsule, "llvm::Type"); + if (!ptr) { + return NULL; + } + Type* type = static_cast(ptr); + elements.push_back(type); + } + + Self->setBody(elements, isPacked); + + Py_RETURN_NONE; +} + +static +PyObject* Module_list_globals(llvm::Module* Mod) +{ + return iplist_to_pylist(Mod->getGlobalList(), + "llvm::Value", "llvm::GlobalVariable"); +} + +static +PyObject* Module_list_functions(llvm::Module* Mod) +{ + return iplist_to_pylist(Mod->getFunctionList(), + "llvm::Value", "llvm::Function"); +} + diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index 40825a8..d14d48a 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -6,3 +6,21 @@ from Value import GlobalValue class GlobalValue: _include_ = 'llvm/GlobalValue.h' + LinkageTypes = Enum(''' + ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage, + LinkOnceODRLinkage, LinkOnceODRAutoHideLinkage, WeakAnyLinkage, + WeakODRLinkage, AppendingLinkage, InternalLinkage, PrivateLinkage, + LinkerPrivateLinkage, LinkerPrivateWeakLinkage, DLLImportLinkage, + DLLExportLinkage, ExternalWeakLinkage, CommonLinkage + ''') + + VisibilityTypes = Enum('''DefaultVisibility, + HiddenVisibility, + ProtectedVisibility''') + + setLinkage = Method(Void, LinkageTypes) + getLinkage = Method(LinkageTypes) + + setVisibility = Method(Void, VisibilityTypes) + getVisibility = Method(VisibilityTypes) + diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py index 548a8d1..70203d5 100644 --- a/newbinding/src/GlobalVariable.py +++ b/newbinding/src/GlobalVariable.py @@ -1,8 +1,48 @@ from binding import * from namespace import llvm + from GlobalValue import GlobalValue +GlobalVariable = llvm.Class(GlobalValue) -@llvm.Class(GlobalValue) +from Constant import Constant +from Module import Module +from Type import Type +from ADT.StringRef import StringRef + +@GlobalVariable class GlobalVariable: - pass + ThreadLocalMode = Enum('''NotThreadLocal, GeneralDynamicTLSModel, + LocalDynamicTLSModel, InitialExecTLSModel, + LocalExecTLSModel + ''') + new = Constructor(ref(Module), + ptr(Type), + cast(bool, Bool), # is constant + GlobalValue.LinkageTypes, + ptr(Constant), # initializer -- can be None + cast(str, StringRef), # name + ptr(GlobalVariable), # insert before + ThreadLocalMode, + cast(int, Unsigned), # address-space + # cast(bool, Bool), # externally initialized + ).require_only(5) + + setThreadLocal = Method(Void, cast(bool, Bool)) + setThreadLocalMode = Method(Void, ThreadLocalMode) + isThreadLocal = Method(cast(Bool, bool)) + + isConstant = Method(cast(Bool, bool)) + setConstant = Method(Void, ptr(Constant)) + + setInitializer = Method(Void, ptr(Constant)) + getInitializer = Method(ptr(Constant)) + hasInitializer = Method(cast(Bool, bool)) + + hasUniqueInitializer = Method(cast(Bool, bool)) + hasDefinitiveInitializer = Method(cast(Bool, bool)) + +# isExternallyInitialized = Method(cast(Bool, bool)) +# setExternallyinitialized = Method(Void, cast(bool, Bool)) + + \ No newline at end of file diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 539c486..706fe48 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -1,14 +1,19 @@ from binding import * from namespace import llvm + +Module = llvm.Class() + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Constant import Constant +from GlobalVariable import GlobalVariable from Function import Function from DerivedTypes import FunctionType from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Type import Type, StructType -@llvm.Class() +@Module class Module: _include_ = "llvm/Module.h" # Enumerators @@ -38,6 +43,21 @@ class Module: # Function Accessors getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) + getFunction = Method(ptr(Function), cast(str, StringRef)) + + # Function Iteration + list_functions = CustomMethod('Module_list_functions', PyObjectPtr) + + # GlobalVariabe Accessors + getGlobalVariable = Method(ptr(GlobalVariable), + cast(str, StringRef), + cast(bool, Bool), + ).require_only(1) + getNamedGlobal = Method(ptr(GlobalVariable), cast(str, StringRef)) + getOrInsertGlobal = Method(ptr(Constant), cast(str, StringRef), ptr(Type)) + + # GlobalVariable Iteration + list_globals = CustomMethod('Module_list_globals', PyObjectPtr) # Utilities dump = Method(Void) @@ -52,3 +72,7 @@ class Module: return os.str() dropAllReferences = Method() + + getTypeByName = Method(ptr(StructType), cast(str, StringRef)) + + \ No newline at end of file diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 8e6b381..09b8ba9 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -110,6 +110,12 @@ class Type: getIntNPtrTy = StaticMethod(ptr(PointerType), ref(LLVMContext), cast(int, Unsigned)) + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os) + return os.str() @IntegerType class IntegerType: @@ -130,4 +136,23 @@ class PointerType: @StructType class StructType: - pass + isPacked = Method(cast(Bool, bool)) + isLiteral = Method(cast(Bool, bool)) + isOpaque = Method(cast(Bool, bool)) + hasName = Method(cast(Bool, bool)) + getName = Method(cast(StringRef, str)) + setName = Method(Void, cast(str, StringRef)) + setBody = CustomMethod('StructType_setBody', + PyObjectPtr, # None + PyObjectPtr, # ArrayRef + cast(bool, Bool), + ).require_only(1) + getNumElements = Method(cast(Unsigned, int)) + getElementType = Method(ptr(Type), cast(int, Unsigned)) + + create = StaticMethod(ptr(StructType), + ref(LLVMContext), + cast(str, StringRef), + ).require_only(1) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5841746..5675fa5 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -1,13 +1,8 @@ from binding import * from namespace import llvm -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter -from Type import Type -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -Value = llvm.Class() # forward declarations +Value = llvm.Class() Argument = llvm.Class(Value) MDNode = llvm.Class(Value) User = llvm.Class(Value) @@ -16,6 +11,13 @@ Constant = llvm.Class(User) GlobalValue = llvm.Class(Constant) Function = llvm.Class(GlobalValue) +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Type import Type +from LLVMContext import LLVMContext +from ADT.StringRef import StringRef + + @Value class Value: From 39de8c400332ffac9bfbdbaba4fd8ca48f08bdc4 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 18:49:33 -0600 Subject: [PATCH 072/338] Expand test --- newbinding/test_binding.py | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 1321eb6..578c532 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -151,6 +151,10 @@ def test_basic_jit_use(): m2.setModuleIdentifier(m.getModuleIdentifier()) assert str(m2) == str(m) + # parse llvm ir + m3 = api.ParseAssemblyString(str(m), None, api.SMDiagnostic.new(), context) + m3.setModuleIdentifier(m.getModuleIdentifier()) + assert str(m3) == str(m) def test_engine_builder(): api.InitializeNativeTarget() @@ -223,10 +227,64 @@ def test_engine_builder(): assert 'foo' in asm +def test_linker(): + context = api.getGlobalContext() + mA = api.Module.new("modA", context) + mB = api.Module.new("modB", context) + def create_function(m, name): + int32ty = api.Type.getIntNTy(context, 32) + fnty = api.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction(name, fnty)._downcast(api.Function) + bb = api.BasicBlock.Create(context, "entry", fn, None) + builder = api.IRBuilder.new(context) + builder.SetInsertPoint(bb) + builder.CreateRet(fn.getArgumentList()[0]) + create_function(mA, 'foo') + create_function(mB, 'bar') + errmsg = StringIO() + linkermode = api.Linker.LinkerMode.PreserveSource + failed = api.Linker.LinkModules(mA, mB, linkermode, errmsg) + assert not failed, errmsg.getvalue() + assert mA.getFunction('foo') + assert mA.getFunction('bar') + + assert set(mA.list_functions()) == set([mA.getFunction('foo'), + mA.getFunction('bar')]) + +def test_structtype(): + context = api.getGlobalContext() + m = api.Module.new("modname", context) + + assert m.getTypeByName("truck") is None + + truck = api.StructType.create(context, "truck") + assert 'type opaque' in str(truck) + elemtys = [api.Type.getInt32Ty(context), api.Type.getDoubleTy(context)] + truck.setBody(elemtys) + + assert 'i32' in str(truck) + assert 'double' in str(truck) + + assert m.getTypeByName("truck") is truck + +def test_globalvariable(): + context = api.getGlobalContext() + m = api.Module.new("modname", context) + + ty = api.Type.getInt32Ty(context) + LinkageTypes = api.GlobalVariable.LinkageTypes + linkage = LinkageTypes.ExternalLinkage + gvar = api.GlobalVariable.new(m, ty, False, linkage, None, "apple") + assert '@apple = external global i32' in str(m) + + gvar2 = m.getNamedGlobal('apple') + assert gvar2 is gvar + + print m.list_globals() def main(): for name, value in globals().items(): @@ -234,6 +292,7 @@ def main(): print name.center(80, '-') value() + if __name__ == '__main__': main() From cd1fa4c4d825efab4cc8b3ac1375f72dd2725dbe Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 6 Feb 2013 21:30:36 -0600 Subject: [PATCH 073/338] Add binding for Attributes, Argument, Constants, CallingConv, GlobalValue, GlobalVariable, etc. --- newbinding/gen/binding.py | 1 + newbinding/include/llvm_binding/conversion.h | 22 ++ newbinding/include/llvm_binding/extra.h | 152 +++++++++-- newbinding/src/Analysis/Verifier.py | 25 ++ newbinding/src/Analysis/__init__.py | 10 + newbinding/src/Argument.py | 4 + newbinding/src/Attributes.py | 39 +++ newbinding/src/CallingConv.py | 11 + newbinding/src/Constant.py | 260 ++++++++++++++++++- newbinding/src/DerivedTypes.py | 1 - newbinding/src/Function.py | 5 + newbinding/src/GlobalValue.py | 21 ++ newbinding/src/GlobalVariable.py | 3 +- newbinding/src/IRBuilder.py | 29 ++- newbinding/src/Metadata.py | 17 ++ newbinding/src/Module.py | 13 +- newbinding/src/Transforms/Utils/Cloning.py | 8 + newbinding/src/Transforms/Utils/__init__.py | 15 ++ newbinding/src/Transforms/__init__.py | 11 +- newbinding/src/Type.py | 59 ++++- newbinding/src/User.py | 8 +- newbinding/src/Value.py | 13 + 22 files changed, 692 insertions(+), 35 deletions(-) create mode 100644 newbinding/src/Analysis/Verifier.py create mode 100644 newbinding/src/Analysis/__init__.py create mode 100644 newbinding/src/Attributes.py create mode 100644 newbinding/src/CallingConv.py create mode 100644 newbinding/src/Transforms/Utils/Cloning.py create mode 100644 newbinding/src/Transforms/Utils/__init__.py diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index d9b44af..09cd9bf 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -69,6 +69,7 @@ LongLong = BuiltinTypes('long long') Float = BuiltinTypes('float') Double = BuiltinTypes('double') Uint64 = BuiltinTypes('uint64_t') +Int64 = BuiltinTypes('int64_t') Size_t = BuiltinTypes('size_t') VoidPtr = BuiltinTypes('void*') Bool = BuiltinTypes('bool') diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h index a1fc87c..cf4e639 100644 --- a/newbinding/include/llvm_binding/conversion.h +++ b/newbinding/include/llvm_binding/conversion.h @@ -64,6 +64,28 @@ int py_str_to(PyObject *strobj, const char* &strref){ return 1; } + +static +int py_int_to(PyObject *intobj, int64_t & val){ + if (!PyInt_Check(intobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting an int"); + return 0; + } + if (PyLong_Check(intobj)) { + val = PyLong_AsLongLong(intobj); + } else { + val = PyInt_AsLong(intobj); + } + if (PyErr_Occurred()){ + return NULL; + } + // success + return 1; +} + + + static int py_int_to(PyObject *intobj, unsigned & val){ if (!PyInt_Check(intobj)) { diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index fd4eb4e..85e1ea5 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "auto_pyobject.h" @@ -171,6 +173,33 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, className); } +template +struct extract { + + template + static + bool from_py_sequence(VecTy& vec, PyObject* seq, const char *capsuleName) + { + Py_ssize_t N = PySequence_Size(seq); + for (Py_ssize_t i = 0; i < N; ++i) { + auto_pyobject item = PySequence_GetItem(seq, i); + if (!item) { + return false; + } + auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); + if (!capsule) { + return false; + } + void* ptr = PyCapsule_GetPointer(*capsule, capsuleName); + if (!ptr) { + return false; + } + vec.push_back(static_cast(ptr)); + } + return true; + } + +}; //static //bool string_equal(const char *A, const char *B){ // for (; *A and *B; ++A, ++B) { @@ -492,7 +521,7 @@ PyObject* TargetMachine_addPassesToEmitFile( if (!buf) { return NULL; } - if ( -1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW) ){ + if (-1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW)){ return NULL; } Py_RETURN_TRUE; @@ -501,6 +530,30 @@ PyObject* TargetMachine_addPassesToEmitFile( } } +static +PyObject* Constant_getIntegerValue(llvm::Type* Ty, PyObject* pyint) +{ + using namespace llvm; + if (!Ty->isIntegerTy()) { + PyErr_SetString(PyExc_ValueError, "Type should be of integer type."); + return NULL; + } + unsigned width = Ty->getIntegerBitWidth(); + if (width > sizeof(unsigned long long)*8) { + PyErr_SetString(PyExc_ValueError, "Integer value is too large."); + } + Constant* K; + if (PyLong_Check(pyint)){ + APInt apint(width, PyLong_AsLongLong(pyint), true); + K = Constant::getIntegerValue(Ty, apint); + } else { + APInt apint(width, PyInt_AsLong(pyint), true); + K = Constant::getIntegerValue(Ty, apint); + } + return pycapsule_new(K, "llvm::Value", "llvm::Constant"); +} + + static PyObject* Linker_LinkInModule(llvm::Linker* Linker, llvm::Module* Mod, @@ -543,24 +596,8 @@ PyObject* StructType_setBody(llvm::StructType* Self, { using namespace llvm; std::vector elements; - Py_ssize_t N = PySequence_Size(Elems); - elements.reserve(N); - for (Py_ssize_t i=0; i < N; ++i) { - auto_pyobject obj = PySequence_GetItem(Elems, i); - auto_pyobject capsule = PyObject_GetAttrString(*obj, "_ptr"); - if (!capsule) { - return NULL; - } - void * ptr = PyCapsule_GetPointer(*capsule, "llvm::Type"); - if (!ptr) { - return NULL; - } - Type* type = static_cast(ptr); - elements.push_back(type); - } - + extract::from_py_sequence(elements, Elems, "llvm::Type"); Self->setBody(elements, isPacked); - Py_RETURN_NONE; } @@ -578,3 +615,82 @@ PyObject* Module_list_functions(llvm::Module* Mod) "llvm::Value", "llvm::Function"); } +static +PyObject* Module_list_named_metadata(llvm::Module* Mod) +{ + return iplist_to_pylist(Mod->getFunctionList(), + "llvm::NamedMDNode", "llvm::NamedMDNode"); + +} + +static +PyObject* llvm_verifyModule(const llvm::Module& Fn, + llvm::VerifierFailureAction Action, + PyObject* ErrMsg) +{ + std::string errmsg; + bool failed = llvm::verifyModule(Fn, Action, &errmsg); + + if (failed) { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static +PyObject* ConstantArray_get(llvm::ArrayType* Ty, PyObject* Consts) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Consts, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantArray::get(Ty, vec_consts); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + +static +PyObject* ConstantStruct_get(llvm::StructType* Ty, PyObject* Elems) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Elems, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantStruct::get(Ty, vec_consts); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + +static +PyObject* ConstantStruct_getAnon(PyObject* Elems, + bool isPacked=false) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Elems, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantStruct::getAnon(vec_consts, isPacked); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + +static +PyObject* ConstantVector_get(PyObject* Elems) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Elems, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantVector::get(vec_consts); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + diff --git a/newbinding/src/Analysis/Verifier.py b/newbinding/src/Analysis/Verifier.py new file mode 100644 index 0000000..5b47740 --- /dev/null +++ b/newbinding/src/Analysis/Verifier.py @@ -0,0 +1,25 @@ +from binding import * +from ..namespace import llvm +from ..Module import Module +from ..Function import Function + +llvm.includes.add('llvm/Analysis/Verifier.h') + +VerifierFailureAction = llvm.Enum('VerifierFailureAction', + '''AbortProcessAction + PrintMessageAction + ReturnStatusAction''') + +verifyModule = llvm.CustomFunction('verifyModule', + 'llvm_verifyModule', + PyObjectPtr, # boolean -- failed? + ref(Module), + VerifierFailureAction, + PyObjectPtr, # errmsg + ) + +verifyFunction = llvm.Function('verifyFunction', + cast(Bool, bool), # failed? + ref(Function), + VerifierFailureAction) + diff --git a/newbinding/src/Analysis/__init__.py b/newbinding/src/Analysis/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Analysis/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/Argument.py b/newbinding/src/Argument.py index 08b35be..eac4b07 100644 --- a/newbinding/src/Argument.py +++ b/newbinding/src/Argument.py @@ -1,9 +1,13 @@ from binding import * from namespace import llvm from Value import Argument +from Attributes import Attributes @Argument class Argument: _include_ = 'llvm/Argument.h' + addAttr = Method(Void, ref(Attributes)) + removeAttr = Method(Void, ref(Attributes)) + getParamAlignment = Method(cast(Unsigned, int)) diff --git a/newbinding/src/Attributes.py b/newbinding/src/Attributes.py new file mode 100644 index 0000000..235d2c8 --- /dev/null +++ b/newbinding/src/Attributes.py @@ -0,0 +1,39 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext + +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 = Method(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/newbinding/src/CallingConv.py b/newbinding/src/CallingConv.py new file mode 100644 index 0000000..6d0baea --- /dev/null +++ b/newbinding/src/CallingConv.py @@ -0,0 +1,11 @@ +from binding import * +from namespace import llvm + +@llvm.Class() # actually a namespace +class CallingConv: + ID = Enum(''' + C, Fast, Cold, GHC, FirstTargetCC, X86_StdCall, X86_FastCall, + ARM_APCS, ARM_AAPCS, ARM_AAPCS_VFP, MSP430_INTR, X86_ThisCall, + PTX_Kernel, PTX_Device, MBLAZE_INTR, MBLAZE_SVOL, SPIR_FUNC, + SPIR_KERNEL, Intel_OCL_BI + ''') # HiPE diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index c59fef4..9027e3f 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -1,8 +1,266 @@ from binding import * from namespace import llvm -from Value import Constant +from LLVMContext import LLVMContext +from ADT.StringRef import StringRef +from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from Type import Type, IntegerType, ArrayType, StructType +from Value import Constant, Value +from Instruction import CmpInst @Constant class Constant: + _downcast_ = Value + + isNullValue = Method(cast(bool, Bool)) + isAllOnesValue = Method(cast(bool, Bool)) + isNegativeZeroValue = Method(cast(bool, Bool)) + #isZeroValue = Method(cast(bool, Bool)) + canTrap = Method(cast(bool, Bool)) + isThreadDependent = Method(cast(bool, Bool)) + isConstantUsed = Method(cast(bool, Bool)) + + _getAggregateElement_by_int = Method(ptr(Constant), cast(int, Unsigned)) + _getAggregateElement_by_int.realname = 'getAggregateElement' + _getAggregateElement_by_const = Method(ptr(Constant), ptr(Constant)) + _getAggregateElement_by_const.realname = 'getAggregateElement' + + @CustomPythonMethod + def getAggregateElement(self, elt): + if isinstance(elt, Constant): + return self._getAggregateElement_by_const(elt) + else: + return self._getAggregateElement_by_int(elt) + + + removeDeadConstantUsers = Method() + + getNullValue = StaticMethod(ptr(Constant), ptr(Type)) + getAllOnesValue = StaticMethod(ptr(Constant), ptr(Type)) + getIntegerValue = CustomStaticMethod('Constant_getIntegerValue', + PyObjectPtr, # ptr(Constant), + ptr(Type), + PyObjectPtr) + + +UndefValue = llvm.Class(Constant) + +@UndefValue +class UndefValue: + getSequentialElement = Method(ptr(UndefValue)) + getStructElement = Method(ptr(UndefValue), cast(int, Unsigned)) + + _getElementValue_by_const = Method(ptr(UndefValue), ptr(Constant)) + _getElementValue_by_const.realname = 'getElementValue' + + _getElementValue_by_int = Method(ptr(UndefValue), cast(int, Unsigned)) + _getElementValue_by_int.realname = 'getElementValue' + + @CustomPythonMethod + def getElementValue(self, idx): + if isinstance(idx, Constant): + return self._getElementValue_by_const(idx) + else: + return self._getElementValue_by_int(idx) + + destroyConstant = Method() + + get = StaticMethod(ptr(UndefValue), ptr(Type)) + + +ConstantInt = llvm.Class(Constant) + +@ConstantInt +class ConstantInt: + get = StaticMethod(ptr(ConstantInt), + ptr(IntegerType), + cast(int, Unsigned), + cast(bool, Bool), + ).require_only(2) + isValueValidForType = StaticMethod(cast(Bool, bool), + ptr(Type), + cast(int, Int64)) + getZExtValue = Method(cast(Uint64, int)) + getSExtValue = Method(cast(Int64, int)) + +ConstantFP = llvm.Class(Constant) + +@ConstantFP +class ConstantFP: + get = StaticMethod(ptr(Constant), ptr(Type), cast(float, Double)) + getNegativeZero = StaticMethod(ptr(ConstantFP), ptr(Type)) + getInfinity = StaticMethod(ptr(ConstantFP), ptr(Type), cast(bool, Bool)) + + isZero = Method(cast(Bool, bool)) + isNegative = Method(cast(Bool, bool)) + isNaN = Method(cast(Bool, bool)) + + +ConstantArray = llvm.Class(Constant) + +@ConstantArray +class ConstantArray: + get = CustomStaticMethod('ConstantArray_get', + PyObjectPtr, # ptr(Constant), + ptr(ArrayType), + PyObjectPtr, # Constants + ) + +ConstantStruct = llvm.Class(Constant) + +@ConstantStruct +class ConstantStruct: + get = CustomStaticMethod('ConstantStruct_get', + PyObjectPtr, # ptr(Constant) + ptr(StructType), + PyObjectPtr, # Constants + ) + getAnon = CustomStaticMethod('ConstantStruct_getAnon', + PyObjectPtr, # ptr(Constant) + PyObjectPtr, # constants + cast(bool, Bool), # packed + ).require_only(1) + +ConstantVector = llvm.Class(Constant) + +@ConstantVector +class ConstantVector: + get = CustomStaticMethod('ConstantVector_get', + PyObjectPtr, # ptr(Constant) + PyObjectPtr, # constants + ) + +ConstantDataSequential = llvm.Class(Constant) + +@ConstantDataSequential +class ConstantDataSequential: pass +ConstantDataArray = llvm.Class(ConstantDataSequential) + +@ConstantDataArray +class ConstantDataArray: + getString = StaticMethod(ptr(Constant), + ref(LLVMContext), + cast(str, StringRef), + cast(bool, Bool) + ).require_only(2) + + +ConstantExpr = llvm.Class(Constant) + +def _factory(*args): + return StaticMethod(ptr(Constant), *args) + +def _factory_const(*args): + return _factory(ptr(Constant), *args) + +def _factory_const2(*args): + return _factory(ptr(Constant), ptr(Constant), *args) + +def _factory_const_nuw_nsw(): + return _factory_const(cast(bool, Bool), cast(bool, Bool)).require_only(1) + +def _factory_const2_nuw_nsw(): + return _factory_const2(cast(bool, Bool), cast(bool, Bool)).require_only(2) + +def _factory_const2_exact(): + return _factory_const2(cast(bool, Bool)).require_only(2) + +def _factory_const_type(): + return _factory_const(ptr(Type)) + +@ConstantExpr +class ConstantExpr: + getAlignOf = _factory(ptr(Type)) + getSizeOf = _factory(ptr(Type)) + getOffsetOf = _factory(ptr(Type), ptr(Constant)) + getNeg = _factory_const_nuw_nsw() + getFNeg = _factory_const() + getNot = _factory_const() + getAdd = _factory_const2_nuw_nsw() + getFAdd = _factory_const2() + getSub = _factory_const2_nuw_nsw() + getFSub = _factory_const2() + getMul = _factory_const2_nuw_nsw() + getFMul = _factory_const2() + getUDiv = _factory_const2_exact() + getSDiv = _factory_const2_exact() + getFDiv = _factory_const2() + getURem = _factory_const2() + getSRem = _factory_const2() + getFRem = _factory_const2() + getAnd = _factory_const2() + getOr = _factory_const2() + getXor = _factory_const2() + getShl = _factory_const2_nuw_nsw() + getLShr = _factory_const2_exact() + getAShr = _factory_const2_exact() + getTrunc = _factory_const_type() + getSExt = _factory_const_type() + getZExt = _factory_const_type() + getFPTrunc = _factory_const_type() + getFPExtend = _factory_const_type() + getUIToFP = _factory_const_type() + getSIToFP = _factory_const_type() + getFPToUI = _factory_const_type() + getFPToSI = _factory_const_type() + getPtrToInt = _factory_const_type() + getIntToPtr = _factory_const_type() + getBitCast = _factory_const_type() + + getCompare = _factory(CmpInst.Predicate, ptr(Constant), ptr(Constant)) + getICmp = _factory(CmpInst.Predicate, ptr(Constant), ptr(Constant)) + getFCmp = _factory(CmpInst.Predicate, ptr(Constant), ptr(Constant)) + + getPointerCast = _factory_const_type() + getIntegerCast = _factory_const(ptr(Type), cast(bool, Bool)) + getFPCast = _factory_const_type() + getSelect = _factory(ptr(Constant), ptr(Constant), ptr(Constant)) + + + _getGEP = _factory(ptr(Constant), ref(SmallVector_Value), cast(bool, Bool)) + _getGEP.require_only(2) + _getGEP.realname = 'getGetElementPtr' + + @CustomPythonStaticMethod + def getGetElementPtr(*args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return ConstantExpr._getGEP(*args) + + getExtractElement = _factory_const2() + getInsertElement = _factory_const2(ptr(Constant)) + getShuffleVector = _factory_const2(ptr(Constant)) + + _getExtractValue = _factory(ptr(Constant), ref(SmallVector_Unsigned)) + _getExtractValue.realname = 'getExtractValue' + + @CustomPythonStaticMethod + def getExtractValue(*args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return ConstantExpr._getExtractValue(*args) + + _getInsertValue = _factory(ptr(Constant), ptr(Constant), + ref(SmallVector_Unsigned)) + _getInsertValue.realname = 'getInsertValue' + + @CustomPythonStaticMethod + def getInsertValue(*args): + import extra + args = list(args) + valuelist = args[2] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return ConstantExpr._getInsertValue(*args) + + getOpcode = Method(cast(Unsigned, int)) + getOpcodeName = Method(cast(ConstCharPtr, str)) + isCast = Method(cast(Bool, bool)) + isCompare = Method(cast(Bool, bool)) + hasIndices = Method(cast(Bool, bool)) + isGEPWithNoNotionalOverIndexing = Method(cast(Bool, bool)) + diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index af9e757..e71f1a8 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -25,7 +25,6 @@ class FunctionType: else: return FunctionType._get(*args) - isVarArg = Method(cast(Bool, bool)) getReturnType = Method(ptr(Type)) getParamType = Method(ptr(Type), cast(int, Unsigned)) diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index 5cebf84..ee59990 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -4,6 +4,7 @@ from Value import GlobalValue, Constant, Function, Argument from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext +from CallingConv import CallingConv @Function class Function: @@ -17,5 +18,9 @@ class Function: getIntrinsicID = Method(cast(Unsigned, int)) isIntrinsic = Method(cast(Bool, bool)) + getCallingConv = Method(CallingConv.ID) + setCallingConv = Method(Void, CallingConv.ID) + + getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index d14d48a..02ba4ea 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm from Value import GlobalValue +from Module import Module +from ADT.StringRef import StringRef @GlobalValue class GlobalValue: @@ -24,3 +26,22 @@ class GlobalValue: setVisibility = Method(Void, VisibilityTypes) getVisibility = Method(VisibilityTypes) + setLinkage = Method(Void, LinkageTypes) + getLinkage = Method(LinkageTypes) + + getAlignment = Method(cast(Unsigned, int)) + setAlignment = Method(Void, cast(int, Unsigned)) + + hasSection = Method(cast(Bool, bool)) + getSection = Method(cast(ConstStdString, str)) + setSection = Method(Void, cast(str, StringRef)) + + isDiscardableIfUnused = Method(cast(Bool, bool)) + mayBeOverridden = Method(cast(Bool, bool)) + isWeakForLinker = Method(cast(Bool, bool)) + copyAttributesFrom = Method(Void, ptr(GlobalValue)) + destroyConstant = Method() + isDeclaration = Method(cast(Bool, bool)) + removeFromParent = Method() + eraseFromParent = Method() + getParent = Method(ptr(Module)) diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py index 70203d5..a11f259 100644 --- a/newbinding/src/GlobalVariable.py +++ b/newbinding/src/GlobalVariable.py @@ -33,7 +33,7 @@ class GlobalVariable: isThreadLocal = Method(cast(Bool, bool)) isConstant = Method(cast(Bool, bool)) - setConstant = Method(Void, ptr(Constant)) + setConstant = Method(Void, cast(bool, Bool)) setInitializer = Method(Void, ptr(Constant)) getInitializer = Method(ptr(Constant)) @@ -45,4 +45,5 @@ class GlobalVariable: # isExternallyInitialized = Method(cast(Bool, bool)) # setExternallyinitialized = Method(Void, cast(bool, Bool)) + eraseFromParent = Method() \ No newline at end of file diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index 61dd99b..e0cac79 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -242,13 +242,32 @@ class IRBuilder: ptr(Value), cast(str, StringRef)) CreateShuffleVector.require_only(3) - CreateExtractValue = Method(ptr(Value), ptr(Value), ref(SmallVector_Unsigned), - cast(str, StringRef)) - CreateExtractValue.require_only(2) + _CreateExtractValue = Method(ptr(Value), ptr(Value), + ref(SmallVector_Unsigned), + cast(str, StringRef)) + _CreateExtractValue.require_only(2) + _CreateExtractValue.realname = 'CreateExtractValue' - CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), + @CustomPythonMethod + def CreateExtractValue(self, args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return self._CreateExtractValue(*args) + + _CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), ref(SmallVector_Unsigned), cast(str, StringRef)) - CreateInsertValue.require_only(3) + _CreateInsertValue.require_only(3) + _CreateInsertValue.realname = 'CreateInsertValue' + + @CustomPythonMethod + def CreateInsertValue(self, args): + import extra + args = list(args) + valuelist = args[2] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return self._CreateInsertValue(*args) CreateLandingPad = Method(ptr(LandingPadInst), ptr(Type), ptr(Value), cast(int, Unsigned), cast(str, StringRef)) diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py index 78dbe15..96dbc01 100644 --- a/newbinding/src/Metadata.py +++ b/newbinding/src/Metadata.py @@ -1,7 +1,24 @@ from binding import * from namespace import llvm from Value import MDNode +from ADT.StringRef import StringRef +from Module import Module +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: pass + +@llvm.Class() +class NamedMDNode: + eraseFromParent = Method() + dropAllReferences = Method() + getParent = Method(ptr(Module)) + getOperand = Method(ptr(MDNode), cast(int, Unsigned)) + getNumOperands = Method(cast(Unsigned, int)) + getName = Method(cast(StringRef, str)) + print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) + print_.realname = "print" + dump = Method() + diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 706fe48..7718cd6 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -12,6 +12,7 @@ from DerivedTypes import FunctionType from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter from Type import Type, StructType +from Metadata import NamedMDNode @Module class Module: @@ -59,6 +60,16 @@ class Module: # GlobalVariable Iteration list_globals = CustomMethod('Module_list_globals', PyObjectPtr) + # Named MetaData Accessors + getNamedMetadata = Method(ptr(NamedMDNode), cast(str, StringRef)) + getOrInsertNamedMetadata = Method(ptr(NamedMDNode), cast(str, StringRef)) + eraseNamedMetadata = Method(Void, ptr(NamedMDNode)) + + # Named MetaData Iteration + list_named_metadata = CustomMethod('Module_list_named_metadata', + PyObjectPtr) + + # Utilities dump = Method(Void) print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) @@ -74,5 +85,3 @@ class Module: dropAllReferences = Method() getTypeByName = Method(ptr(StructType), cast(str, StringRef)) - - \ No newline at end of file diff --git a/newbinding/src/Transforms/Utils/Cloning.py b/newbinding/src/Transforms/Utils/Cloning.py new file mode 100644 index 0000000..c7f7a86 --- /dev/null +++ b/newbinding/src/Transforms/Utils/Cloning.py @@ -0,0 +1,8 @@ +from binding import * +from src.namespace import llvm +from src.Module import Module + +llvm.includes.add('llvm/Transforms/Utils/Cloning.h') +CloneModule = llvm.Function('CloneModule', ptr(Module), ptr(Module)) + + diff --git a/newbinding/src/Transforms/Utils/__init__.py b/newbinding/src/Transforms/Utils/__init__.py new file mode 100644 index 0000000..98c06fc --- /dev/null +++ b/newbinding/src/Transforms/Utils/__init__.py @@ -0,0 +1,15 @@ +import os.path, importlib + +def _init(): + base = os.path.dirname(__file__) + for fname in os.listdir(base): + print fname + is_python_script = fname.endswith('.py') or fname.endswith('.pyc') + is_init_script = fname.startswith('__init__') + is_directory = os.path.isdir(os.path.join(base, fname)) + if (is_directory or is_python_script) and not is_init_script : + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() + diff --git a/newbinding/src/Transforms/__init__.py b/newbinding/src/Transforms/__init__.py index da0beed..98c06fc 100644 --- a/newbinding/src/Transforms/__init__.py +++ b/newbinding/src/Transforms/__init__.py @@ -1,10 +1,15 @@ import os.path, importlib def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): + base = os.path.dirname(__file__) + for fname in os.listdir(base): + print fname + is_python_script = fname.endswith('.py') or fname.endswith('.pyc') + is_init_script = fname.startswith('__init__') + is_directory = os.path.isdir(os.path.join(base, fname)) + if (is_directory or is_python_script) and not is_init_script : modname = os.path.basename(fname).rsplit('.', 1)[0] importlib.import_module('.' + modname, __name__) _init() + diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 09b8ba9..4078a9d 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -9,17 +9,29 @@ IntegerType = llvm.Class(Type) CompositeType = llvm.Class(Type) StructType = llvm.Class(CompositeType) SequentialType = llvm.Class(CompositeType) +ArrayType = llvm.Class(SequentialType) PointerType = llvm.Class(SequentialType) +VectorType = llvm.Class(SequentialType) @Type class Type: _include_ = 'llvm/Type.h' + TypeID = Enum(''' + VoidTyID, HalfTyID, FloatTyID, DoubleTyID, + X86_FP80TyID, FP128TyID, PPC_FP128TyID, LabelTyID, + MetadataTyID, X86_MMXTyID, IntegerTyID, FunctionTyID, + StructTyID, ArrayTyID, PointerTyID, VectorTyID, + NumTypeIDs, LastPrimitiveTyID, FirstDerivedTyID + ''') + getContext = Method(ref(LLVMContext)) dump = Method() print_ = Method(Void, ref(raw_ostream)) print_.realname = 'print' + getTypeID = Method(TypeID) + def type_checker(): return Method(cast(Bool, bool)) @@ -81,7 +93,8 @@ class Type: getPPC_FP128Ty = type_factory() getX86_MMXTy = type_factory() - getIntNTy = StaticMethod(ptr(IntegerType), ref(LLVMContext), cast(Unsigned, int)) + getIntNTy = StaticMethod(ptr(IntegerType), + ref(LLVMContext), cast(Unsigned, int)) def integer_factory(): return StaticMethod(ptr(IntegerType), ref(LLVMContext)) @@ -117,6 +130,20 @@ class Type: self.print_(os) return os.str() + getContainedType = Method(ptr(Type), cast(int, Unsigned)) + getNumContainedTypes = Method(cast(int, Unsigned)) + + getArrayNumElements = Method(cast(Uint64, int)) + getArrayElementType = Method(ptr(Type)) + + getVectorNumElements = Method(cast(Unsigned, int)) + getVectorElementType = Method(ptr(Type)) + + getPointerElementType = Method(ptr(Type)) + getPointerAddressSpace = Method(cast(Unsigned, int)) + getPointerTo = Method(ptr(PointerType), cast(int, Unsigned)) + + @IntegerType class IntegerType: pass @@ -130,9 +157,30 @@ class CompositeType: class SequentialType: pass +@ArrayType +class ArrayType: + getNumElements = Method(cast(Uint64, int)) + get = StaticMethod(ptr(ArrayType), ptr(Type), cast(int, Uint64)) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) + @PointerType class PointerType: - pass + getAddressSpace = Method(cast(Unsigned, int)) + get = StaticMethod(ptr(PointerType), ptr(Type), cast(int, Unsigned)) + getUnqual = StaticMethod(ptr(PointerType), ptr(Type)) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) + +@VectorType +class VectorType: + getNumElements = Method(cast(Unsigned, int)) + getBitWidth = Method(cast(Unsigned, int)) + get = StaticMethod(ptr(VectorType), ptr(Type), cast(int, Unsigned)) + getInteger = StaticMethod(ptr(VectorType), ptr(VectorType)) + getExtendedElementVectorType = StaticMethod(ptr(VectorType), + ptr(VectorType)) + getTruncatedElementVectorType = StaticMethod(ptr(VectorType), + ptr(VectorType)) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) @StructType class StructType: @@ -154,5 +202,12 @@ class StructType: ref(LLVMContext), cast(str, StringRef), ).require_only(1) + + get = StaticMethod(ptr(StructType), + ref(LLVMContext), + cast(bool, Bool), # is packed + ).require_only(1) + + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) diff --git a/newbinding/src/User.py b/newbinding/src/User.py index 57d58bc..9a077c1 100644 --- a/newbinding/src/User.py +++ b/newbinding/src/User.py @@ -1,7 +1,11 @@ from binding import * from namespace import llvm -from Value import User +from Value import Value, User @User class User: - pass + _downcast_ = Value + getOperand = Method(ptr(Value), cast(int, Unsigned)) + setOperand = Method(Void, cast(int, Unsigned), ptr(Value)) + getNumOperands = Method(cast(Unsigned, int)) + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5675fa5..5d8c0a9 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -21,6 +21,16 @@ from ADT.StringRef import StringRef @Value class Value: + ValueTy = Enum(''' + ArgumentVal, BasicBlockVal, FunctionVal, GlobalAliasVal, + GlobalVariableVal, UndefValueVal, BlockAddressVal, ConstantExprVal, + ConstantAggregateZeroVal, ConstantDataArrayVal, ConstantDataVectorVal, + ConstantIntVal, ConstantFPVal, ConstantArrayVal, ConstantStructVal, + ConstantVectorVal, ConstantPointerNullVal, MDNodeVal, MDStringVal, + InlineAsmVal, PseudoSourceValueVal, FixedStackPseudoSourceValueVal, + InstructionVal, ConstantFirstVal, ConstantLastVal + ''') + dump = Method() print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) @@ -41,6 +51,7 @@ class Value: hasOneUse = Method(cast(Bool, bool)) hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) isUsedInBasicBlock = Method(cast(Bool, bool), BasicBlock) + getNumUses = Method(cast(Unsigned, int)) @CustomPythonMethod def __str__(self): @@ -48,3 +59,5 @@ class Value: os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() + + getValueID = Method(cast(Unsigned, int)) From aa5b969961b4390a2e68dab0d6c14b23c7e92933 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 6 Feb 2013 21:31:24 -0600 Subject: [PATCH 074/338] Expand test --- newbinding/test_binding.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 578c532..5b51ecb 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -82,8 +82,16 @@ def test_basic_jit_use(): errio = StringIO() print m - # build pass manager + # verifier + action = api.VerifierFailureAction.ReturnStatusAction + corrupted = api.verifyFunction(fn, action) + assert not corrupted + corrupted = api.verifyModule(m, action, errio) + print corrupted + assert not corrupted, errio.getvalue() + + # build pass manager pmb = api.PassManagerBuilder.new() pmb.OptLevel = 3 assert pmb.OptLevel == 3 @@ -156,6 +164,11 @@ def test_basic_jit_use(): m3.setModuleIdentifier(m.getModuleIdentifier()) assert str(m3) == str(m) + # test clone + m4 = api.CloneModule(m) + assert m4 is not m + assert str(m4) == str(m) + def test_engine_builder(): api.InitializeNativeTarget() context = api.getGlobalContext() @@ -286,6 +299,26 @@ def test_globalvariable(): print m.list_globals() + +def test_sequentialtypes(): + context = api.getGlobalContext() + int32ty = api.Type.getInt32Ty(context) + ary_int32x4 = api.ArrayType.get(int32ty, 4) + assert '[4 x i32]' == str(ary_int32x4) + ptr_int32 = api.PointerType.get(int32ty, 1) + assert 'i32 addrspace(1)*' == str(ptr_int32) + vec_int32x4 = api.VectorType.get(int32ty, 4) + assert '<4 x i32>' == str(vec_int32x4) + + +def test_constants(): + context = api.getGlobalContext() + int32ty = api.Type.getInt32Ty(context) + ary_int32x4 = api.ArrayType.get(int32ty, 4) + intconst = api.ConstantInt.get(int32ty, 123) + aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4) + assert str(aryconst.getAggregateElement(0)) == str(intconst) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value): From 11cc78d780772ec90bab2581fc86e6a5046cf170 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 13:27:03 -0600 Subject: [PATCH 075/338] Add binding for Intrinsics. Add support for functions that free the resource but is not a destructor. --- newbinding/capsule.py | 14 +++++++++--- newbinding/gen/binding.py | 3 +++ newbinding/include/llvm_binding/extra.h | 19 ++++++++++++++++ newbinding/src/Function.py | 29 +++++++++++++++++++++++++ newbinding/src/GlobalValue.py | 2 ++ newbinding/src/GlobalVariable.py | 2 +- newbinding/src/Intrinsics.py | 17 +++++++++++++++ newbinding/test_binding.py | 10 +++++++++ 8 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 newbinding/src/Intrinsics.py diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 8c2f10e..e29948d 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -92,8 +92,12 @@ _cache = defaultdict(WeakValueDictionary) def release_ownership(old): logger.debug('Release %s', old) addr = Capsule.getPointer(old) - if _addr2dtor[addr] is None: - # Guard deduplicated release + + if _addr2dtor.get(addr) is None: + clsname = Capsule.getClassName(old) + if not _pyclasses[clsname]._has_dtor(): + return + # Guard duplicated release raise Exception("Already released") _addr2dtor[addr] = None @@ -117,7 +121,7 @@ def wrap(cap, owned=False): try: # lookup cached object return _cache[cls][addr] except KeyError: - if not owned and hasattr(cls, '_delete_'): + if not owned and cls._has_dtor(): _addr2dtor[addr] = cls._delete_ obj = cap.instantiate() _cache[cls][addr] = obj # cache it @@ -164,6 +168,10 @@ class Wrapper(object): def _downcast(self, newcls): return downcast(self, newcls) + @classmethod + def _has_dtor(cls): + return hasattr(cls, '_delete_') + def downcast(obj, cls): import _api if type(obj) is cls: diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 09cd9bf..1c7c7ca 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -283,6 +283,7 @@ class Method(object): self.signatures = [] self.includes = set() self._add_signature(return_type, *args) + self.disowning = False def _add_signature(self, return_type, *args): prev_lens = set(map(len, self.signatures)) @@ -350,6 +351,8 @@ class Method(object): decl = writer.function(self.name, args=('self',), varargs='args') with decl as (this, varargs): unwrap_this = writer.unwrap(this) + if self.disowning: + writer.release_ownership(unwrap_this) unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 85e1ea5..0d9ba16 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "auto_pyobject.h" @@ -694,3 +695,21 @@ PyObject* ConstantVector_get(PyObject* Elems) return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); } +static +PyObject* Intrinsic_getDeclaration(llvm::Module* Mod, + unsigned ID, + PyObject* Types=NULL) +{ + using namespace llvm; + Function* Fn = NULL; + if (Types) { + std::vector types; + bool ok = extract::from_py_sequence(types, Types, "llvm::Type"); + if (!ok) return NULL; + Fn = Intrinsic::getDeclaration(Mod, (Intrinsic::ID)ID, types); + } else { + Fn = Intrinsic::getDeclaration(Mod, (Intrinsic::ID)ID); + } + return pycapsule_new(Fn, "llvm::Value", "llvm::Function"); +} + diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index ee59990..d82b5d3 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm from Value import GlobalValue, Constant, Function, Argument +from BasicBlock import BasicBlock +from Attributes import Attributes from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext @@ -21,6 +23,33 @@ class Function: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) + hasGC = Method(cast(bool, Bool)) + getGC = Method(cast(ConstCharPtr, str)) + setGC = Method(Void, cast(str, ConstCharPtr)) + getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) + getEntryBlock = Method(ref(BasicBlock)) + + copyAttributesFrom = Method(Void, ptr(GlobalValue)) + + setDoesNotThrow = Method() + doesNotThrow = Method(cast(Bool, bool)) + setDoesNotReturn = Method() + doesNotReturn = Method(cast(Bool, bool)) + setOnlyReadsMemory = Method() + onlyReadsMemory = Method(cast(Bool, bool)) + setDoesNotAccessMemory = Method() + doesNotAccessMemory = Method(cast(Bool, bool)) + + deleteBody = Method() + viewCFG = Method() + viewCFGOnly = Method() + + addFnAttr = Method(Void, Attributes.AttrVal) + removeFnAttr = Method(Void, ref(Attributes)) + + eraseFromParent = Method() + eraseFromParent.disowning = True + diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index 02ba4ea..f21d5af 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -44,4 +44,6 @@ class GlobalValue: isDeclaration = Method(cast(Bool, bool)) removeFromParent = Method() eraseFromParent = Method() + eraseFromParent.disowning = True + getParent = Method(ptr(Module)) diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py index a11f259..4ee91fb 100644 --- a/newbinding/src/GlobalVariable.py +++ b/newbinding/src/GlobalVariable.py @@ -45,5 +45,5 @@ class GlobalVariable: # isExternallyInitialized = Method(cast(Bool, bool)) # setExternallyinitialized = Method(Void, cast(bool, Bool)) - eraseFromParent = Method() + \ No newline at end of file diff --git a/newbinding/src/Intrinsics.py b/newbinding/src/Intrinsics.py new file mode 100644 index 0000000..0f1bcb4 --- /dev/null +++ b/newbinding/src/Intrinsics.py @@ -0,0 +1,17 @@ +from binding import * +from namespace import llvm + +from Module import Module +from Function import Function + + +Intrinsic = llvm.Class() # fake class (actually a namespace) + +@Intrinsic +class Intrinsic: + getDeclaration = CustomStaticMethod('Intrinsic_getDeclaration', + PyObjectPtr, # Function* + ptr(Module), + cast(int, Unsigned), # intrinsic id + PyObjectPtr, # list of Type + ).require_only(2) diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 5b51ecb..9003f7d 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -319,6 +319,16 @@ def test_constants(): aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4) assert str(aryconst.getAggregateElement(0)) == str(intconst) +def test_intrinsic(): + context = api.getGlobalContext() + m = api.Module.new("modname", context) + INTR_SIN = 1652 + floatty = api.Type.getFloatTy(context) + fn = api.Intrinsic.getDeclaration(m, INTR_SIN, [floatty]) + assert 'llvm.sin.f32' in str(fn) + fn.eraseFromParent() + assert 'llvm.sin.f32' not in str(m) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value): From 541c119fc38ef87e7ade743ceb4402db7f213b68 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 13:50:16 -0600 Subject: [PATCH 076/338] Add binding for MDNode, MDString, InlineAsm --- newbinding/include/llvm_binding/extra.h | 17 +++++++++++++++-- newbinding/src/InlineAsm.py | 24 ++++++++++++++++++++++++ newbinding/src/Metadata.py | 23 +++++++++++++++++++++-- newbinding/src/Value.py | 1 + 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 newbinding/src/InlineAsm.py diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 0d9ba16..df0cecd 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -697,8 +697,8 @@ PyObject* ConstantVector_get(PyObject* Elems) static PyObject* Intrinsic_getDeclaration(llvm::Module* Mod, - unsigned ID, - PyObject* Types=NULL) + unsigned ID, + PyObject* Types=NULL) { using namespace llvm; Function* Fn = NULL; @@ -713,3 +713,16 @@ PyObject* Intrinsic_getDeclaration(llvm::Module* Mod, return pycapsule_new(Fn, "llvm::Value", "llvm::Function"); } +static +PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) +{ + std::vector vals; + bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value"); + if (not ok) return NULL; + llvm::MDNode* md = llvm::MDNode::get(Cxt, vals); + return pycapsule_new(md, "llvm::Value", "llvm::MDNode"); +} + + + + diff --git a/newbinding/src/InlineAsm.py b/newbinding/src/InlineAsm.py new file mode 100644 index 0000000..a4ce16b --- /dev/null +++ b/newbinding/src/InlineAsm.py @@ -0,0 +1,24 @@ +from binding import * +from namespace import llvm +from Value import Value +from DerivedTypes import FunctionType +from ADT.StringRef import StringRef + +llvm.includes.add('llvm/InlineAsm.h') + +InlineAsm = llvm.Class(Value) + +@InlineAsm +class InlineAsm: + AsmDialect = Enum('AD_ATT', 'AD_Intel') + ConstraintPrefix = Enum('''isInput, isOutput, isClobber''') + + get = StaticMethod(ptr(InlineAsm), + ptr(FunctionType), + cast(str, StringRef), # AsmString + cast(str, StringRef), # Constrains + cast(bool, Bool), # hasSideEffects + cast(bool, Bool), # isAlignStack + AsmDialect, # default = AD_ATT + ).require_only(4) + diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py index 96dbc01..bda09e1 100644 --- a/newbinding/src/Metadata.py +++ b/newbinding/src/Metadata.py @@ -1,14 +1,32 @@ from binding import * from namespace import llvm -from Value import MDNode +from Value import Value, MDNode, MDString +from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Module import Module +from Function import Function from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: - pass + replaceOperandWith = Method(Void, cast(int, Unsigned), ptr(Value)) + getOperand = Method(ptr(Value), cast(int, Unsigned)) + getNumOperands = Method(cast(Unsigned, int)) + isFunctionLocal = Method(cast(Bool, bool)) + getFunction = Method(const(ptr(Function))) + + get = CustomStaticMethod('MDNode_get', + PyObjectPtr, # MDNode* + ref(LLVMContext), + PyObjectPtr, # ArrayRef + ) + +@MDString +class MDString: + get = StaticMethod(ptr(MDString), ref(LLVMContext), cast(str, StringRef)) + getString = Method(cast(StringRef, str)) + getLength = Method(cast(int, Unsigned)) @llvm.Class() class NamedMDNode: @@ -18,6 +36,7 @@ class NamedMDNode: getOperand = Method(ptr(MDNode), cast(int, Unsigned)) getNumOperands = Method(cast(Unsigned, int)) getName = Method(cast(StringRef, str)) + addOperand = Method(Void, ptr(MDNode)) print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) print_.realname = "print" dump = Method() diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5d8c0a9..27bcda0 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -5,6 +5,7 @@ from namespace import llvm Value = llvm.Class() Argument = llvm.Class(Value) MDNode = llvm.Class(Value) +MDString = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) From 113f30ffab758fc1bf7b0c9d7889ed5297379bf5 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 15:23:31 -0600 Subject: [PATCH 077/338] Add more to Instruction --- newbinding/gen/binding.py | 1 + newbinding/src/Constant.py | 23 ++++--- newbinding/src/Instruction.py | 121 +++++++++++++++++++++++++++++++--- newbinding/src/Metadata.py | 9 +++ 4 files changed, 135 insertions(+), 19 deletions(-) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 1c7c7ca..c1e1d1e 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -70,6 +70,7 @@ Float = BuiltinTypes('float') Double = BuiltinTypes('double') Uint64 = BuiltinTypes('uint64_t') Int64 = BuiltinTypes('int64_t') +Int = BuiltinTypes('int') Size_t = BuiltinTypes('size_t') VoidPtr = BuiltinTypes('void*') Bool = BuiltinTypes('bool') diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index 9027e3f..42541c4 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -1,10 +1,22 @@ from binding import * from namespace import llvm + +from Value import Constant, Value + +UndefValue = llvm.Class(Constant) +ConstantInt = llvm.Class(Constant) +ConstantFP = llvm.Class(Constant) +ConstantArray = llvm.Class(Constant) +ConstantStruct = llvm.Class(Constant) +ConstantVector = llvm.Class(Constant) +ConstantDataSequential = llvm.Class(Constant) +ConstantDataArray = llvm.Class(ConstantDataSequential) +ConstantExpr = llvm.Class(Constant) + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned from Type import Type, IntegerType, ArrayType, StructType -from Value import Constant, Value from Instruction import CmpInst @Constant @@ -42,7 +54,6 @@ class Constant: PyObjectPtr) -UndefValue = llvm.Class(Constant) @UndefValue class UndefValue: @@ -67,7 +78,6 @@ class UndefValue: get = StaticMethod(ptr(UndefValue), ptr(Type)) -ConstantInt = llvm.Class(Constant) @ConstantInt class ConstantInt: @@ -82,7 +92,6 @@ class ConstantInt: getZExtValue = Method(cast(Uint64, int)) getSExtValue = Method(cast(Int64, int)) -ConstantFP = llvm.Class(Constant) @ConstantFP class ConstantFP: @@ -95,7 +104,6 @@ class ConstantFP: isNaN = Method(cast(Bool, bool)) -ConstantArray = llvm.Class(Constant) @ConstantArray class ConstantArray: @@ -105,7 +113,6 @@ class ConstantArray: PyObjectPtr, # Constants ) -ConstantStruct = llvm.Class(Constant) @ConstantStruct class ConstantStruct: @@ -120,7 +127,6 @@ class ConstantStruct: cast(bool, Bool), # packed ).require_only(1) -ConstantVector = llvm.Class(Constant) @ConstantVector class ConstantVector: @@ -129,13 +135,11 @@ class ConstantVector: PyObjectPtr, # constants ) -ConstantDataSequential = llvm.Class(Constant) @ConstantDataSequential class ConstantDataSequential: pass -ConstantDataArray = llvm.Class(ConstantDataSequential) @ConstantDataArray class ConstantDataArray: @@ -146,7 +150,6 @@ class ConstantDataArray: ).require_only(2) -ConstantExpr = llvm.Class(Constant) def _factory(*args): return StaticMethod(ptr(Constant), *args) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py index dda6b48..79cf4a3 100644 --- a/newbinding/src/Instruction.py +++ b/newbinding/src/Instruction.py @@ -1,6 +1,11 @@ from binding import * from namespace import llvm -from Value import User +from Value import Value, MDNode, User, BasicBlock, Function +from ADT.StringRef import StringRef +from CallingConv import CallingConv +from Attributes import Attributes +from Constant import ConstantInt + Instruction = llvm.Class(User) AtomicCmpXchgInst = llvm.Class(Instruction) @@ -54,7 +59,49 @@ FPTruncInst = llvm.Class(CastInst) @Instruction class Instruction: - pass + removeFromParent = Method() + eraseFromParent = Method() + eraseFromParent.disowning = True + + getParent = Method(ptr(BasicBlock)) + getOpcode = Method(cast(Unsigned, int)) + getOpcodeName = Method(cast(ConstCharPtr, str)) + + insertBefore = Method(Void, ptr(Instruction)) + insertAfter = Method(Void, ptr(Instruction)) + moveBefore = Method(Void, ptr(Instruction)) + + isTerminator = Method(cast(Bool, bool)) + isBinaryOp = Method(cast(Bool, bool)) + isShift = Method(cast(Bool, bool)) + isCast = Method(cast(Bool, bool)) + isLogicalShift = Method(cast(Bool, bool)) + isArithmeticShift = Method(cast(Bool, bool)) + hasMetadata = Method(cast(Bool, bool)) + hasMetadataOtherThanDebugLoc = Method(cast(Bool, bool)) + isAssociative = Method(cast(Bool, bool)) + isCommutative = Method(cast(Bool, bool)) + isIdempotent = Method(cast(Bool, bool)) + isNilpotent = Method(cast(Bool, bool)) + mayWriteToMemory = Method(cast(Bool, bool)) + mayReadFromMemory = Method(cast(Bool, bool)) + mayReadOrWriteMemory = Method(cast(Bool, bool)) + mayThrow = Method(cast(Bool, bool)) + mayHaveSideEffects = Method(cast(Bool, bool)) + + hasMetadata = Method(cast(Bool, bool)) + getMetadata = Method(ptr(MDNode), cast(str, StringRef)) + setMetadata = Method(Void, cast(str, StringRef), ptr(MDNode)) + + clone = Method(ptr(Instruction)) + +# LLVM 3.3 +# hasUnsafeAlgebra = Method(cast(Bool, bool)) +# hasNoNans = Method(cast(Bool, bool)) +# hasNoInfs = Method(cast(Bool, bool)) +# hasNoSignedZeros = Method(cast(Bool, bool)) +# hasAllowReciprocal = Method(cast(Bool, bool)) + @AtomicCmpXchgInst class AtomicCmpXchgInst: @@ -71,7 +118,16 @@ class BinaryOperator: @CallInst class CallInst: - pass + _downcast_ = Value, Instruction + 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)) + getCalledFunction = Method(ptr(Function)) + getCalledValue = Method(ptr(Value)) + setCalledFunction = Method(Void, ptr(Function)) + isInlineAsm = Method(cast(Bool, bool)) @CmpInst class CmpInst: @@ -87,6 +143,8 @@ class CmpInst: 'LAST_ICMP_PREDICATE', 'BAD_ICMP_PREDICATE',) + getPredicate = Method(Predicate) + @ExtractElementInst class ExtractElementInst: pass @@ -113,7 +171,14 @@ class LandingPadInst: @PHINode class PHINode: - pass + getNumIncomingValues = Method(cast(Unsigned, int)) + getIncomingValue = Method(ptr(Value), cast(int, Unsigned)) + setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value)) + getIncomingBlock = Method(ptr(BasicBlock), cast(int, Unsigned)) + setIncomingBlock = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) + addIncoming = Method(Void, ptr(Value), ptr(BasicBlock)) + hasConstantValue = Method(ptr(Value)) + getBasicBlockIndex = Method(cast(Int, int), ptr(BasicBlock)) @SelectInst class SelectInst: @@ -125,11 +190,24 @@ class ShuffleVectorInst: @StoreInst class StoreInst: - pass + _downcast_ = Instruction + isVolatile = Method(cast(Bool, bool)) + isSimple = Method(cast(Bool, bool)) + isUnordered = Method(cast(Bool, bool)) + isAtomic = Method(cast(Bool, bool)) + + setVolatile = Method(Void, cast(Bool, bool)) + + getAlignment = Method(cast(Unsigned, int)) + setAlignment = Method(Void, cast(int, Unsigned)) + + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @TerminatorInst class TerminatorInst: - pass + getNumSuccessors = Method(cast(Unsigned, int)) + getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned)) + setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) @UnaryInstruction class UnaryInstruction: @@ -162,7 +240,15 @@ class IndirectBrInst: @InvokeInst class InvokeInst: - pass + _downcast_ = Value, Instruction + 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)) + getCalledFunction = Method(ptr(Function)) + getCalledValue = Method(ptr(Value)) + setCalledFunction = Method(Void, ptr(Function)) @ResumeInst class ResumeInst: @@ -174,7 +260,13 @@ class ReturnInst: @SwitchInst class SwitchInst: - pass + getCondition = Method(ptr(Value)) + setCondition = Method(Void, ptr(Value)) + getDefaultDest = Method(ptr(BasicBlock)) + setDefaultDest = Method(Void, ptr(BasicBlock)) + getNumCases = Method(cast(int, Unsigned)) + addCase = Method(Void, ptr(ConstantInt), ptr(BasicBlock)) + @UnreachableInst class UnreachableInst: @@ -195,7 +287,18 @@ class ExtractValueInst: @LoadInst class LoadInst: - pass + _downcast_ = Value, Instruction + isVolatile = Method(cast(Bool, bool)) + isSimple = Method(cast(Bool, bool)) + isUnordered = Method(cast(Bool, bool)) + isAtomic = Method(cast(Bool, bool)) + + setVolatile = Method(Void, cast(Bool, bool)) + + getAlignment = Method(cast(Unsigned, int)) + setAlignment = Method(Void, cast(int, Unsigned)) + + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @VAArgInst class VAArgInst: diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py index bda09e1..338cbbd 100644 --- a/newbinding/src/Metadata.py +++ b/newbinding/src/Metadata.py @@ -31,6 +31,8 @@ class MDString: @llvm.Class() class NamedMDNode: eraseFromParent = Method() + eraseFromParent.disowning = True + dropAllReferences = Method() getParent = Method(ptr(Module)) getOperand = Method(ptr(MDNode), cast(int, Unsigned)) @@ -41,3 +43,10 @@ class NamedMDNode: print_.realname = "print" dump = Method() + + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() \ No newline at end of file From b9ac22d13688cb7ae2c99e14fbed92d96312e566 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 15:31:54 -0600 Subject: [PATCH 078/338] More to BasicBlock --- newbinding/include/llvm_binding/extra.h | 8 +++++++- newbinding/src/BasicBlock.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index df0cecd..bde92a7 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -724,5 +724,11 @@ PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) } - +static +PyObject* BasicBlock_getInstList(llvm::BasicBlock* BB) +{ + return iplist_to_pylist(BB->getInstList(), + "llvm::Value", + "llvm::Instruction"); +} diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py index 61a09d7..81edf37 100644 --- a/newbinding/src/BasicBlock.py +++ b/newbinding/src/BasicBlock.py @@ -20,3 +20,5 @@ class BasicBlock: isLandingPad = Method(cast(Bool, bool)) removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool)) removePredecessor |= Method(Void, ptr(BasicBlock)) + + getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) \ No newline at end of file From fe383ca326342472b325f60e79fca563873f10cd Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 17:40:00 -0600 Subject: [PATCH 079/338] More to IRBuilder and Instruction --- newbinding/include/llvm_binding/extra.h | 15 +++++++ newbinding/src/IRBuilder.py | 54 ++++++++++++++++++++----- newbinding/src/Instruction.py | 40 ++++++++++++++---- 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index bde92a7..75739de 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "auto_pyobject.h" @@ -732,3 +733,17 @@ PyObject* BasicBlock_getInstList(llvm::BasicBlock* BB) "llvm::Instruction"); } +static +PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, + PyObject* Vals, + unsigned N) +{ + using namespace llvm; + std::vector vec_values; + bool ok = extract::from_py_sequence(vec_values, Vals, "llvm::Value"); + if (not ok) return NULL; + Value** ptr_values = &vec_values[0]; + ReturnInst* inst = builder->CreateAggregateRet(ptr_values, N); + return pycapsule_new(inst, "llvm::Value", "llvm:ReturnInst"); +} + diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index e0cac79..2965367 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -2,6 +2,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from BasicBlock import BasicBlock +from Instruction import Instruction from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst from Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst @@ -23,12 +24,30 @@ class IRBuilder: new = Constructor(ref(LLVMContext)) delete = Destructor() - SetInsertPoint = Method(Void, ptr(BasicBlock)) + GetInsertBlock = Method(ptr(BasicBlock)) + + _SetInsertPoint_end_of_bb = Method(Void, ptr(BasicBlock)) + _SetInsertPoint_end_of_bb.realname = 'SetInsertPoint' + _SetInsertPoint_before_instr = Method(Void, ptr(Instruction)) + _SetInsertPoint_before_instr.realname = 'SetInsertPoint' + + @CustomPythonMethod + def SetInsertPoint(self, pt): + if isinstance(pt, Instruction): + return self._SetInsertPoint_before_instr(pt) + elif isinstance(pt, BasicBlock): + return self._SetInsertPoint_end_of_bb(pt) + else: + raise ValueError("Expected either an Instruction or a BasicBlock") isNamePreserving = Method(cast(Bool, bool)) CreateRetVoid = Method(ptr(ReturnInst)) CreateRet = Method(ptr(ReturnInst), ptr(Value)) + CreateAggregateRet = CustomMethod('IRBuilder_CreateAggregateRet', + PyObjectPtr, # ptr(ReturnInst), + PyObjectPtr, # list of Value + cast(int, Unsigned)) CreateBr = Method(ptr(BranchInst), ptr(BasicBlock)) @@ -42,9 +61,18 @@ class IRBuilder: CreateIndirectBr = Method(ptr(IndirectBrInst), ptr(Value), cast(int, Unsigned)).require_only(1) - CreateInvoke = Method(ptr(InvokeInst), ptr(Value), ptr(BasicBlock), + _CreateInvoke = Method(ptr(InvokeInst), ptr(Value), ptr(BasicBlock), ptr(BasicBlock), ref(SmallVector_Value), cast(str, StringRef)).require_only(4) + _CreateInvoke.realname = 'CreateInvoke' + + @CustomPythonMethod + def CreateInvoke(self, *args): + import extra + args = list(args) + valuelist = args[3] + args[3] = extra.make_small_vector_from_values(*valuelist) + return self._CreateInvoke(*args) CreateResume = Method(ptr(ResumeInst), ptr(Value)) @@ -114,8 +142,11 @@ class IRBuilder: ptr(Value), cast(str, StringRef)).require_only(1) - CreateAlloca = Method(ptr(AllocaInst), ptr(Type), ptr(Value), - cast(str, StringRef)).require_only(2) + CreateAlloca = Method(ptr(AllocaInst), + ptr(Type), # ty + ptr(Value), # arysize = 0 + cast(str, StringRef), # name = '' + ).require_only(1) CreateLoad = Method(ptr(LoadInst), ptr(Value), cast(str, StringRef)).require_only(1) @@ -208,6 +239,14 @@ class IRBuilder: cast(str, StringRef)).require_only(2) _CreateCall.realname = 'CreateCall' + @CustomPythonMethod + def CreateCall(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return self._CreateCall(*args) + # Skip specialized CreateICmp* and CreateFCmp* CreateICmp = Method(ptr(Value), CmpInst.Predicate, ptr(Value), ptr(Value), @@ -219,13 +258,6 @@ class IRBuilder: CreatePHI = Method(ptr(PHINode), ptr(Type), cast(int, Unsigned), cast(str, StringRef)).require_only(2) - @CustomPythonMethod - def CreateCall(self, *args): - import extra - args = list(args) - valuelist = args[1] - args[1] = extra.make_small_vector_from_values(*valuelist) - return self._CreateCall(*args) CreateSelect = Method(ptr(Value), ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef)).require_only(3) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py index 79cf4a3..ca64072 100644 --- a/newbinding/src/Instruction.py +++ b/newbinding/src/Instruction.py @@ -5,6 +5,7 @@ from ADT.StringRef import StringRef from CallingConv import CallingConv from Attributes import Attributes from Constant import ConstantInt +from Type import Type Instruction = llvm.Class(User) @@ -57,6 +58,17 @@ FPToSIInst = llvm.Class(CastInst) FPToUIInst = llvm.Class(CastInst) FPTruncInst = llvm.Class(CastInst) +AtomicOrdering = llvm.Enum('AtomicOrdering', + 'NotAtomic', 'Unordered', 'Monotonic', 'Acquire', + 'Release', 'AcquireRelease', + 'SequentiallyConsistent') + +SynchronizationScope = llvm.Enum('SynchronizationScope', + 'SingleThread', 'CrossThread') + + + + @Instruction class Instruction: removeFromParent = Method() @@ -129,6 +141,18 @@ class CallInst: setCalledFunction = Method(Void, ptr(Function)) isInlineAsm = Method(cast(Bool, bool)) + CreateMalloc = StaticMethod(ptr(Instruction), + ptr(BasicBlock), # insertAtEnd + ptr(Type), # intptrty + ptr(Type), # allocty + ptr(Value), # allocsz + ptr(Value), # array size = 0 + ptr(Function), # malloc fn = 0 + cast(str, StringRef), # name + ).require_only(4) + + CreateFree = StaticMethod(ptr(Instruction), ptr(Value), ptr(BasicBlock)) + @CmpInst class CmpInst: Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', @@ -201,6 +225,10 @@ class StoreInst: getAlignment = Method(cast(Unsigned, int)) setAlignment = Method(Void, cast(int, Unsigned)) + setAtomic = Method(Void, + AtomicOrdering, + SynchronizationScope).require_only(1) + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @TerminatorInst @@ -298,6 +326,10 @@ class LoadInst: getAlignment = Method(cast(Unsigned, int)) setAlignment = Method(Void, cast(int, Unsigned)) + setAtomic = Method(Void, + AtomicOrdering, + SynchronizationScope).require_only(1) + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @VAArgInst @@ -345,11 +377,3 @@ class FPToUIInst: class FPTruncInst: pass -AtomicOrdering = llvm.Enum('AtomicOrdering', - 'NotAtomic', 'Unordered', 'Monotonic', 'Acquire', - 'Release', 'AcquireRelease', - 'SequentiallyConsistent') - -SynchronizationScope = llvm.Enum('SynchronizationScope', - 'SingleThread', 'CrossThread') - From 7c39bd1f5beb2182a6863ad48bd6d874041a53c1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 16:03:29 -0600 Subject: [PATCH 080/338] Refactor to allow sub-namespace declaration --- newbinding/Makefile | 10 +- newbinding/capsule.py | 2 +- newbinding/gen/binding.py | 225 ++++++++++++++++----- newbinding/gen/codegen.py | 6 + newbinding/gen/gen.py | 135 +++---------- newbinding/include/llvm_binding/binding.h | 12 +- newbinding/src/CallingConv.py | 5 +- newbinding/src/EngineBuilder.py | 7 +- newbinding/src/Intrinsics.py | 17 +- newbinding/src/Support/CodeGen.py | 26 +-- newbinding/src/Support/DynamicLibrary.py | 6 + newbinding/src/Target/TargetLibraryInfo.py | 5 +- newbinding/src/namespace.py | 5 +- 13 files changed, 264 insertions(+), 197 deletions(-) create mode 100644 newbinding/src/Support/DynamicLibrary.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 0e7924f..9de1fb0 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -5,18 +5,18 @@ all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp $(PYTHON) setup.py build_ext --inplace -api.cpp api.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/binding.py +api.cpp api/__init__.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/binding.py $(PYTHON) gen/gen.py api src clean: cleantemp rm -f _api.so _capsule.so + rm -rf api + py_clean cleantemp: - rm -f api.cpp api.py - rm -f src/*.pyc src/Transforms/*.pyc src/ADT/*.pyc src/Assembly/*.pyc src/CodeGen/*.pyc src/ExecutionEngine/*.pyc src/Target/*.pyc src/Transforms/*.pyc + rm -f api.cpp - -check: _api.so api.py +check: _api.so api/__init__.py $(PYTHON) test_binding.py @PHONY: all clean check diff --git a/newbinding/capsule.py b/newbinding/capsule.py index e29948d..d98a23d 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -182,7 +182,7 @@ def downcast(obj, cls): fname = 'downcast_%s_to_%s' % (fromty, toty) fname = fname.replace('::', '_') try: - caster = getattr(_api, fname) + caster = getattr(_api.downcast, fname) except AttributeError: fmt = "Downcast from %s to %s is not supported" raise TypeError(fmt % (fromty, toty)) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index c1e1d1e..601ac6e 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -1,19 +1,157 @@ import inspect, textwrap import functools import codegen as cg +import os _rank = 0 namespaces = {} RESERVED = frozenset(['None']) -class Namespace(object): - def __init__(self, name): - self.name = name +def makedir(directory): + if not os.path.exists(directory): + os.makedirs(directory) + +class SubModule(object): + def __init__(self): + self.methods = [] self.enums = [] self.classes = [] - self.functions = [] + self.namespaces = [] + self.attrs = [] self.includes = set() + + def aggregate_includes(self): + includes = set(self.includes) + for unit in self.iter_all(): + if isinstance(unit, SubModule): + includes |= unit.aggregate_includes() + else: + includes |= unit.includes + return includes + + def aggregate_downcast(self): + dclist = [] + for cls in self.classes: + for bcls in cls.downcastables: + from_to = bcls.fullname, cls.fullname + name = 'downcast_%s_to_%s' % tuple(map(cg.mangle, from_to)) + fn = Function(namespaces[''], name, ptr(cls), ptr(bcls)) + dclist.append((from_to, fn)) + for ns in self.namespaces: + dclist.extend(ns.aggregate_downcast()) + return dclist + + def iter_all(self): + for fn in self.methods: + yield fn + for cls in self.classes: + yield cls + for enum in self.enums: + yield enum + for attr in self.attrs: + yield attr + for ns in self.namespaces: + yield ns + + + def generate_method_table(self, println): + writer = cg.CppCodeWriter(println) + writer.println('static') + writer.println('PyMethodDef meth_%s[] = {' % cg.mangle(self.fullname)) + with writer.indent(): + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for meth in self.methods: + name = meth.name + func = meth.c_name + writer.println(fmt % locals()) + for enumkind in self.enums: + for enum in enumkind.value_names: + name = enum + func = enumkind.c_name(enum) + writer.println(fmt % locals()) + for attr in self.attrs: + # getter + name = attr.getter_name + func = attr.getter_c_name + writer.println(fmt % locals()) + # setter + name = attr.setter_name + func = attr.setter_c_name + writer.println(fmt % locals()) + writer.println('{ NULL },') + writer.println('};') + writer.println() + + def generate_downcasts(self, println): + for ((fromty, toty), fn) in self.downcastlist: + name = fn.name + fmt = ''' +static +%(toty)s* %(name)s(%(fromty)s* arg) +{ + return typecast<%(toty)s>::from(arg); +} + ''' + println(fmt % locals()) + + fn.generate_cpp(println) + + def generate_cpp(self, println, extras=()): + for unit in self.iter_all(): + unit.generate_cpp(println) + self.generate_method_table(println) + self.generate_submodule_table(println, extras=extras) + + def generate_submodule_table(self, println, extras=()): + writer = cg.CppCodeWriter(println) + writer.println('static') + name = cg.mangle(self.fullname) + writer.println('SubModuleEntry submodule_%(name)s[] = {' % locals()) + with writer.indent(): + for cls in self.classes: + name = cls.name + table = cg.mangle(cls.fullname) + writer.println('{ "%(name)s", meth_%(table)s, NULL },' % + locals()) + for ns in self.namespaces: + name = ns.localname + table = cg.mangle(ns.fullname) + fmt = '{ "%(name)s", meth_%(table)s, submodule_%(table)s },' + writer.println(fmt % locals()) + for name, table in extras: + writer.println('{ "%(name)s", %(table)s, NULL },' % locals()) + writer.println('{ NULL }') + writer.println('};') + writer.println('') + + def generate_py(self, rootdir='.', name=''): + name = name or self.localname + if self.namespaces: # should make new directory + path = os.path.join(rootdir, name) + makedir(path) + filepath = os.path.join(path, '__init__.py') + else: + filepath = os.path.join(rootdir, '%s.py' % name) + with open(filepath, 'w') as pyfile: + println = cg.wrap_println_from_file(pyfile) + println('import _api, capsule') + for ns in self.namespaces: + println('from . import %s' % ns.localname) + println() + for unit in self.iter_all(): + if not isinstance(unit, Namespace): + writer = cg.PyCodeWriter(println) + unit.compile_py(writer) + + for ns in self.namespaces: + ns.generate_py(rootdir=path) + + +class Namespace(SubModule): + def __init__(self, name): + SubModule.__init__(self) + self.name = name namespaces[name] = self def Class(self, *bases): @@ -23,12 +161,12 @@ class Namespace(object): def Function(self, *args): fn = Function(self, *args) - self.functions.append(fn) + self.methods.append(fn) return fn def CustomFunction(self, *args): fn = CustomFunction(self, *args) - self.functions.append(fn) + self.methods.append(fn) return fn def Enum(self, name, *value_names): @@ -36,12 +174,23 @@ class Namespace(object): enum.parent = self enum.name = name self.enums.append(enum) + assert name not in vars(self), 'Duplicated' + setattr(self, name, enum) return enum + def Namespace(self, name): + ns = Namespace('::'.join([self.name, name])) + self.namespaces.append(ns) + return ns + @property def fullname(self): return self.name + @property + def localname(self): + return self.name.rsplit('::', 1)[-1] + def __str__(self): return self.name @@ -80,18 +229,15 @@ ConstCharPtr = BuiltinTypes('const char*') PyObjectPtr = BuiltinTypes('PyObject*') PyObjectPtr.format='O' -class Class(_Type): +class Class(SubModule, _Type): format = 'O' def __init__(self, ns, *bases): + SubModule.__init__(self) self.ns = ns self.bases = bases self._is_defined = False - self.methods = [] self.pymethods = [] - self.enums = [] - self.attrs = [] - self.includes = set() self.downcastables = set() def __call__(self, defn): @@ -110,6 +256,7 @@ class Class(_Type): self.enums.append(v) v.name = k v.parent = self + assert k not in vars(self), "Duplicated: %s" % k setattr(self, k, v) elif isinstance(v, Attr): self.attrs.append(v) @@ -133,43 +280,6 @@ class Class(_Type): self.downcastables.add(i) return self - def compile_cpp(self, writer): - # generate methods - for meth in self.methods: - meth.compile_cpp(writer) - for enum in self.enums: - enum.compile_cpp(writer) - for attr in self.attrs: - attr.compile_cpp(writer) - - # generate method table - writer.println('static') - writer.println('PyMethodDef %s[] = {' % cg.mangle(self.fullname)) - with writer.indent(): - fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' - for meth in self.methods: - name = meth.name - func = meth.c_name - writer.println(fmt % locals()) - for enumkind in self.enums: - for enum in enumkind.value_names: - name = enum - func = enumkind.c_name(enum) - writer.println(fmt % locals()) - for attr in self.attrs: - # getter - name = attr.getter_name - func = attr.getter_c_name - writer.println(fmt % locals()) - # setter - name = attr.setter_name - func = attr.setter_c_name - writer.println(fmt % locals()) - - writer.println('{ NULL },') - writer.println('};') - writer.println() - def compile_py(self, writer): clsname = self.name bases = 'capsule.Wrapper' @@ -256,6 +366,9 @@ class Enum(object): def c_name(self, enum): return cg.mangle("%s_%s_%s" % (self.parent, self.name, enum)) + def generate_cpp(self, println): + self.compile_cpp(cg.CppCodeWriter(println)) + def compile_cpp(self, writer): for enum in self.value_names: with writer.py_function(self.c_name(enum)): @@ -322,6 +435,9 @@ class Method(object): def __str__(self): return self.fullname + def generate_cpp(self, println): + self.compile_cpp(cg.CppCodeWriter(println)) + def compile_cpp(self, writer): with writer.py_function(self.c_name): if len(self.signatures) == 1: @@ -454,9 +570,12 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = self.name - ret = writer.call('_api.%s' % func, - varargs=unwrapped) + if '::' in self.parent.name: + ns = self.parent.name.split('::', 1)[-1].replace('::', '.') + func = '.'.join([ns, self.name]) + else: + func = self.name + ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() @@ -630,6 +749,7 @@ class Attr(object): def __init__(self, getter, setter): self.getter = getter self.setter = setter + self.includes = set() @property def fullname(self): @@ -658,6 +778,9 @@ class Attr(object): def setter_c_name(self): return cg.mangle('%s_set' % self.fullname) + def generate_cpp(self, println): + self.compile_cpp(cg.CppCodeWriter(println)) + def compile_cpp(self, writer): # getter with writer.py_function(self.getter_c_name): diff --git a/newbinding/gen/codegen.py b/newbinding/gen/codegen.py index 5a31e38..dd499d6 100644 --- a/newbinding/gen/codegen.py +++ b/newbinding/gen/codegen.py @@ -4,6 +4,12 @@ NULL = 'NULL' _symbols = set() +def wrap_println_from_file(file): + def println(s=''): + file.write(s) + file.write('\n') + return println + def indent(println): def _println(s=''): println("%s%s" % (' '* 4, s)) diff --git a/newbinding/gen/gen.py b/newbinding/gen/gen.py index 89399f3..bb7eab3 100644 --- a/newbinding/gen/gen.py +++ b/newbinding/gen/gen.py @@ -14,7 +14,7 @@ PyInit_%(module)s(void) { PyObject *module = create_python_module("%(module)s", %(methtable)s); if (module) { -if (populate_submodules(module, submodules)) +if (populate_submodules(module, submodule_llvm)) return module; } return NULL; @@ -27,7 +27,7 @@ init%(module)s(void) { PyObject *module = create_python_module("%(module)s", %(methtable)s); if (module) { -populate_submodules(module, submodules); +populate_submodules(module, submodule_llvm); } } #endif @@ -49,65 +49,25 @@ def populate_headers(println): println('#include "%s"' % inc) println() - -def wrap_println_from_file(file): - def println(s=''): - file.write(s) - file.write('\n') - return println - def main(): outputfilename = sys.argv[1] entry_modname = sys.argv[2] sys.path += [os.path.dirname(os.curdir)] entry_module = __import__(entry_modname) - units = [] - for ns in namespaces.values(): - print 'namespace', ns - for fn in ns.functions: - print fn - units.append(fn) - for cls in ns.classes: - print cls - units.append(cls) - for enum in ns.enums: - print enum - units.append(enum) - - # add extra stuffs - downcastlist = [] - ## add downcast - for cls in units: - if isinstance(cls, Class): - for bcls in cls.downcastables: - from_to = bcls.fullname, cls.fullname - name = 'downcast_%s_to_%s' % tuple(map(codegen.mangle, from_to)) - fn = Function(namespaces[''], name, ptr(cls), ptr(bcls)) - downcastlist.append((from_to, fn)) - units.append(fn) - + rootns = namespaces['llvm'] # Generate C++ source with open('%s.cpp' % outputfilename, 'w') as cppfile: - println = wrap_println_from_file(cppfile) - - # extra headers - populate_headers(println) - - # required headers - includes = set() - for ns in namespaces.values(): - includes |= ns.includes - for u in units: - includes |= u.includes - - for inc in includes: + println = codegen.wrap_println_from_file(cppfile) + populate_headers(println) # extra headers + # print all includes + for inc in rootns.aggregate_includes(): println('#include "%s"' % inc) println() - - # generate downcast - for ((fromty, toty), fn) in downcastlist: + # print all downcast + downcast_fns = rootns.aggregate_downcast() + for ((fromty, toty), fn) in downcast_fns: name = fn.name fmt = ''' static @@ -117,65 +77,28 @@ static } ''' println(fmt % locals()) + + fn.generate_cpp(println) - # write methods and method tables - for u in units: - writer = codegen.CppCodeWriter(println) - u.compile_cpp(writer) - else: - del writer - - # write function table - writer = codegen.CppCodeWriter(println) - writer.println('static') - writer.println('PyMethodDef methtable[] = {') - with writer.indent(): - fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' - for u in units: - if isinstance(u, Function): - name = u.name - func = u.c_name - writer.println(fmt % locals()) - for u in units: - if isinstance(u, Enum): - for enum in u.value_names: - name = enum - func = u.c_name(enum) - writer.println(fmt % locals()) - - writer.println('{ NULL },') - writer.println('};') - writer.println() - del writer - - - # write submodule table - writer = codegen.CppCodeWriter(println) - writer.println('static') - writer.println('SubModuleEntry submodules[] = {') - with writer.indent(): - for cls in units: - if isinstance(cls, Class): - name = cls.name - table = codegen.mangle(cls.fullname) - writer.println('{ "%(name)s", %(table)s },' % locals()) - writer.println('{ "extra", extra_methodtable },') - writer.println('{ NULL }') - writer.println('};') - writer.println('') - del writer - - println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) + println('static') + println('PyMethodDef downcast_methodtable[] = {') + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for _, fn in downcast_fns: + name = fn.name + func = fn.c_name + println(fmt % locals()) + println('{ NULL }') + println('};') + println() + # generate submodule + rootns.generate_cpp(println, extras=[('extra', 'extra_methodtable'), + ('downcast', 'downcast_methodtable')]) + println(extension_entry % {'module' : '_api', + 'methtable': 'meth_llvm'}) # Generate Python source - with open('%s.py' % outputfilename, 'w') as pyfile: - println = wrap_println_from_file(pyfile) - println('import _api, capsule') - println() - for u in units: - writer = codegen.PyCodeWriter(println) - u.compile_py(writer) - + rootns.generate_py(rootdir='.', name='api') + if __name__ == '__main__': main() diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h index 58a8ad0..68af615 100644 --- a/newbinding/include/llvm_binding/binding.h +++ b/newbinding/include/llvm_binding/binding.h @@ -63,13 +63,23 @@ create_python_submodule(PyObject* parent, const char* name, struct SubModuleEntry{ const char* name; PyMethodDef* methtable; + SubModuleEntry* submodule; }; static int populate_submodules(PyObject* parent, SubModuleEntry* entries){ for(SubModuleEntry* iter = entries; iter->name; ++iter){ - if (!create_python_submodule(parent, iter->name, iter->methtable)) + PyObject* submodule = create_python_submodule(parent, + iter->name, + iter->methtable); + if (!submodule){ return 0; + } else if (iter->submodule){ + // Recursively populate submodules + if (!populate_submodules(submodule, iter->submodule)) { + return 0; + } + } } return 1; } diff --git a/newbinding/src/CallingConv.py b/newbinding/src/CallingConv.py index 6d0baea..71b4ad3 100644 --- a/newbinding/src/CallingConv.py +++ b/newbinding/src/CallingConv.py @@ -1,9 +1,8 @@ from binding import * from namespace import llvm -@llvm.Class() # actually a namespace -class CallingConv: - ID = Enum(''' +CallingConv = llvm.Namespace('CallingConv') +ID = CallingConv.Enum('ID', ''' C, Fast, Cold, GHC, FirstTargetCC, X86_StdCall, X86_FastCall, ARM_APCS, ARM_AAPCS, ARM_AAPCS_VFP, MSP430_INTR, X86_ThisCall, PTX_Kernel, PTX_Device, MBLAZE_INTR, MBLAZE_SVOL, SPIR_FUNC, diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index 4b68a25..c3feafe 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -10,9 +10,8 @@ from ADT.Triple import Triple EngineBuilder = llvm.Class() -@llvm.Class() # a fake class (actually a namespace) -class EngineKind: - Kind = Enum('JIT', 'Interpreter') +EngineKind = llvm.Namespace('EngineKind') +Kind = EngineKind.Enum('Kind', 'JIT', 'Interpreter') @EngineBuilder class EngineBuilder: @@ -22,7 +21,7 @@ class EngineBuilder: def _setter(*args): return Method(ref(EngineBuilder), *args) - setEngineKind = _setter(EngineKind.Kind) + setEngineKind = _setter(Kind) setJITMemoryManager = _setter(ptr(JITMemoryManager)) setErrorStr = CustomMethod('EngineBuilder_setErrorStr', diff --git a/newbinding/src/Intrinsics.py b/newbinding/src/Intrinsics.py index 0f1bcb4..5314112 100644 --- a/newbinding/src/Intrinsics.py +++ b/newbinding/src/Intrinsics.py @@ -5,13 +5,12 @@ from Module import Module from Function import Function -Intrinsic = llvm.Class() # fake class (actually a namespace) +Intrinsic = llvm.Namespace('Intrinsic') -@Intrinsic -class Intrinsic: - getDeclaration = CustomStaticMethod('Intrinsic_getDeclaration', - PyObjectPtr, # Function* - ptr(Module), - cast(int, Unsigned), # intrinsic id - PyObjectPtr, # list of Type - ).require_only(2) +getDeclaration = Intrinsic.CustomFunction('getDeclaration', + 'Intrinsic_getDeclaration', + PyObjectPtr, # Function* + ptr(Module), + cast(int, Unsigned), # intrinsic id + PyObjectPtr, # list of Type + ).require_only(2) diff --git a/newbinding/src/Support/CodeGen.py b/newbinding/src/Support/CodeGen.py index 013caa1..3bc6f9d 100644 --- a/newbinding/src/Support/CodeGen.py +++ b/newbinding/src/Support/CodeGen.py @@ -1,20 +1,20 @@ from binding import * from ..namespace import llvm -@llvm.Class() -class Reloc: - Model = Enum('Default', 'Static', 'PIC_', 'DynamicNoPIC') -@llvm.Class() -class CodeModel: - Model = Enum('Default', 'JITDefault', 'Small', 'Kernel', 'Medium', 'Large') +Reloc = llvm.Namespace('Reloc') +Reloc.Enum('Model', + 'Default', 'Static', 'PIC_', 'DynamicNoPIC') -@llvm.Class() -class TLSModel: - Model = Enum('GeneralDynamic', 'LocalDynamic', 'InitialExec', 'LocalExec') +CodeModel = llvm.Namespace('CodeModel') +CodeModel.Enum('Model', + 'Default', 'JITDefault', 'Small', 'Kernel', 'Medium', 'Large') -@llvm.Class() -class CodeGenOpt: - 'Actually a namespace' - Level = Enum('None', 'Less', 'Default', 'Aggressive') +TLSModel = llvm.Namespace('TLSModel') +TLSModel.Enum('Model', + 'GeneralDynamic', 'LocalDynamic', 'InitialExec', 'LocalExec') + +CodeGenOpt = llvm.Namespace('CodeGenOpt') +CodeGenOpt.Enum('Level', + 'None', 'Less', 'Default', 'Aggressive') diff --git a/newbinding/src/Support/DynamicLibrary.py b/newbinding/src/Support/DynamicLibrary.py new file mode 100644 index 0000000..7f661d3 --- /dev/null +++ b/newbinding/src/Support/DynamicLibrary.py @@ -0,0 +1,6 @@ +from binding import * +from ..namespace import sys + +DynamicLibrary = sys.Namespace('DynamicLibrary') +#LoadLibraryPermanently + diff --git a/newbinding/src/Target/TargetLibraryInfo.py b/newbinding/src/Target/TargetLibraryInfo.py index b90c619..d98b00b 100644 --- a/newbinding/src/Target/TargetLibraryInfo.py +++ b/newbinding/src/Target/TargetLibraryInfo.py @@ -6,9 +6,8 @@ from ..ADT.StringRef import StringRef TargetLibraryInfo = llvm.Class(ImmutablePass) -@llvm.Class() -class LibFunc: - Func = Enum(''' +LibFunc = llvm.Namespace('LibFunc') +LibFunc.Enum('Func', ''' ZdaPv, ZdlPv, Znaj, ZnajRKSt9nothrow_t, Znam, ZnamRKSt9nothrow_t, Znwj, ZnwjRKSt9nothrow_t, Znwm, ZnwmRKSt9nothrow_t, cxa_atexit, cxa_guard_abort, diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index 3a081af..f833af8 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,4 +1,7 @@ from binding import * -llvm = Namespace('llvm') default = Namespace('') + +llvm = Namespace('llvm') +sys = llvm.Namespace('sys') + From 6eae24bcf3966471dc8404805af5c609a331642c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:10:52 -0600 Subject: [PATCH 081/338] Set default namespace to top-level C++ namespace. --- newbinding/gen/binding.py | 58 +++++++------ newbinding/gen/gen.py | 16 ++-- newbinding/test_binding.py | 170 ++++++++++++++++++------------------- 3 files changed, 124 insertions(+), 120 deletions(-) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 601ac6e..51620a8 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -83,19 +83,19 @@ class SubModule(object): writer.println('};') writer.println() - def generate_downcasts(self, println): - for ((fromty, toty), fn) in self.downcastlist: - name = fn.name - fmt = ''' -static -%(toty)s* %(name)s(%(fromty)s* arg) -{ - return typecast<%(toty)s>::from(arg); -} - ''' - println(fmt % locals()) - - fn.generate_cpp(println) +# def generate_downcasts(self, println): +# for ((fromty, toty), fn) in self.downcastlist: +# name = fn.name +# fmt = ''' +#static +#%(toty)s* %(name)s(%(fromty)s* arg) +#{ +# return typecast< %(toty)s >::from(arg); +#} +# ''' +# println(fmt % locals()) +# +# fn.generate_cpp(println) def generate_cpp(self, println, extras=()): for unit in self.iter_all(): @@ -151,7 +151,7 @@ static class Namespace(SubModule): def __init__(self, name): SubModule.__init__(self) - self.name = name + self.name = name = name.lstrip(':') namespaces[name] = self def Class(self, *bases): @@ -187,6 +187,10 @@ class Namespace(SubModule): def fullname(self): return self.name + @property + def py_name(self): + return self.name.replace('::', '.') + @property def localname(self): return self.name.rsplit('::', 1)[-1] @@ -313,6 +317,11 @@ class Class(SubModule, _Type): name = self.name return '::'.join([self.ns.fullname, name]) + @property + def py_name(self): + ns = self.ns.name.split('::') + return '.'.join(ns + [self.name]) + def __str__(self): return self.fullname @@ -323,7 +332,7 @@ class Class(SubModule, _Type): writer.die_if_false(raw) ptrty = ptr(self).fullname ty = self.fullname - fmt = 'typecast<%(ty)s >::from(%(raw)s)' + fmt = 'typecast< %(ty)s >::from(%(raw)s)' casted = writer.declare(ptrty, fmt % locals()) writer.die_if_false(casted) return casted @@ -385,7 +394,7 @@ class Enum(object): else: k = v fmt = '%(k)s = %(p)s.%(v)s()' - p = '.'.join(['_api'] + self.parent.fullname.split('::')[1:]) + p = '.'.join(['_api'] + self.parent.fullname.split('::')) writer.println(fmt % locals()) writer.println() @@ -415,7 +424,7 @@ class Method(object): @property def fullname(self): - return '::'.join([self.parent.fullname, self.realname]) + return '::'.join([self.parent.fullname, self.realname]).lstrip(':') @property def realname(self): @@ -472,8 +481,7 @@ class Method(object): writer.release_ownership(unwrap_this) unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - - func = '.'.join([self.parent.name, self.name]) + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, args=(unwrap_this,), varargs=unwrapped) @@ -537,7 +545,7 @@ class StaticMethod(Method): unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = '.'.join([self.parent.name, self.name]) + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) @@ -570,11 +578,7 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - if '::' in self.parent.name: - ns = self.parent.name.split('::', 1)[-1].replace('::', '.') - func = '.'.join([ns, self.name]) - else: - func = self.name + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) @@ -603,7 +607,7 @@ class Destructor(Method): writer.return_value(None) def compile_py(self, writer): - func = '.'.join([self.parent.name, self.name]) + func = '.'.join([self.parent.py_name, self.name]) writer.println('_delete_ = _api.%s' % func) @@ -799,7 +803,7 @@ class Attr(object): def compile_py(self, writer): name = self.name - parent = '.'.join(self.parent.fullname.split('::')[1:]) + parent = '.'.join(self.parent.fullname.split('::')) getter = '.'.join([parent, self.getter_name]) setter = '.'.join([parent, self.setter_name]) writer.println('@property') diff --git a/newbinding/gen/gen.py b/newbinding/gen/gen.py index bb7eab3..c5d30de 100644 --- a/newbinding/gen/gen.py +++ b/newbinding/gen/gen.py @@ -12,9 +12,9 @@ extern "C" { PyObject * PyInit_%(module)s(void) { -PyObject *module = create_python_module("%(module)s", %(methtable)s); +PyObject *module = create_python_module("%(module)s", meth_%(ns)s); if (module) { -if (populate_submodules(module, submodule_llvm)) +if (populate_submodules(module, submodule_%(ns)s)) return module; } return NULL; @@ -25,9 +25,9 @@ return NULL; PyMODINIT_FUNC init%(module)s(void) { -PyObject *module = create_python_module("%(module)s", %(methtable)s); +PyObject *module = create_python_module("%(module)s", meth_%(ns)s); if (module) { -populate_submodules(module, submodule_llvm); +populate_submodules(module, submodule_%(ns)s); } } #endif @@ -55,7 +55,7 @@ def main(): sys.path += [os.path.dirname(os.curdir)] entry_module = __import__(entry_modname) - rootns = namespaces['llvm'] + rootns = namespaces[''] # Generate C++ source with open('%s.cpp' % outputfilename, 'w') as cppfile: @@ -73,7 +73,7 @@ def main(): static %(toty)s* %(name)s(%(fromty)s* arg) { - return typecast<%(toty)s>::from(arg); + return typecast< %(toty)s >::from(arg); } ''' println(fmt % locals()) @@ -93,8 +93,8 @@ static # generate submodule rootns.generate_cpp(println, extras=[('extra', 'extra_methodtable'), ('downcast', 'downcast_methodtable')]) - println(extension_entry % {'module' : '_api', - 'methtable': 'meth_llvm'}) + println(extension_entry % {'module' : '_api', + 'ns' : ''}) # Generate Python source rootns.generate_py(rootdir='.', name='api') diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 9003f7d..7fa5e2c 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -1,22 +1,22 @@ -import api +from api import llvm import extra import _capsule from StringIO import StringIO -api.capsule.set_debug(True) +llvm.capsule.set_debug(True) def test_basic_jit_use(): - api.InitializeNativeTarget() - api.InitializeNativeTargetAsmPrinter() - context = api.getGlobalContext() + llvm.InitializeNativeTarget() + llvm.InitializeNativeTargetAsmPrinter() + context = llvm.getGlobalContext() - m = api.Module.new("modname", context) + m = llvm.Module.new("modname", context) print m.getModuleIdentifier() m.setModuleIdentifier('modname2') print m.getModuleIdentifier() print 'endianness', m.getEndianness() - assert m.getEndianness() == api.Module.Endianness.AnyEndianness + assert m.getEndianness() == llvm.Module.Endianness.AnyEndianness print 'pointer-size', m.getPointerSize() - assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize + assert m.getPointerSize() == llvm.Module.PointerSize.AnyPointerSize m.dump() @@ -25,21 +25,21 @@ def test_basic_jit_use(): print os.str() - int1ty = api.Type.getInt1Ty(context) + int1ty = llvm.Type.getInt1Ty(context) int1ty.dump() assert int1ty.isIntegerTy(1) - fnty = api.FunctionType.get(int1ty, False) + fnty = llvm.FunctionType.get(int1ty, False) fnty.dump() - types = [api.Type.getIntNTy(context, 8), api.Type.getIntNTy(context, 32)] - fnty = api.FunctionType.get(api.Type.getIntNTy(context, 8), types, False) + types = [llvm.Type.getIntNTy(context, 8), llvm.Type.getIntNTy(context, 32)] + fnty = llvm.FunctionType.get(llvm.Type.getIntNTy(context, 8), types, False) print fnty const = m.getOrInsertFunction("foo", fnty) - fn = const._downcast(api.Function) + fn = const._downcast(llvm.Function) print fn assert fn.hasName() assert 'foo' == fn.getName() @@ -58,10 +58,10 @@ def test_basic_jit_use(): assert isinstance(fn_uselist, list) assert len(fn_uselist) == 0 - builder = api.IRBuilder.new(context) + builder = llvm.IRBuilder.new(context) print builder - bb = api.BasicBlock.Create(context, "entry", fn, None) + bb = llvm.BasicBlock.Create(context, "entry", fn, None) assert bb.empty() builder.SetInsertPoint(bb) @@ -83,23 +83,23 @@ def test_basic_jit_use(): print m # verifier - action = api.VerifierFailureAction.ReturnStatusAction + action = llvm.VerifierFailureAction.ReturnStatusAction - corrupted = api.verifyFunction(fn, action) + corrupted = llvm.verifyFunction(fn, action) assert not corrupted - corrupted = api.verifyModule(m, action, errio) + corrupted = llvm.verifyModule(m, action, errio) print corrupted assert not corrupted, errio.getvalue() # build pass manager - pmb = api.PassManagerBuilder.new() + pmb = llvm.PassManagerBuilder.new() pmb.OptLevel = 3 assert pmb.OptLevel == 3 - pmb.LibraryInfo = api.TargetLibraryInfo.new() - pmb.Inliner = api.createFunctionInliningPass() + pmb.LibraryInfo = llvm.TargetLibraryInfo.new() + pmb.Inliner = llvm.createFunctionInliningPass() - fpm = api.FunctionPassManager.new(m) - pm = api.PassManager.new() + fpm = llvm.FunctionPassManager.new(m) + pm = llvm.PassManager.new() pmb.populateFunctionPassManager(fpm) pmb.populateModulePassManager(pm) @@ -114,14 +114,14 @@ def test_basic_jit_use(): # build engine - ee = api.ExecutionEngine.createJIT(m, errio) + ee = llvm.ExecutionEngine.createJIT(m, errio) print ee, errio.getvalue() print ee.getDataLayout().getStringRepresentation() datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' - assert datalayout_str == str(api.DataLayout.new(datalayout_str)) - assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) + assert datalayout_str == str(llvm.DataLayout.new(datalayout_str)) + assert datalayout_str == str(llvm.DataLayout.new(str(llvm.DataLayout.new(datalayout_str)))) fn2 = ee.FindFunctionNamed(fn.getName()) assert fn2 is fn @@ -129,8 +129,8 @@ def test_basic_jit_use(): assert ee.getPointerToFunction(fn) assert ee.getPointerToNamedFunction('printf') - gv0 = api.GenericValue.CreateInt(arg0.getType(), 12, False) - gv1 = api.GenericValue.CreateInt(arg1.getType(), -32, True) + gv0 = llvm.GenericValue.CreateInt(arg0.getType(), 12, False) + gv1 = llvm.GenericValue.CreateInt(arg1.getType(), -32, True) assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() @@ -138,7 +138,7 @@ def test_basic_jit_use(): assert gv0.toUnsignedInt() == 12 assert gv1.toSignedInt() == -32 - gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) + gv1 = llvm.GenericValue.CreateInt(arg1.getType(), 32, False) gvR = ee.runFunction(fn, (gv0, gv1)) @@ -146,13 +146,13 @@ def test_basic_jit_use(): # write bitcode bc_buffer = StringIO() - api.WriteBitcodeToFile(m, bc_buffer) + llvm.WriteBitcodeToFile(m, bc_buffer) bc = bc_buffer.getvalue() bc_buffer.close() # read bitcode errbuf = StringIO() - m2 = api.ParseBitCodeFile(bc, context, errbuf) + m2 = llvm.ParseBitCodeFile(bc, context, errbuf) if not m2: raise Exception(errbuf.getvalue()) else: @@ -160,35 +160,35 @@ def test_basic_jit_use(): assert str(m2) == str(m) # parse llvm ir - m3 = api.ParseAssemblyString(str(m), None, api.SMDiagnostic.new(), context) + m3 = llvm.ParseAssemblyString(str(m), None, llvm.SMDiagnostic.new(), context) m3.setModuleIdentifier(m.getModuleIdentifier()) assert str(m3) == str(m) # test clone - m4 = api.CloneModule(m) + m4 = llvm.CloneModule(m) assert m4 is not m assert str(m4) == str(m) def test_engine_builder(): - api.InitializeNativeTarget() - context = api.getGlobalContext() + llvm.InitializeNativeTarget() + context = llvm.getGlobalContext() - m = api.Module.new("modname", context) + m = llvm.Module.new("modname", context) - int32ty = api.Type.getIntNTy(context, 32) - fnty = api.FunctionType.get(int32ty, [int32ty], False) - fn = m.getOrInsertFunction("foo", fnty)._downcast(api.Function) - bb = api.BasicBlock.Create(context, "entry", fn, None) - builder = api.IRBuilder.new(context) + int32ty = llvm.Type.getIntNTy(context, 32) + fnty = llvm.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction("foo", fnty)._downcast(llvm.Function) + bb = llvm.BasicBlock.Create(context, "entry", fn, None) + builder = llvm.IRBuilder.new(context) builder.SetInsertPoint(bb) builder.CreateRet(fn.getArgumentList()[0]) print fn - eb = api.EngineBuilder.new(m) - eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) + eb = llvm.EngineBuilder.new(m) + eb2 = eb.setEngineKind(llvm.EngineKind.Kind.JIT) assert eb is eb2 - eb.setOptLevel(api.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) + eb.setOptLevel(llvm.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) tm = eb.selectTarget() @@ -205,7 +205,7 @@ def test_engine_builder(): ee = eb.create(tm) - triple = api.Triple.new('x86_64-unknown-linux') + triple = llvm.Triple.new('x86_64-unknown-linux') assert triple.getArchName() == 'x86_64' assert triple.getVendorName() == 'unknown' assert triple.getOSName() == 'linux' @@ -216,18 +216,18 @@ def test_engine_builder(): print tm.getDataLayout() - pm = api.PassManager.new() - pm.add(api.DataLayout.new(str(tm.getDataLayout()))) - pm.add(api.TargetLibraryInfo.new()) + pm = llvm.PassManager.new() + pm.add(llvm.DataLayout.new(str(tm.getDataLayout()))) + pm.add(llvm.TargetLibraryInfo.new()) # write assembly - pm = api.PassManager.new() - pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + pm = llvm.PassManager.new() + pm.add(llvm.DataLayout.new(str(tm.getDataLayout()))) raw = extra.make_raw_ostream_for_printing() - formatted = api.formatted_raw_ostream.new(raw, False) + formatted = llvm.formatted_raw_ostream.new(raw, False) - cgft = api.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + cgft = llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) assert not failed @@ -241,17 +241,17 @@ def test_engine_builder(): def test_linker(): - context = api.getGlobalContext() + context = llvm.getGlobalContext() - mA = api.Module.new("modA", context) - mB = api.Module.new("modB", context) + mA = llvm.Module.new("modA", context) + mB = llvm.Module.new("modB", context) def create_function(m, name): - int32ty = api.Type.getIntNTy(context, 32) - fnty = api.FunctionType.get(int32ty, [int32ty], False) - fn = m.getOrInsertFunction(name, fnty)._downcast(api.Function) - bb = api.BasicBlock.Create(context, "entry", fn, None) - builder = api.IRBuilder.new(context) + int32ty = llvm.Type.getIntNTy(context, 32) + fnty = llvm.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction(name, fnty)._downcast(llvm.Function) + bb = llvm.BasicBlock.Create(context, "entry", fn, None) + builder = llvm.IRBuilder.new(context) builder.SetInsertPoint(bb) builder.CreateRet(fn.getArgumentList()[0]) @@ -259,8 +259,8 @@ def test_linker(): create_function(mB, 'bar') errmsg = StringIO() - linkermode = api.Linker.LinkerMode.PreserveSource - failed = api.Linker.LinkModules(mA, mB, linkermode, errmsg) + linkermode = llvm.Linker.LinkerMode.PreserveSource + failed = llvm.Linker.LinkModules(mA, mB, linkermode, errmsg) assert not failed, errmsg.getvalue() assert mA.getFunction('foo') assert mA.getFunction('bar') @@ -269,14 +269,14 @@ def test_linker(): mA.getFunction('bar')]) def test_structtype(): - context = api.getGlobalContext() - m = api.Module.new("modname", context) + context = llvm.getGlobalContext() + m = llvm.Module.new("modname", context) assert m.getTypeByName("truck") is None - truck = api.StructType.create(context, "truck") + truck = llvm.StructType.create(context, "truck") assert 'type opaque' in str(truck) - elemtys = [api.Type.getInt32Ty(context), api.Type.getDoubleTy(context)] + elemtys = [llvm.Type.getInt32Ty(context), llvm.Type.getDoubleTy(context)] truck.setBody(elemtys) assert 'i32' in str(truck) @@ -285,13 +285,13 @@ def test_structtype(): assert m.getTypeByName("truck") is truck def test_globalvariable(): - context = api.getGlobalContext() - m = api.Module.new("modname", context) + context = llvm.getGlobalContext() + m = llvm.Module.new("modname", context) - ty = api.Type.getInt32Ty(context) - LinkageTypes = api.GlobalVariable.LinkageTypes + ty = llvm.Type.getInt32Ty(context) + LinkageTypes = llvm.GlobalVariable.LinkageTypes linkage = LinkageTypes.ExternalLinkage - gvar = api.GlobalVariable.new(m, ty, False, linkage, None, "apple") + gvar = llvm.GlobalVariable.new(m, ty, False, linkage, None, "apple") assert '@apple = external global i32' in str(m) gvar2 = m.getNamedGlobal('apple') @@ -301,30 +301,30 @@ def test_globalvariable(): def test_sequentialtypes(): - context = api.getGlobalContext() - int32ty = api.Type.getInt32Ty(context) - ary_int32x4 = api.ArrayType.get(int32ty, 4) + context = llvm.getGlobalContext() + int32ty = llvm.Type.getInt32Ty(context) + ary_int32x4 = llvm.ArrayType.get(int32ty, 4) assert '[4 x i32]' == str(ary_int32x4) - ptr_int32 = api.PointerType.get(int32ty, 1) + ptr_int32 = llvm.PointerType.get(int32ty, 1) assert 'i32 addrspace(1)*' == str(ptr_int32) - vec_int32x4 = api.VectorType.get(int32ty, 4) + vec_int32x4 = llvm.VectorType.get(int32ty, 4) assert '<4 x i32>' == str(vec_int32x4) def test_constants(): - context = api.getGlobalContext() - int32ty = api.Type.getInt32Ty(context) - ary_int32x4 = api.ArrayType.get(int32ty, 4) - intconst = api.ConstantInt.get(int32ty, 123) - aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4) + context = llvm.getGlobalContext() + int32ty = llvm.Type.getInt32Ty(context) + ary_int32x4 = llvm.ArrayType.get(int32ty, 4) + intconst = llvm.ConstantInt.get(int32ty, 123) + aryconst = llvm.ConstantArray.get(ary_int32x4, [intconst] * 4) assert str(aryconst.getAggregateElement(0)) == str(intconst) def test_intrinsic(): - context = api.getGlobalContext() - m = api.Module.new("modname", context) + context = llvm.getGlobalContext() + m = llvm.Module.new("modname", context) INTR_SIN = 1652 - floatty = api.Type.getFloatTy(context) - fn = api.Intrinsic.getDeclaration(m, INTR_SIN, [floatty]) + floatty = llvm.Type.getFloatTy(context) + fn = llvm.Intrinsic.getDeclaration(m, INTR_SIN, [floatty]) assert 'llvm.sin.f32' in str(fn) fn.eraseFromParent() assert 'llvm.sin.f32' not in str(m) From 355332d6d848ec162ffcdaed9e70d52ef5915efb Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:12:07 -0600 Subject: [PATCH 082/338] Add NVPTX components --- newbinding/setup.py | 22 ++++++++++++++++------ newbinding/src/Support/TargetSelect.py | 21 ++++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/newbinding/setup.py b/newbinding/setup.py index 6e2ceb5..bb23c32 100644 --- a/newbinding/setup.py +++ b/newbinding/setup.py @@ -26,12 +26,22 @@ macros = [('__STDC_CONSTANT_MACROS', None), extra_link_args = ldflags.split() -libs_core, objs_core = get_libs_and_objs(['core', 'analysis', 'scalaropts', - 'executionengine', 'jit', 'native', - 'interpreter', 'bitreader', - 'bitwriter', 'instrumentation', 'ipa', - 'ipo', 'transformutils', 'asmparser', - 'linker', 'support', 'vectorize']) +components = ['core', 'analysis', 'scalaropts', + 'executionengine', 'jit', 'native', + 'interpreter', 'bitreader', + 'bitwriter', 'instrumentation', 'ipa', + 'ipo', 'transformutils', 'asmparser', + 'linker', 'support', 'vectorize', + ] + +nvptx = ['nvptx', + 'nvptxasmprinter', + 'nvptxcodegen', + 'nvptxdesc', + 'nvptxinfo'] + +libs_core, objs_core = get_libs_and_objs(components + nvptx) + ext_modules = [Extension(name='_api', sources=['api.cpp'], diff --git a/newbinding/src/Support/TargetSelect.py b/newbinding/src/Support/TargetSelect.py index 208ef4b..ca97c24 100644 --- a/newbinding/src/Support/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -1,17 +1,28 @@ from binding import * -from ..namespace import llvm +from ..namespace import llvm, default llvm.includes.add('llvm/Support/TargetSelect.h') InitializeNativeTarget = llvm.Function('InitializeNativeTarget') -#llvm.Function('InitializeAllTargets') - InitializeNativeTargetAsmPrinter = llvm.Function( 'InitializeNativeTargetAsmPrinter', cast(Bool, bool)) - InitializeNativeTargetAsmParser = llvm.Function( 'InitializeNativeTargetAsmParser', cast(Bool, bool)) - InitializeNativeTargetDisassembler = llvm.Function( 'InitializeNativeTargetDisassembler', cast(Bool, bool)) + +#InitializeAllTargets = llvm.Function('InitializeAllTargets') +#InitializeAllTargetInfos = llvm.Function('InitializeAllTargetInfos') +#InitializeAllTargetMCs = llvm.Function('InitializeAllTargetMCs') +#InitializeAllAsmPrinters = llvm.Function('InitializeAllAsmPrinters') + +#LLVMInitializePTXTarget = default.Function('LLVMInitializePTXTarget') +#LLVMInitializePTXTargetInfo = default.Function('LLVMInitializePTXTargetInfo') +#LLVMInitializePTXTargetMC = default.Function('LLVMInitializePTXTargetMC') +#LLVMInitializePTXAsmPrinter = default.Function('LLVMInitializePTXAsmPrinter') + +LLVMInitializeNVPTXTarget = default.Function('LLVMInitializeNVPTXTarget') +LLVMInitializeNVPTXTargetInfo = default.Function('LLVMInitializeNVPTXTargetInfo') +LLVMInitializeNVPTXTargetMC = default.Function('LLVMInitializeNVPTXTargetMC') +LLVMInitializeNVPTXAsmPrinter = default.Function('LLVMInitializeNVPTXAsmPrinter') From c66dad7ecede9cf6c5224711dc1485605633320d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:12:36 -0600 Subject: [PATCH 083/338] Implement commandline namespace --- newbinding/src/Support/CommandLine.py | 12 ++++++++++++ newbinding/src/namespace.py | 5 ++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 newbinding/src/Support/CommandLine.py diff --git a/newbinding/src/Support/CommandLine.py b/newbinding/src/Support/CommandLine.py new file mode 100644 index 0000000..2a114f7 --- /dev/null +++ b/newbinding/src/Support/CommandLine.py @@ -0,0 +1,12 @@ +from binding import * +from src.namespace import cl + +cl.includes.add('llvm/Support/CommandLine.h') + +ParseEnvironmentOptions = cl.Function('ParseEnvironmentOptions', + Void, + cast(str, ConstCharPtr), # progName + cast(str, ConstCharPtr), # envvar + cast(str, ConstCharPtr), # overiew = 0 + ).require_only(2) + diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index f833af8..8ad62a3 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,7 +1,6 @@ from binding import * default = Namespace('') - -llvm = Namespace('llvm') +llvm = default.Namespace('llvm') sys = llvm.Namespace('sys') - +cl = llvm.Namespace('cl') From 60336d1c5fe9fc897e1c5899131e663f7a3f1a6d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:12:51 -0600 Subject: [PATCH 084/338] Add DynamicLibrary and InlineFunction --- newbinding/include/llvm_binding/extra.h | 26 ++++++++++++++++++++++ newbinding/src/Support/DynamicLibrary.py | 26 ++++++++++++++++++++-- newbinding/src/Transforms/Utils/Cloning.py | 15 ++++++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 75739de..d045d5c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -747,3 +748,28 @@ PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, return pycapsule_new(inst, "llvm::Value", "llvm:ReturnInst"); } +static +PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, + PyObject* ErrMsg = 0) +{ + using namespace llvm::sys; + bool failed; + if (ErrMsg) { + std::string errmsg; + failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg); + if (failed) { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + } + } else { + failed = DynamicLibrary::LoadLibraryPermanently(Filename); + } + + if (failed) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/newbinding/src/Support/DynamicLibrary.py b/newbinding/src/Support/DynamicLibrary.py index 7f661d3..7dce97a 100644 --- a/newbinding/src/Support/DynamicLibrary.py +++ b/newbinding/src/Support/DynamicLibrary.py @@ -1,6 +1,28 @@ from binding import * from ..namespace import sys +from ..ADT.StringRef import StringRef -DynamicLibrary = sys.Namespace('DynamicLibrary') -#LoadLibraryPermanently +DynamicLibrary = sys.Class() + +@DynamicLibrary +class DynamicLibrary: + _include_ = 'llvm/Support/DynamicLibrary.h' + isValid = Method(cast(Bool, bool)) + getAddressOfSymbol = Method(cast(VoidPtr, int), cast(str, ConstCharPtr)) + + LoadPermanentLibrary = CustomStaticMethod( + 'DynamicLibrary_LoadLibraryPermanently', + PyObjectPtr, # bool --- failed? + cast(str, ConstCharPtr), # filename + PyObjectPtr, # std::string * errmsg = 0 + ).require_only(1) + + SearchForAddressOfSymbol = StaticMethod(cast(VoidPtr, int), # address + cast(str, ConstCharPtr), # symName + ) + + AddSymbol = StaticMethod(Void, + cast(str, StringRef), # symbolName + cast(int, VoidPtr), # address + ) diff --git a/newbinding/src/Transforms/Utils/Cloning.py b/newbinding/src/Transforms/Utils/Cloning.py index c7f7a86..1971177 100644 --- a/newbinding/src/Transforms/Utils/Cloning.py +++ b/newbinding/src/Transforms/Utils/Cloning.py @@ -1,8 +1,21 @@ from binding import * from src.namespace import llvm from src.Module import Module +from src.Instruction import CallInst llvm.includes.add('llvm/Transforms/Utils/Cloning.h') + +@llvm.Class() +class InlineFunctionInfo: + new = Constructor() + delete = Destructor() + + CloneModule = llvm.Function('CloneModule', ptr(Module), ptr(Module)) - +InlineFunction = llvm.Function('InlineFunction', + cast(Bool, bool), # bool --- failed + ptr(CallInst), + ref(InlineFunctionInfo), + cast(bool, Bool), # insert lifetime = true + ).require_only(2) From 8700bbc4f16192f84d77989ecc5ef0ab640d3bdf Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:13:16 -0600 Subject: [PATCH 085/338] Fix segfault on exit --- newbinding/include/llvm_binding/binding.h | 1 + 1 file changed, 1 insertion(+) diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h index 68af615..b5c5b48 100644 --- a/newbinding/include/llvm_binding/binding.h +++ b/newbinding/include/llvm_binding/binding.h @@ -57,6 +57,7 @@ create_python_submodule(PyObject* parent, const char* name, if (-1 == PyModule_AddObject(parent, name, submod)) { return NULL; } + Py_INCREF(submod); // otherwise, it would segfault on exit return submod; } From 1fb6b05715f4eba36583e2210d1a58e555b5a121 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:13:45 -0600 Subject: [PATCH 086/338] Finished wrapper in llvm.core --- .gitignore | 3 + llvm/__init__.py | 11 + llvm/core.py | 2196 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 1980 insertions(+), 230 deletions(-) diff --git a/.gitignore b/.gitignore index 6d0cc2b..6d6296f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ build _build *.pyc +*.so /llvm/_intrinsic_ids.py +llvm_ +newbinding/api/* \ No newline at end of file diff --git a/llvm/__init__.py b/llvm/__init__.py index e69de29..23f3f4d 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -0,0 +1,11 @@ +class Wrapper(object): + def __init__(self, ptr): + self.__ptr = ptr + + @property + def _ptr(self): + return self.__ptr + + +def _extract_ptrs(objs): + return [x._ptr for x in objs] diff --git a/llvm/core.py b/llvm/core.py index 0bf99fd..6d5f0d1 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2,6 +2,9 @@ try: from cStringIO import StringIO except ImportError: from StringIO import StringIO +import contextlib + +import llvm import api @@ -9,248 +12,263 @@ import api # Enumerations #===----------------------------------------------------------------------=== -# type kinds (LLVMTypeKind enum) -TYPE_VOID = 0 -TYPE_HALF = 1 -TYPE_FLOAT = 2 -TYPE_DOUBLE = 3 -TYPE_X86_FP80 = 4 -TYPE_FP128 = 5 -TYPE_PPC_FP128 = 6 -TYPE_LABEL = 7 -TYPE_INTEGER = 8 -TYPE_FUNCTION = 9 -TYPE_STRUCT = 10 -TYPE_ARRAY = 11 -TYPE_POINTER = 12 -TYPE_VECTOR = 13 -TYPE_METADATA = 14 -TYPE_X86_MMX = 15 +# 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 # value IDs (llvm::Value::ValueTy enum) -VALUE_ARGUMENT = 0 -VALUE_BASIC_BLOCK = 1 -VALUE_FUNCTION = 2 -VALUE_GLOBAL_ALIAS = 3 -VALUE_GLOBAL_VARIABLE = 4 -VALUE_UNDEF_VALUE = 5 -VALUE_BLOCK_ADDRESS = 6 -VALUE_CONSTANT_EXPR = 7 -VALUE_CONSTANT_AGGREGATE_ZERO = 8 -VALUE_CONSTANT_DATA_ARRAY = 9 -VALUE_CONSTANT_DATA_VECTOR = 10 -VALUE_CONSTANT_INT = 11 -VALUE_CONSTANT_FP = 12 -VALUE_CONSTANT_ARRAY = 13 -VALUE_CONSTANT_STRUCT = 14 -VALUE_CONSTANT_VECTOR = 15 -VALUE_CONSTANT_POINTER_NULL = 16 -VALUE_MD_NODE = 17 -VALUE_MD_STRING = 18 -VALUE_INLINE_ASM = 19 -VALUE_PSEUDO_SOURCE_VALUE = 20 -VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = 21 -VALUE_INSTRUCTION = 22 +# 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 -# 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 +## 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 +# +## calling conventions +#CC_C = 0 +#CC_FASTCALL = 8 +#CC_COLDCALL = 9 +#CC_GHC = 10 +#CC_X86_STDCALL = 64 +#CC_X86_FASTCALL = 65 +#CC_ARM_APCS = 66 +#CC_ARM_AAPCS = 67 +#CC_ARM_AAPCS_VFP = 68 +#CC_MSP430_INTR = 69 +#CC_X86_THISCALL = 70 +#CC_PTX_KERNEL = 71 +#CC_PTX_DEVICE = 72 +#CC_MBLAZE_INTR = 73 +#CC_MBLAZE_SVOL = 74 +# +# +## int predicates +#ICMP_EQ = 32 +#ICMP_NE = 33 +#ICMP_UGT = 34 +#ICMP_UGE = 35 +#ICMP_ULT = 36 +#ICMP_ULE = 37 +#ICMP_SGT = 38 +#ICMP_SGE = 39 +#ICMP_SLT = 40 +#ICMP_SLE = 41 +# +## same as ICMP_xx, for backward compatibility +#IPRED_EQ = ICMP_EQ +#IPRED_NE = ICMP_NE +#IPRED_UGT = ICMP_UGT +#IPRED_UGE = ICMP_UGE +#IPRED_ULT = ICMP_ULT +#IPRED_ULE = ICMP_ULE +#IPRED_SGT = ICMP_SGT +#IPRED_SGE = ICMP_SGE +#IPRED_SLT = ICMP_SLT +#IPRED_SLE = ICMP_SLE +# +## real predicates +#FCMP_FALSE = 0 +#FCMP_OEQ = 1 +#FCMP_OGT = 2 +#FCMP_OGE = 3 +#FCMP_OLT = 4 +#FCMP_OLE = 5 +#FCMP_ONE = 6 +#FCMP_ORD = 7 +#FCMP_UNO = 8 +#FCMP_UEQ = 9 +#FCMP_UGT = 10 +#FCMP_UGE = 11 +#FCMP_ULT = 12 +#FCMP_ULE = 13 +#FCMP_UNE = 14 +#FCMP_TRUE = 15 +# +## real predicates +#RPRED_FALSE = FCMP_FALSE +#RPRED_OEQ = FCMP_OEQ +#RPRED_OGT = FCMP_OGT +#RPRED_OGE = FCMP_OGE +#RPRED_OLT = FCMP_OLT +#RPRED_OLE = FCMP_OLE +#RPRED_ONE = FCMP_ONE +#RPRED_ORD = FCMP_ORD +#RPRED_UNO = FCMP_UNO +#RPRED_UEQ = FCMP_UEQ +#RPRED_UGT = FCMP_UGT +#RPRED_UGE = FCMP_UGE +#RPRED_ULT = FCMP_ULT +#RPRED_ULE = FCMP_ULE +#RPRED_UNE = FCMP_UNE +#RPRED_TRUE = FCMP_TRUE +# +## linkages (see llvm-c/Core.h) +#LINKAGE_EXTERNAL = 0 +#LINKAGE_AVAILABLE_EXTERNALLY = 1 +#LINKAGE_LINKONCE_ANY = 2 +#LINKAGE_LINKONCE_ODR = 3 +#LINKAGE_WEAK_ANY = 4 +#LINKAGE_WEAK_ODR = 5 +#LINKAGE_APPENDING = 6 +#LINKAGE_INTERNAL = 7 +#LINKAGE_PRIVATE = 8 +#LINKAGE_DLLIMPORT = 9 +#LINKAGE_DLLEXPORT = 10 +#LINKAGE_EXTERNAL_WEAK = 11 +#LINKAGE_GHOST = 12 +#LINKAGE_COMMON = 13 +#LINKAGE_LINKER_PRIVATE = 14 +#LINKAGE_LINKER_PRIVATE_WEAK = 15 +#LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 +# +## visibility (see llvm/GlobalValue.h) +#VISIBILITY_DEFAULT = 0 +#VISIBILITY_HIDDEN = 1 +#VISIBILITY_PROTECTED = 2 -# calling conventions -CC_C = 0 -CC_FASTCALL = 8 -CC_COLDCALL = 9 -CC_GHC = 10 -CC_X86_STDCALL = 64 -CC_X86_FASTCALL = 65 -CC_ARM_APCS = 66 -CC_ARM_AAPCS = 67 -CC_ARM_AAPCS_VFP = 68 -CC_MSP430_INTR = 69 -CC_X86_THISCALL = 70 -CC_PTX_KERNEL = 71 -CC_PTX_DEVICE = 72 -CC_MBLAZE_INTR = 73 -CC_MBLAZE_SVOL = 74 +# 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 -# int predicates -ICMP_EQ = 32 -ICMP_NE = 33 -ICMP_UGT = 34 -ICMP_UGE = 35 -ICMP_ULT = 36 -ICMP_ULE = 37 -ICMP_SGT = 38 -ICMP_SGE = 39 -ICMP_SLT = 40 -ICMP_SLE = 41 +class Module(llvm.Wrapper): + """A Module instance stores all the information related to an LLVM module. -# same as ICMP_xx, for backward compatibility -IPRED_EQ = ICMP_EQ -IPRED_NE = ICMP_NE -IPRED_UGT = ICMP_UGT -IPRED_UGE = ICMP_UGE -IPRED_ULT = ICMP_ULT -IPRED_ULE = ICMP_ULE -IPRED_SGT = ICMP_SGT -IPRED_SGE = ICMP_SGE -IPRED_SLT = ICMP_SLT -IPRED_SLE = ICMP_SLE + Modules are the top level container of all other LLVM Intermediate + Representation (IR) objects. Each module directly contains a list of + globals variables, a list of functions, a list of libraries (or + other modules) this module depends on, a symbol table, and various + data about the target's characteristics. -# real predicates -FCMP_FALSE = 0 -FCMP_OEQ = 1 -FCMP_OGT = 2 -FCMP_OGE = 3 -FCMP_OLT = 4 -FCMP_OLE = 5 -FCMP_ONE = 6 -FCMP_ORD = 7 -FCMP_UNO = 8 -FCMP_UEQ = 9 -FCMP_UGT = 10 -FCMP_UGE = 11 -FCMP_ULT = 12 -FCMP_ULE = 13 -FCMP_UNE = 14 -FCMP_TRUE = 15 + Construct a Module only using the static methods defined below, *NOT* + using the constructor. A correct usage is: -# real predicates -RPRED_FALSE = FCMP_FALSE -RPRED_OEQ = FCMP_OEQ -RPRED_OGT = FCMP_OGT -RPRED_OGE = FCMP_OGE -RPRED_OLT = FCMP_OLT -RPRED_OLE = FCMP_OLE -RPRED_ONE = FCMP_ONE -RPRED_ORD = FCMP_ORD -RPRED_UNO = FCMP_UNO -RPRED_UEQ = FCMP_UEQ -RPRED_UGT = FCMP_UGT -RPRED_UGE = FCMP_UGE -RPRED_ULT = FCMP_ULT -RPRED_ULE = FCMP_ULE -RPRED_UNE = FCMP_UNE -RPRED_TRUE = FCMP_TRUE - -# linkages (see llvm-c/Core.h) -LINKAGE_EXTERNAL = 0 -LINKAGE_AVAILABLE_EXTERNALLY = 1 -LINKAGE_LINKONCE_ANY = 2 -LINKAGE_LINKONCE_ODR = 3 -LINKAGE_WEAK_ANY = 4 -LINKAGE_WEAK_ODR = 5 -LINKAGE_APPENDING = 6 -LINKAGE_INTERNAL = 7 -LINKAGE_PRIVATE = 8 -LINKAGE_DLLIMPORT = 9 -LINKAGE_DLLEXPORT = 10 -LINKAGE_EXTERNAL_WEAK = 11 -LINKAGE_GHOST = 12 -LINKAGE_COMMON = 13 -LINKAGE_LINKER_PRIVATE = 14 -LINKAGE_LINKER_PRIVATE_WEAK = 15 -LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 - -# visibility (see llvm/GlobalValue.h) -VISIBILITY_DEFAULT = 0 -VISIBILITY_HIDDEN = 1 -VISIBILITY_PROTECTED = 2 - -# parameter attributes (see llvm/Attributes.h) -ATTR_NONE = 0 -ATTR_ZEXT = 1 -ATTR_SEXT = 2 -ATTR_NO_RETURN = 4 -ATTR_IN_REG = 8 -ATTR_STRUCT_RET = 16 -ATTR_NO_UNWIND = 32 -ATTR_NO_ALIAS = 64 -ATTR_BY_VAL = 128 -ATTR_NEST = 256 -ATTR_READ_NONE = 512 -ATTR_READONLY = 1024 -ATTR_NO_INLINE = 1<<11 -ATTR_ALWAYS_INLINE = 1<<12 -ATTR_OPTIMIZE_FOR_SIZE = 1<<13 -ATTR_STACK_PROTECT = 1<<14 -ATTR_STACK_PROTECT_REQ = 1<<15 -ATTR_ALIGNMENT = 1<<16 -ATTR_NO_CAPTURE = 1<<21 -ATTR_NO_REDZONE = 1<<22 -ATTR_NO_IMPLICIT_FLOAT = 1<<23 -ATTR_NAKED = 1<<24 -ATTR_INLINE_HINT = 1<<25 -ATTR_STACK_ALIGNMENT = 7<<26 -ATTR_HOTPATCH = 1<<29 - -class Module(object): + module_obj = Module.new('my_module') + """ @staticmethod def new(id): """Create a new Module instance. Creates an instance of Module, having the id `id'. """ - context = api.getGlobalContext() - m = api.Module.new(id, context) + context = api.llvm.getGlobalContext() + m = api.llvm.Module.new(id, context) return Module(m) @staticmethod @@ -266,14 +284,1732 @@ class Module(object): else: bc = fileobj_or_str.read() errbuf = StringIO() - m = api.ParseBitCodeFile(bc, context, errbuf) + m = api.llvm.ParseBitCodeFile(bc, context, errbuf) if not m: raise Exception(errbuf.getvalue()) errbuf.close() return Module(m) - def __init__(self, ptr): - self.ptr = ptr + + @staticmethod + def from_assembly(fileobj_or_str): + """Create a Module instance from the contents of an LLVM + assembly (.ll) file. + + + fileobj_or_str -- takes a file-like object or string that contains + a module represented in llvm-ir assembly. + """ + if isinstance(fileobj_or_str, str): + ir = fileobj_or_str + else: + ir = fileobj_or_str.read() + errbuf = StringIO() + m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDIagnostic.new(), context) + errbuf.close() + return Module(m) + + def __str__(self): + """Text representation of a module. + + Returns the textual representation (`llvm assembly') of the + module. Use it like this: + + ll = str(module_obj) + print module_obj # same as `print ll' + """ + return str(self.ptr) + + def __eq__(self, rhs): + if isinstance(rhs, Module): + return str(self) == str(rhs) + else: + return False + + def __ne__(self, rhs): + return not (self == rhs) + + + def _get_target(self): + return self.ptr.getTargetTriple() + + def _set_target(self, value): + return self.ptr.setTargetTriple(value) + + target = property(_get_target, _set_target, + doc="The target triple string describing the target host.") + + + def _get_data_layout(self): + return self.ptr.getDataLayout() + + def _set_data_layout(self, value): + return self.ptr.setDataLayout(value) + + data_layout = property(_get_data_layout, _set_data_layout, + doc = """The data layout string for the module's target platform. + + The data layout strings is an encoded representation of + the type sizes and alignments expected by this module. + """ + ) + + @property + def pointer_size(self): + return self.getPointerSize() + + def link_in(self, other, preserve=False): + """Link the `other' module into this one. + + The `other' module is linked into this one such that types, + global variables, function, etc. are matched and resolved. + + The `other' module is no longer valid after this method is + invoked, all refs to it should be dropped. + + In the future, this API might be replaced with a full-fledged + Linker class. + """ + assert isinstance(other, Module) + enum_mode = api.llvm.Linker.LinkMode + mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource + + with contextlib.closing(StringIO()) as errmsg: + failed = api.llvm.Linker.LinkModule(self._ptr, + other._ptr, + mode, + errmsg) + if failed: + raise llvm.LLVMException(errmsg) + + def get_type_named(self, name): + typ = self.ptr.getTypeByName(name) + return StructType(typ) + + def add_global_variable(self, ty, name, addrspace=0): + """Add a global variable of given type with given name.""" + external = api.llvm.GlobalVariable.LinkageTypes.ExternalLinkage + notthreadlocal = api.llvm.GlobalVariable.ThreadLocalMode.NotThreadLocal + init = None + insertbefore = None + ptr = api.llvm.GlobalVariable.new(self, + ty._ptr, + False, + external, + init, + name, + insertbefore, + notthreadlocal, + addrspace) + return GlobalVariable(ptr) + + def get_global_variable_named(self, name): + """Return a GlobalVariable object for the given name.""" + ptr = self.ptr.getNamedGlobal(name) + return GlobalVariable(ptr) + + @property + def global_variables(self): + return self.ptr.list_globals() + + def add_function(self, ty, name): + """Add a function of given type with given name.""" + fn = self.get_function_named(name) + if fn is not None: + raise llvm.LLVMException("Duplicated function %s" % name) + return self.get_or_insert_function(ty, name) + + def get_function_named(self, name): + """Return a Function object representing function with given name.""" + fn = self.ptr.getFunction(name) + if fn is None: + return None + return Function(fn) + + def get_or_insert_function(self, ty, name): + """Like get_function_named(), but does add_function() first, if + function is not present.""" + constant = self.ptr.getOrInsertFunction(name, ty._ptr) + fn = constant._downcast(api.llvm.Function) + return Function(fn) + + @property + def functions(self): + """All functions in this module.""" + return map(Function, self.ptr.list_functions()) + + def verify(self): + """Verify module. + + Checks module for errors. Raises `llvm.LLVMException' on any + error.""" + action = api.llvm.VerifierFailureAction.ReturnStatusAction + errio = StringIO() + broken = api.llvm.verifyModule(self.ptr, action, errio) + if broken: + raise llvm.LLVMException(errio.getvalue()) + + def to_bitcode(self, fileobj=None): + """Write bitcode representation of module to given file-like + object. + + fileobj -- A file-like object to where the bitcode is written. + If it is None, the bitcode is returned. + + Return value -- Returns None if fileobj is not None. + Otherwise, return the bitcode as a bytestring. + """ + ret = False + if fileobj is None: + ret = True + fileobj = StringIO + api.llvm.WriteBitcodeToFile(self.ptr, fileobj) + if ret: + return fileobj.getvalue() + + def _get_id(self): + return self.ptr.getModuleIdentifier(self.ptr) + + def _set_id(self, string): + self.ptr.setModuleIdentifier(string) + + id = property(_get_id, _set_id) + + def _to_native_something(self, fileobj, cgft): + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_ObjectFile + failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + if failed: + raise llvm.LLVMException("Failed to write native object file") + if ret: + return fileobj.getvalue() + + + def to_native_object(self, fileobj=None): + '''Outputs the byte string of the module as native object code + + If a fileobj is given, the output is written to it; + Otherwise, the output is returned + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._to_native_something(fileobj, CGFT.CGFT_ObjectFile) + + def to_native_assembly(self, fileobj=None): + '''Outputs the byte string of the module as native assembly code + + If a fileobj is given, the output is written to it; + Otherwise, the output is returned + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._to_native_something(fileobj, CGFT.CGFT_AssemblyFile) + + def get_or_insert_named_metadata(self, name): + return NamedMetadata(self.ptr.getOrInsertNamedMetadata(name)) + + def get_named_metadata(self, name): + return NamedMetadata(self.ptr.get_named_metadata(name)) + + def clone(self): + return NamedMetadata(api.llvm.CloneModule(self.ptr)) + +class Type(llvm.Wrapper): + """Represents a type, like a 32-bit integer or an 80-bit x86 float. + + Use one of the static methods to create an instance. Example: + ty = Type.double() + """ + + @staticmethod + def int(bits=32): + """Create an integer type having the given bit width.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getIntNTy(context, bits) + return Type(ptr) + + @staticmethod + def float(): + """Create a 32-bit floating point type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getFloatTy(context) + return Type(ptr) + + @staticmethod + def double(): + """Create a 64-bit floating point type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getDoubleTy(context) + return Type(ptr) + + @staticmethod + def x86_fp80(): + """Create a 80-bit x86 floating point type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getX86_FP80Ty(context) + return Type(ptr) + + @staticmethod + def fp128(): + """Create a 128-bit floating point type (with 112-bit + mantissa).""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getFP128Ty(context) + return Type(ptr) + + @staticmethod + def ppc_fp128(): + """Create a 128-bit floating point type (two 64-bits).""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getPPC_FP128Ty(context) + return Type(ptr) + + + @staticmethod + def function(return_ty, param_tys, var_arg=False): + """Create a function type. + + Creates a function type that returns a value of type + `return_ty', takes arguments of types as given in the iterable + `param_tys'. Set `var_arg' to True (default is False) for a + variadic function.""" + ptr = api.llvm.FunctionType.get(return_ty._ptr, + llvm._extract_ptrs(param_tys), + var_arg) + return FunctionType(ptr) + + @staticmethod + def opaque(name): + """Create a opaque StructType""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.StructType.create(context, name) + return StructType(ptr) + + @staticmethod + def struct(element_tys, name=''): # not packed + """Create a (unpacked) structure type. + + Creates a structure type with elements of types as given in the + iterable `element_tys'. This method creates a unpacked + structure. For a packed one, use the packed_struct() method. + + If name is not '', creates a identified type; + otherwise, creates a literal type.""" + context = api.llvm.getGlobalContext() + is_packed = False + ptr = api.llvm.StructType.create(context) + ptr.setBody(_extract_ptrs(element_tys), is_packed) + return StructType(ptr) + + @staticmethod + def packed_struct(element_tys, name=''): + """Create a (packed) structure type. + + Creates a structure type with elements of types as given in the + iterable `element_tys'. This method creates a packed + structure. For an unpacked one, use the struct() method. + + If name is not '', creates a identified type; + otherwise, creates a literal type.""" + context = api.llvm.getGlobalContext() + is_packed = True + ptr = api.llvm.StructType.create(context) + ptr.setBody(_extract_ptrs(element_tys), is_packed) + return StructType(ptr) + + @staticmethod + def array(element_ty, count): + """Create an array type. + + Creates a type for an array of elements of type `element_ty', + having 'count' elements.""" + ptr = api.llvm.ArrayType.get(element_ty._ptr, count) + return ArrayType(ptr) + + @staticmethod + def pointer(pointee_ty, addr_space=0): + """Create a pointer type. + + Creates a pointer type, which can point to values of type + `pointee_ty', in the address space `addr_space'.""" + ptr = api.llvm.PointerType.get(pointee_ty._ptr, addr_space) + return PointerType(ptr) + + @staticmethod + def vector(element_ty, count): + """Create a vector type. + + Creates a type for a vector of elements of type `element_ty', + having `count' elements.""" + ptr = api.llvm.VectorType.get(element_ty._ptr, count) + return VectorType(ptr) + + @staticmethod + def void(): + """Create a void type. + + Represents the `void' type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getVoidTy(context) + return Type(ptr) + + @staticmethod + def label(): + """Create a label type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getLabelTy(context) + return Type(ptr) + + def __new__(cls, ptr): + tyid = ptr.getTypeID() + + idmap = { + TYPE_HALF: IntegerType, + TYPE_INTEGER: IntegerType, + TYPE_FUNCTION: FunctionType, + TYPE_STRUCT: StructType, + TYPE_ARRAY: ArrayType, + TYPE_POINTER: PointerType, + TYPE_VECTOR: VectorType, + } + + try: + newcls = idmap[tyid] + except KeyError: + newcls = Type + obj = llvm.Wrapper.__new__(newcls) + return obj + + def __str__(self): + return str(self._ptr) + + def __eq__(self, rhs): + return self._ptr is rhs._ptr + + def __ne__(self, rhs): + return not (self == rhs) + +class IntegerType(Type): + """Represents an integer type.""" + + @property + def width(self): + """The width of the integer type, in bits.""" + return self._ptr.getIntegerBitWidth() + +class FunctionType(Type): + """Represents a function type.""" + + @property + def return_type(self): + """The type of the value returned by this function.""" + return Type(self._ptr.getReturnType()) + + @property + def vararg(self): + """True if this function is variadic.""" + return self._ptr.isVarArg() + + @property + def args(self): + """An iterable that yields Type objects, representing the types of the + arguments accepted by this function, in order.""" + tys = [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] + + @property + def arg_count(self): + """Number of arguments accepted by this function. + + Same as len(obj.args), but faster.""" + return self._ptr.getNumParams() + + + +class StructType(Type): + """Represents a structure type.""" + + @property + def element_count(self): + """Number of elements (members) in the structure. + + Same as len(obj.elements), but faster.""" + return self._ptr.getNumElements() + + @property + def elements(self): + """An iterable that yields Type objects, representing the types of the + elements (members) of the structure, in order.""" + return [Type(self._ptr.getElementType(i)) + for i in range(self._ptr.getNumElements())] + + def set_body(self, elems, packed=False): + """Filled the body of a opaque type. + """ + # check + if not self.is_opaque: + raise llvm.LLVMException("Body is already defined.") + + self._ptr.setBody(llvm._extract_ptrs(elems), packed) + + @property + def packed(self): + """True if the structure is packed, False otherwise.""" + return self._ptr.isPacked() + + def _set_name(self, name): + self._ptr.setName(name) + + def _get_name(self): + return self._ptr.getName() + + name = property(_get_name, _set_name) + + @property + def is_literal(self): + return self.isLiteral() + + @property + def is_identified(self): + return not self.is_literal() + + @property + def is_opaque(self): + return self.isOpaque() + +class ArrayType(Type): + """Represents an array type.""" + + @property + def element(self): + return Type(self._ptr.getArrayElementType()) + + @property + def count(self): + return self._ptr.getNumElements() + +class PointerType(Type): + + @property + def pointee(self): + return Type(self._ptr.getPointerElementType()) + + @property + def address_space(self): + return self._ptr.getAddressSpace() + +class VectorType(Type): + + @property + def element(self): + return self._ptr.getVectorElementType() + + @property + def count(self): + return self._ptr.getNumElements() + +class Value(llvm.Wrapper): + + def __str__(self): + return str(self._ptr) + + def __eq__(self, rhs): + if isinstance(rhs, Value): + return str(self) == str(rhs) + else: + return False + + def __ne__(self, rhs): + return not self == rhs + + def _get_name(self): + return self._ptr.getName() + + def _set_name(self, value): + return self._ptr.setName(value) + + name = property(_get_name, _set_name) + + @property + def value_id(self): + return self._ptr.getValueID() + + @property + def type(self): + return Type(self._ptr.getType()) + + @property + def use_count(self): + return self._ptr.getNumUses() + + @property + def uses(self): + return map(User, self._ptr.list_use()) + +class User(Value): + + @property + def operand_count(self): + return self._ptr.getNumOperands() + + @property + def operands(self): + """Yields operands of this instruction.""" + return [Value(self._ptr.getOperand(i)) + for i in range(self.operand_count)] + + def _get_operand(self, i): + return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) + +class Constant(User): + + @staticmethod + def null(ty): + return Value(api.llvm.Constant.getNullValue(ty._ptr)) + + @staticmethod + def all_ones(ty): + return Value(api.llvm.Constant.getAllOnesValue(ty._ptr)) + + @staticmethod + def undef(ty): + return Value(api.llvm.UndefValue.get(ty._ptr)) + + @staticmethod + def int(ty, value): + return Value(api.llvm.ConstantInt.get(ty._ptr, value, False)) + + @staticmethod + def int_signextend(ty, value): + return Value(api.llvm.ConstantInt.get(ty._ptr, value, True)) + + @staticmethod + def real(ty, value): + return Value(api.llvm.ConstantFP.get(ty._ptr, value)) + + @staticmethod + def string(strval): # dont_null_terminate=True + return Value(api.llvm.ConstantDataArray.getString(strval, False)) + + @staticmethod + def stringz(strval): # dont_null_terminate=False + return Value(api.llvm.ConstantDataArray.getString(strval, True)) + + @staticmethod + def array(ty, consts): + return Value(api.llvm.ConstantArray.get(ty._ptr, consts)) + + @staticmethod + def struct(consts): # not packed + return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + False)) + + @staticmethod + def packed_struct(consts): + return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + False)) + + @staticmethod + def vector(consts): + return Value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) + + @staticmethod + def sizeof(ty): + return Value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) + + def neg(self): + return Value(api.llvm.ConstantExpr.getNeg(self._ptr)) + + def not_(self): + return Value(api.llvm.ConstantExpr.getNot(self._ptr)) + + def add(self, rhs): + return Value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) + + def fadd(self, rhs): + return Value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) + + def sub(self, rhs): + return Value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) + + def fsub(self, rhs): + return Value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) + + def mul(self, rhs): + return Value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) + + def fmul(self, rhs): + return Value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) + + def udiv(self, rhs): + return Value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) + + def sdiv(self, rhs): + return Value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) + + def fdiv(self, rhs): + return Value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) + + def urem(self, rhs): + return Value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) + + def srem(self, rhs): + return Value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) + + def frem(self, rhs): + return Value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) + + def and_(self, rhs): + return Value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) + + def or_(self, rhs): + return Value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) + + def xor(self, rhs): + return Value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) + + def icmp(self, int_pred, rhs): + return Value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) + + def fcmp(self, real_pred, rhs): + return Value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) + + def shl(self, rhs): + return Value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) + + def lshr(self, rhs): + return Value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) + + def ashr(self, rhs): + return Value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) + + def gep(self, indices): + indices = llvm._extract_ptrs(indices) + return Value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) + + def trunc(self, ty): + return Value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty)) + + def sext(self, ty): + return Value(api.llvm.ConstantExpr.getSExt(self._ptr, ty)) + + def zext(self, ty): + return Value(api.llvm.ConstantExpr.getZExt(self._ptr, ty)) + + def fptrunc(self, ty): + return Value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty)) + + def fpext(self, ty): + return Value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty)) + + def uitofp(self, ty): + return Value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty)) + + def sitofp(self, ty): + return Value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty)) + + def fptoui(self, ty): + return Value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty)) + + def fptosi(self, ty): + return Value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty)) + + def ptrtoint(self, ty): + return Value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty)) + + def inttoptr(self, ty): + return Value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty)) + + def bitcast(self, ty): + return Value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty)) + + def select(self, true_const, false_const): + return Value(api.llvm.ConstantExpr.getSelect(self._ptr, + true_const._ptr, + false_const._ptr)) + + def extract_element(self, index): # note: self must be a _vector_ constant + return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) + + def insert_element(self, value, index): + return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, + value._ptr, + index._ptr)) + + def shuffle_vector(self, vector_b, mask): + return Value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, + vector_b._ptr, + mask._ptr)) + +class ConstantExpr(Constant): + @property + def opcode(self): + return self._ptr.getOpcode() + + @property + def opcode_name(self): + return self._ptr.getOpcodeName() + +class ConstantAggregateZero(Constant): + pass + + +class ConstantDataArray(Constant): + pass + + +class ConstantDataVector(Constant): + pass + + +class ConstantInt(Constant): + @property + def z_ext_value(self): + '''Obtain the zero extended value for an integer constant value.''' + # Warning: assertion failure when value does not fit in 64 bits + return self._ptr.getZExtValue() + + @property + def s_ext_value(self): + '''Obtain the sign extended value for an integer constant value.''' + # Warning: assertion failure when value does not fit in 64 bits + return self._ptr.getSExtValue() + + +class ConstantFP(Constant): + pass + + +class ConstantArray(Constant): + pass + + +class ConstantStruct(Constant): + pass + + +class ConstantVector(Constant): + pass + + +class ConstantPointerNull(Constant): + pass + + +class UndefValue(Constant): + pass + + +class GlobalValue(Constant): + + def _get_linkage(self): + return self._ptr.getLinkage() + + def _set_linkage(self, value): + self._ptr.setLinkage(value) + + linkage = property(_get_linkage, _set_linkage) + + def _get_section(self): + return self._ptr.getSection() + + def _set_section(self, value): + return self._ptr.setSection(value) + + section = property(_get_section, _set_section) + + def _get_visibility(self): + return self._ptr.getVisibility() + + def _set_visibility(self, value): + return self._ptr.setVisibility(value) + + visibility = property(_get_visibility, _set_visibility) + + def _get_alignment(self): + return self._ptr.getAlignment() + + def _set_alignment(self, value): + return self._ptr.setAlignment(value) + + alignment = property(_get_alignment, _set_alignment) + + @property + def is_declaration(self): + return self._ptr.isDeclaration() + + @property + def module(self): + return Module(self._ptr.getParent()) + + + +class GlobalVariable(GlobalValue): + + @staticmethod + def new(module, ty, name, addrspace=0): + linkage = api.llvm.GlobalValue.LinkageTypes + external_linkage = linkage.ExternalLinkage + tlmode = api.llvm.GlobalVariable.ThreadLocalMode + not_threadlocal = tlmode.NotThreadLocal + gv = api.llvm.GlobalVariablel.new(module._ptr, + ty._ptr, + False, # is constant + external_linkage, + None, # initializer + name, + None, # insert before + not_threadlocal, + addrspace) + return GlobalVariable(gv) + + @staticmethod + def get(module, name): + gv = GlobalVariable(module._ptr.getNamedGlobal(name)) + if not gv: + llvm.LLVMException("no global named `%s`" % name) + return gv + + def delete(self): + self._ptr.eraseFromParent() + + def _get_initializer(self): + if not self._ptr.hasInitializer(): + return None + return Constant(self._ptr.getInitializer()) + + def _set_initializer(self, const): + self._ptr.setInitializer(const._ptr) + + def _del_initializer(self): + self._ptr.setInitializer(None) + + initializer = property(_get_initializer, _set_initializer) + + def _get_is_global_constant(self): + return self._ptr.isConstant() + + def _set_is_global_constant(self, value): + self._ptr.setConstant(value) + + global_constant = property(_get_is_global_constant, + _set_is_global_constant) + + def _get_thread_local(self): + return self._ptr.isThreadLocal() + + def _set_thread_local(self, value): + return self._ptr.setThreadLocal(value) + + thread_local = property(_get_thread_local, _set_thread_local) + +class Argument(Value): + + def add_attribute(self, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + + def remove_attribute(self, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttr(attrs) + + def _set_alignment(self, align): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + + def _get_alignment(self): + return self._ptr.getParamAlignment() + + alignment = property(_get_alignment, + _set_alignment) + +class Function(GlobalValue): + + @staticmethod + def new(module, func_ty, name): + return module.add_function(func_ty, name) + + @staticmethod + def get_or_insert(module, func_ty, name): + return module.get_or_insert_function(func_ty, name) + + @staticmethod + def get(module, name): + return module.get_function_named(name) + + @staticmethod + def intrinsic(module, intrinsic_id, types): + fn = api.llvm.Intrinsic.getDeclaration(module._ptr, + intrinsic_id, + types) + return Function(fn) + + def delete(self): + self._ptr.eraseFromParent() + + @property + def intrinsic_id(self): + self._ptr.getIntrinsicID() + + def _get_cc(self): + return self._ptr.getCallingConv() + + def _set_cc(self, value): + self._ptr.setCallingConv(value) + + calling_convention = property(_get_cc, _set_cc) + + def _get_coll(self): + return self._ptr.getGC() + + def _set_coll(self, value): + return self._ptr.setGC(value) + + collector = property(_get_coll, _set_coll) + + # the nounwind attribute: + def _get_does_not_throw(self): + return self._ptr.doesNotThrow() + + def _set_does_not_throw(self,value): + assert value + self._ptr.setDoesNotThow() + + does_not_throw = property(_get_does_not_throw, _set_does_not_throw) + + @property + def args(self): + return self._ptr.getArgumentList() + + @property + def basic_block_count(self): + return len(self.basic_blocks) + + @property + def entry_basic_block(self): + return self._ptr.getEntryBlock() + + def append_basic_block(self, name): + context = api.llvm.getGlobalContext() + bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) + return BasicBlock(bb) + + @property + def basic_blocks(self): + return self._ptr.getBasicBlockList() + + def viewCFG(self): + return self._ptr.viewCFG() + + def add_attribute(self, attr): + _core.LLVMAddFunctionAttr(self.ptr, attr) + + def remove_attribute(self, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeFnAttr(attrs) + + def viewCFGOnly(self): + return self._ptr.viewCFGOnly() + + def verify(self): + # Although we're just asking LLVM to return the success or + # failure, it appears to print result to stderr and abort. + + # Note: LLVM has a bug in preverifier that will always abort + # the process upon failure. + return api.llvm.verifyFunction() + +#===----------------------------------------------------------------------=== +# InlineAsm +#===----------------------------------------------------------------------=== + +class InlineAsm(Value): + @staticmethod + def get(functype, asm, constrains, side_effect=False, + align_stack=False, dialect=api.llvm.InlineAsm.AsmDialect.AD_ATT): + ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, contrains, side_effect, + align_stack, dialect) + return InlineAsm(ilasm) + +#===----------------------------------------------------------------------=== +# MetaData +#===----------------------------------------------------------------------=== + +class MetaData(Value): + @staticmethod + def get(module, values): + ''' + values -- must be an iterable of Constant or None. None is treated as "null". + ''' + context = api.llvm.getGlobalContext() + ptr = api.llvm.MDNode.get(context, llvm._extract_ptrs(values)) + return MetaData(ptr) + + @staticmethod + def get_named_operands(module, name): + namedmd = module.get_named_metadata(name)._ptr + return [MetaData(namedmd.getOperand(i)) + for i in namedmd.getNumOperands()] + + @staticmethod + def add_named_operand(module, name, operand): + namedmd = module.get_or_insert_named_metadata(name)._ptr + namedmd.addOperand(operand._ptr) + + @property + def operand_count(self): + return self._ptr.getOperand() + + @property + def operands(self): + """Yields operands of this metadata.""" + return [Value(self._ptr.getOperand(i)) for i in self.operand_count] + + +class MetaDataString(Value): + @staticmethod + def get(module, s): + context = api.llvm.getGlobalContext() + ptr = api.llvm.MDString.get(context, s) + return MetaDataString(ptr) + + @property + def string(self): + '''Same as MDString::getString''' + return self._ptr.getString() + + +class NamedMetaData(llvm.Wrapper): + @staticmethod + def get_or_insert(mod, name): + return mod.get_or_insert_named_metadata(name) + + @staticmethod + def get(mod, name): + return mod.get_named_metadata(name) + + def delete(self): + self._ptr.eraseFromParent() + + @property + def name(self): + return self._ptr.getName() + + def __str__(self): + return str(self._ptr) + + def add(self, operand): + self._ptr.addOperand(operand._ptr) + + +#===----------------------------------------------------------------------=== +# Instruction +#===----------------------------------------------------------------------=== + +class Instruction(User): + + @property + def basic_block(self): + return BasicBlock(self._ptr.getParent()) + + @property + def is_terminator(self): + return self._ptr.isTerminator() + + @property + def is_binary_op(self): + return self._ptr.isBinaryOp() + + @property + def is_shift(self): + return self._ptr.isShift() + + @property + def is_cast(self): + return self._ptr.isCast() + + @property + def is_logical_shift(self): + return self._ptr.isLogicalShift() + + @property + def is_arithmetic_shift(self): + return self._ptr.isArithmeticShift() + + @property + def is_associative(self): + return self._ptr.isAssociative() + + @property + def is_commutative(self): + return self._ptr.isCommutative() + + @property + def is_volatile(self): + """True if this is a volatile load or store.""" + if api.llvm.LoadInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.LoadInst).isVolatile() + elif api.llvm.StoreInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.StoreInst).isVolatile() + else: + return False + + def set_volatile(self, flag): + if api.llvm.LoadInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.LoadInst).setVolatile(flag) + elif api.llvm.StoreInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.StoreInst).setVolatile(flag) + else: + return False + + def set_metadata(self, kind, metadata): + self._ptr.setMetadata(kind, metadata._ptr) + + @property + def opcode(self): + return self._ptr.getOpcode() + + @property + def opcode_name(self): + return self._ptr.getOpcodeName() + + def erase_from_parent(self): + return self._ptr.eraseFromParent() + + +class CallOrInvokeInstruction(Instruction): + + def _get_cc(self): + return self._ptr.getCallingConv() + + def _set_cc(self, value): + return self._ptr.setCallingConv(value) + + calling_convention = property(_get_cc, _set_cc) + + def add_parameter_attribute(self, idx, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttribute(idx, attrs) + + def remove_parameter_attribute(self, idx, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttribute(idx, attrs) + + def set_parameter_alignment(self, idx, align): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttribute(idx, attrs) + + def _get_called_function(self): + function = self._ptr.getCalledFunction() + if function: # Return value can be None on indirect call/invoke + return Value(function) + + def _set_called_function(self, function): + self._ptr.setCalledFunction(function) + + called_function = property(_get_called_function, _set_called_function) + + +class PHINode(Instruction): + + @property + def incoming_count(self): + return self._ptr.getNumIncomingValues() + + def add_incoming(self, value, block): + self._ptr.addIncoming(value._ptr, block._ptr) + + def get_incoming_value(self, idx): + return self._ptr.getIncomingValue(idx) + + def get_incoming_block(self, idx): + return self._ptr.getIncomingBlock(idx) + + +class SwitchInstruction(Instruction): + + def add_case(self, const, bblk): + self._ptr.addCase(const._ptr, bblk._ptr) + + +class CompareInstruction(Instruction): + + @property + def predicate(self): + return self._ptr.getPredicate() + + +#===----------------------------------------------------------------------=== +# Basic block +#===----------------------------------------------------------------------=== + +class BasicBlock(Value): + + def insert_before(self, name): + context = api.llvm.getGlobalContext() + ptr = api.llvm.BasicBlock.Create(context, name, self.function._ptr, + self._ptr) + return BasicBlock(ptr) + + def delete(self): + self._ptr.eraseFromParent() + + @property + def function(self): + return Function(self._ptr.getParent()) + + @property + def instructions(self): + return map(Value, self._ptr.getInstList()) + + +#===----------------------------------------------------------------------=== +# Builder +#===----------------------------------------------------------------------=== + +class Builder(llvm.Wrapper): + + @staticmethod + def new(basic_block): + context = api.llvm.getGlobalContext() + ptr = api.llvm.IRBuilder.new(context) + ptr.SetInsertPoint(basic_block._ptr) + return BasicBlock(ptr) + + def position_at_beginning(self, bblk): + """Position the builder at the beginning of the given block. + + Next instruction inserted will be first one in the block.""" + + # Instruction list won't be long anyway, + # Does not matter much to build a list of all instructions + instrs = bblk._ptr.getInstList() + if instrs: + self.position_before(instrs[0]) + else: + self.position_at_end(bblk) + + def position_at_end(self, bblk): + """Position the builder at the end of the given block. + + Next instruction inserted will be last one in the block.""" + self._ptr.SetInsertPoint(bblk._ptr) + + def position_before(self, instr): + """Position the builder before the given instruction. + + The instruction can belong to a basic block other than the + current one.""" + self._ptr.SetInsertPoint(instr._ptr) + + @property + def basic_block(self): + """The basic block where the builder is positioned.""" + return BasicBlock(self._ptr.GetInsertBlock()) + + # terminator instructions + + def ret_void(self): + return Value(self._ptr.CreateRetVoid()) + + def ret(self, value): + return Value(self._ptr.CreateRet(value._ptr)) + + def ret_many(self, values): + values = llvm._extract_ptrs(values) + return Value(self._ptr.CreateAggregateRet(values, len(values))) + + def branch(self, bblk): + if __debug__: + for instr in self.basic_block.instructions: + assert not instr.is_terminator, "BasicBlock can only have one terminator" + return Value(self._ptr.CreateBr(bblk._ptr)) + + def cbranch(self, if_value, then_blk, else_blk): + return Value(self._ptr.CreateCondBr(if_value._ptr, + then_blk._ptr, + else_blk._ptr)) + + def switch(self, value, else_blk, n=10): + return Value(self._ptr.CreateSwitch(self.value._ptr, + self.else_blk._ptr, + n)) + + def invoke(self, func, args, then_blk, catch_blk, name=""): + return Value(self._ptr.CreateInvoke(self.func._ptr, + self.then_blk._ptr, + self.catch_blk._ptr, + args)) + + def unreachable(self): + return Value(self._ptr.CreateUnreachable()) + + # arithmethic, bitwise and logical + + def add(self, lhs, rhs, name=""): + return Value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) + + def fadd(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) + + def sub(self, lhs, rhs, name=""): + return Value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) + + def fsub(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) + + def mul(self, lhs, rhs, name=""): + return Value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) + + def fmul(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) + + def udiv(self, lhs, rhs, name=""): + return Value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) + + def sdiv(self, lhs, rhs, name=""): + return Value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) + + def fdiv(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) + + def urem(self, lhs, rhs, name=""): + return Value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) + + def srem(self, lhs, rhs, name=""): + return Value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) + + def frem(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) + + def shl(self, lhs, rhs, name=""): + return Value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) + + def lshr(self, lhs, rhs, name=""): + return Value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) + + def ashr(self, lhs, rhs, name=""): + return Value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) + + def and_(self, lhs, rhs, name=""): + return Value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) + + def or_(self, lhs, rhs, name=""): + return Value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) + + def xor(self, lhs, rhs, name=""): + return Value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) + + def neg(self, val, name=""): + return Value(self._ptr.CreateNeg(val._ptr, name)) + + def not_(self, val, name=""): + return Value(self._ptr.CreateNot(val._ptr, name)) + + # memory + + def malloc(self, ty, name=""): + context = api.llvm.getGlobalContext() + intty = api.llvm.Type.getInt32Ty(context) + sizeof = api.llvm.ConstantExpr.getSizeOf(ty) + zero = api.llvm.ConstantInt.get(intty, 0) + # XXX: how do I know when to insert? + # assume to end of block for now + inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + intty, + ty._ptr, + sizeof, + zero, + None, + name) + return Value(inst) + + def malloc_array(self, ty, size, name=""): + sizeof = api.llvm.ConstantExpr.getSizeOf(ty) + # XXX: how do I know when to insert? + # assume to end of block for now + inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + size.type._ptr, + ty._ptr, + sizeof, + size._ptr, + None, + name) + return Value(inst) + + def alloca(self, ty, name=""): + zero = api.llvm.ConstantInt.get(intty, 0) + return Value(self._ptr.CreateAlloca(ty._ptr, zero, name)) + + def alloca_array(self, ty, size, name=""): + return Value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) + + def free(self, ptr): + return Value(api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr)) + + def load(self, ptr, name="", align=0, volatile=False, invariant=False): + inst = Value(self._ptr.CreateLoad(ptr._ptr, name)) + if align: + inst._ptr.setAlignment(align) + if volatile: + inst.set_volatile(volatile) + if invariant: + mod = self.basic_block.function.module + md = MetaData.get(mod, []) # empty metadata node + inst.set_metadata('invariant.load', md) + return inst + + def store(self, value, ptr, align=0, volatile=False): + inst = Value(self._ptr.CreateStore(value._ptr, ptr._ptr)) + if align: + inst._ptr.setAlignment(align) + if volatile: + inst.set_volatile(volatile) + return inst + + def gep(self, ptr, indices, name="", inbounds=False): + if inbounds: + ret = self._ptr.CreateInBoundsGEP(ptr._ptr, + llvm._extract_ptrs(indices), + name) + else: + ret = self._ptr.CreateGEP(ptr._ptr, + llvm._extract_ptrs(indices), + name) + return Value(ret) + + # casts and extensions + + def trunc(self, value, dest_ty, name=""): + return Value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) + + def zext(self, value, dest_ty, name=""): + return Value(self._ptr.CreateZext(value._ptr, dest_ty._ptr, name)) + + def sext(self, value, dest_ty, name=""): + return Value(self._ptr.CreateSext(value._ptr, dest_ty._ptr, name)) + + def fptoui(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) + + def fptosi(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) + + def uitofp(self, value, dest_ty, name=""): + return Value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) + + def sitofp(self, value, dest_ty, name=""): + return Value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) + + def fptrunc(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) + + def fpext(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) + + def ptrtoint(self, value, dest_ty, name=""): + return Value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) + + def inttoptr(self, value, dest_ty, name=""): + return Value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) + + def bitcast(self, value, dest_ty, name=""): + return Value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) + + # comparisons + + def icmp(self, ipred, lhs, rhs, name=""): + return Value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) + + def fcmp(self, rpred, lhs, rhs, name=""): + return Value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) + + # misc + + def extract_value(self, retval, idx, name=""): + return Value(self._ptr.CreateExtractValue(retval._ptr, [idx], name)) + + # obsolete synonym for extract_value + getresult = extract_value + + def insert_value(self, retval, rhs, idx, name=""): + return Value(self._ptr.CreateInsertValue(retval._ptr, + rhs._ptr, + [idx], + name)) + + def phi(self, ty, name=""): + return Value(self._ptr.CreatePHI(ty._ptr, 2, name)) + + def call(self, fn, args, name=""): + err_template = 'Argument type mismatch: expected %s but got %s' + for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): + if t != v.type: + raise TypeError(err_template % (t, v.type)) + arg_ptrs = llvm._extract_ptrs(args) + return Value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) + + def select(self, cond, then_value, else_value, name=""): + return Value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, + else_value._ptr, name)) + + def vaarg(self, list_val, ty, name=""): + return Value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) + + def extract_element(self, vec_val, idx_val, name=""): + return Value(self._ptr.CreateExtractElement(vec_val._ptr, + idx_val_.ptr, + name)) + + + def insert_element(self, vec_val, elt_val, idx_val, name=""): + return Value(self._ptr.CreateExtractElement(vec_val._ptr, + elt_val._ptr, + idx_val_.ptr, + name)) + + def shuffle_vector(self, vecA, vecB, mask, name=""): + return Value(self._ptr.CreateShuffleVector(vecA._ptr, + vecB._ptr, + mask._ptr, + name)) + # atomics + + def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): + return Value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, + old._ptr, + new._ptr, + ordering, + _sync_scope(crossthread))) + + def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): + op_dict = dict((k.lower(), v) + for k, v in vars(api.llvm.AtomicRMWInst.BinOp)) + op = op_dict[op] + return Value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, + ordering, + _sync_scope(crossthread))) + + def atomic_xchg(self, *args, **kwargs): + return self.atomic_rmw('xchg', *args, **kwargs) + + def atomic_add(self, *args, **kwargs): + return self.atomic_rmw('add', *args, **kwargs) + + def atomic_sub(self, *args, **kwargs): + return self.atomic_rmw('sub', *args, **kwargs) + + def atomic_and(self, *args, **kwargs): + return self.atomic_rmw('and', *args, **kwargs) + + def atomic_nand(self, *args, **kwargs): + return self.atomic_rmw('nand', *args, **kwargs) + + def atomic_or(self, *args, **kwargs): + return self.atomic_rmw('or', *args, **kwargs) + + def atomic_xor(self, *args, **kwargs): + return self.atomic_rmw('xor', *args, **kwargs) + + def atomic_max(self, *args, **kwargs): + return self.atomic_rmw('max', *args, **kwargs) + + def atomic_min(self, *args, **kwargs): + return self.atomic_rmw('min', *args, **kwargs) + + def atomic_umax(self, *args, **kwargs): + return self.atomic_rmw('umax', *args, **kwargs) + + def atomic_umin(self, *args, **kwargs): + return self.atomic_rmw('umin', *args, **kwargs) + + def atomic_load(self, ptr, ordering, align=1, crossthread=True, + volatile=False, name=""): + inst = self._ptr.load(ptr, align=align, volatile=volatile, name=name) + inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + return inst + + def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, + volatile=False): + inst = self._ptr.store(ptr, value, align=align, volatile=volatile, + name=name) + inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + return inst + + + def fence(self, ordering, crossthread=True): + return Value(self._ptr.CreateFence(ordering, + _sync_scope(crossthread))) + +def _sync_scope(crossthread): + if crossthread: + scope = api.llvm.SynchronizationScope.CrossThread + else: + scope = api.llvm.SynchronizationScope.SingleThread + return scope + +def load_library_permanently(filename): + """Load a shared library. + + Load the given shared library (filename argument specifies the full + path of the .so file) using LLVM. Symbols from these are available + from the execution engine thereafter.""" + with contextlib.closing(StringIO()) as errmsg: + failed = _api.llvm.sys.LoadLibraryPermanently(filename, errmsg) + if failed: + raise llvm.LLVMException(errmsg.getvalue()) + +def inline_function(call): + info = _api.llvm.InlineFunctionInfo() + return _api.llvm.InlineFunction(call._ptr, info) + +def parse_environment_options(progname, envname): + _api.llvm.cl.ParseEnvironmentOptions(progname, envname) + +if _api.llvm.InitializeNativeTarget(): + raise llvm.LLVMException("No native target!?") +if _api.llvm.InitializeNativeTargetAsmPrinter(): + # should this be an optional feature? + # 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 + - \ No newline at end of file From 230583f42ddec81bcea0f153c29f8e1930c7f900 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:16:26 -0600 Subject: [PATCH 087/338] Fix bug with empty namespace --- newbinding/gen/binding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 51620a8..cfe4394 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -578,7 +578,7 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = '.'.join([self.parent.py_name, self.name]) + func = '.'.join([self.parent.py_name, self.name]).lstrip('.') ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) From 0681d2f37eb4a67aa2e8b78403241bd2f7a7e03e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:22:53 -0600 Subject: [PATCH 088/338] Fixes various problem in llvm.core --- llvm/core.py | 70 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 6d5f0d1..2f7adb5 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -318,7 +318,7 @@ class Module(llvm.Wrapper): ll = str(module_obj) print module_obj # same as `print ll' """ - return str(self.ptr) + return str(self._ptr) def __eq__(self, rhs): if isinstance(rhs, Module): @@ -331,20 +331,20 @@ class Module(llvm.Wrapper): def _get_target(self): - return self.ptr.getTargetTriple() + return self._ptr.getTargetTriple() def _set_target(self, value): - return self.ptr.setTargetTriple(value) + return self._ptr.setTargetTriple(value) target = property(_get_target, _set_target, doc="The target triple string describing the target host.") def _get_data_layout(self): - return self.ptr.getDataLayout() + return self._ptr.getDataLayout() def _set_data_layout(self, value): - return self.ptr.setDataLayout(value) + return self._ptr.setDataLayout(value) data_layout = property(_get_data_layout, _set_data_layout, doc = """The data layout string for the module's target platform. @@ -383,7 +383,7 @@ class Module(llvm.Wrapper): raise llvm.LLVMException(errmsg) def get_type_named(self, name): - typ = self.ptr.getTypeByName(name) + typ = self._ptr.getTypeByName(name) return StructType(typ) def add_global_variable(self, ty, name, addrspace=0): @@ -405,12 +405,12 @@ class Module(llvm.Wrapper): def get_global_variable_named(self, name): """Return a GlobalVariable object for the given name.""" - ptr = self.ptr.getNamedGlobal(name) + ptr = self._ptr.getNamedGlobal(name) return GlobalVariable(ptr) @property def global_variables(self): - return self.ptr.list_globals() + return self._ptr.list_globals() def add_function(self, ty, name): """Add a function of given type with given name.""" @@ -421,7 +421,7 @@ class Module(llvm.Wrapper): def get_function_named(self, name): """Return a Function object representing function with given name.""" - fn = self.ptr.getFunction(name) + fn = self._ptr.getFunction(name) if fn is None: return None return Function(fn) @@ -429,14 +429,14 @@ class Module(llvm.Wrapper): def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" - constant = self.ptr.getOrInsertFunction(name, ty._ptr) + constant = self._ptr.getOrInsertFunction(name, ty._ptr) fn = constant._downcast(api.llvm.Function) return Function(fn) @property def functions(self): """All functions in this module.""" - return map(Function, self.ptr.list_functions()) + return map(Function, self._ptr.list_functions()) def verify(self): """Verify module. @@ -445,7 +445,7 @@ class Module(llvm.Wrapper): error.""" action = api.llvm.VerifierFailureAction.ReturnStatusAction errio = StringIO() - broken = api.llvm.verifyModule(self.ptr, action, errio) + broken = api.llvm.verifyModule(self._ptr, action, errio) if broken: raise llvm.LLVMException(errio.getvalue()) @@ -463,15 +463,15 @@ class Module(llvm.Wrapper): if fileobj is None: ret = True fileobj = StringIO - api.llvm.WriteBitcodeToFile(self.ptr, fileobj) + api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() def _get_id(self): - return self.ptr.getModuleIdentifier(self.ptr) + return self._ptr.getModuleIdentifier(self._ptr) def _set_id(self, string): - self.ptr.setModuleIdentifier(string) + self._ptr.setModuleIdentifier(string) id = property(_get_id, _set_id) @@ -508,13 +508,13 @@ class Module(llvm.Wrapper): return self._to_native_something(fileobj, CGFT.CGFT_AssemblyFile) def get_or_insert_named_metadata(self, name): - return NamedMetadata(self.ptr.getOrInsertNamedMetadata(name)) + return NamedMetadata(self._ptr.getOrInsertNamedMetadata(name)) def get_named_metadata(self, name): - return NamedMetadata(self.ptr.get_named_metadata(name)) + return NamedMetadata(self._ptr.get_named_metadata(name)) def clone(self): - return NamedMetadata(api.llvm.CloneModule(self.ptr)) + return NamedMetadata(api.llvm.CloneModule(self._ptr)) class Type(llvm.Wrapper): """Represents a type, like a 32-bit integer or an 80-bit x86 float. @@ -860,7 +860,7 @@ class User(Value): for i in range(self.operand_count)] def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) + return _make_value(_core.LLVMUserGetOperand(self._ptr, i)) class Constant(User): @@ -1309,7 +1309,7 @@ class Function(GlobalValue): return self._ptr.viewCFG() def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self.ptr, attr) + _core.LLVMAddFunctionAttr(self._ptr, attr) def remove_attribute(self, attr): attrbldr = api.llvm.AttrBuilder() @@ -1589,7 +1589,7 @@ class Builder(llvm.Wrapper): context = api.llvm.getGlobalContext() ptr = api.llvm.IRBuilder.new(context) ptr.SetInsertPoint(basic_block._ptr) - return BasicBlock(ptr) + return Builder(ptr) def position_at_beginning(self, bblk): """Position the builder at the beginning of the given block. @@ -1970,20 +1970,20 @@ def load_library_permanently(filename): path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" with contextlib.closing(StringIO()) as errmsg: - failed = _api.llvm.sys.LoadLibraryPermanently(filename, errmsg) + failed = api.llvm.sys.LoadLibraryPermanently(filename, errmsg) if failed: raise llvm.LLVMException(errmsg.getvalue()) def inline_function(call): - info = _api.llvm.InlineFunctionInfo() - return _api.llvm.InlineFunction(call._ptr, info) + info = api.llvm.InlineFunctionInfo() + return api.llvm.InlineFunction(call._ptr, info) def parse_environment_options(progname, envname): - _api.llvm.cl.ParseEnvironmentOptions(progname, envname) + api.llvm.cl.ParseEnvironmentOptions(progname, envname) -if _api.llvm.InitializeNativeTarget(): +if api.llvm.InitializeNativeTarget(): raise llvm.LLVMException("No native target!?") -if _api.llvm.InitializeNativeTargetAsmPrinter(): +if api.llvm.InitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") @@ -1996,17 +1996,17 @@ HAS_PTX = HAS_NVPTX = False if True: # use PTX? try: - _api.LLVMInitializePTXTarget() - _api.LLVMInitializePTXTargetInfo() - _api.LLVMInitializePTXTargetMC() - _api.LLVMInitializePTXAsmPrinter() + api.LLVMInitializePTXTarget() + api.LLVMInitializePTXTargetInfo() + api.LLVMInitializePTXTargetMC() + api.LLVMInitializePTXAsmPrinter() HAS_PTX = True except AttributeError: try: - _api.LLVMInitializeNVPTXTarget() - _api.LLVMInitializeNVPTXTargetInfo() - _api.LLVMInitializeNVPTXTargetMC() - _api.LLVMInitializeNVPTXAsmPrinter() + api.LLVMInitializeNVPTXTarget() + api.LLVMInitializeNVPTXTargetInfo() + api.LLVMInitializeNVPTXTargetMC() + api.LLVMInitializeNVPTXAsmPrinter() HAS_NVPTX = True except AttributeError: pass From 3189be4d58a24d6a16bb02d38a89472806a89eaa Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 09:59:15 -0600 Subject: [PATCH 089/338] Rename newbinding directory to llvmpy. --- {newbinding => llvmpy}/Makefile | 0 {newbinding => llvmpy}/README | 0 llvmpy/__init__.py | 0 {newbinding => llvmpy}/capsule.cpp | 0 {newbinding => llvmpy}/capsule.py | 0 {newbinding => llvmpy}/extra.py | 4 ++-- {newbinding => llvmpy}/gen/binding.py | 2 +- {newbinding => llvmpy}/gen/codegen.py | 0 {newbinding => llvmpy}/gen/gen.py | 0 .../include/llvm_binding/auto_pyobject.h | 0 .../include/llvm_binding/binding.h | 0 .../include/llvm_binding/capsule_context.h | 0 .../include/llvm_binding/conversion.h | 0 {newbinding => llvmpy}/include/llvm_binding/extra.h | 1 + {newbinding => llvmpy}/setup.py | 0 {newbinding => llvmpy}/src/ADT/SmallVector.py | 0 {newbinding => llvmpy}/src/ADT/StringRef.py | 0 {newbinding => llvmpy}/src/ADT/Triple.py | 0 {newbinding => llvmpy}/src/ADT/__init__.py | 0 {newbinding => llvmpy}/src/Analysis/Verifier.py | 0 {newbinding => llvmpy}/src/Analysis/__init__.py | 0 {newbinding => llvmpy}/src/Argument.py | 0 .../src/Assembly/AssemblyAnnotationWriter.py | 0 {newbinding => llvmpy}/src/Assembly/Parser.py | 0 {newbinding => llvmpy}/src/Assembly/__init__.py | 0 {newbinding => llvmpy}/src/Attributes.py | 0 {newbinding => llvmpy}/src/BasicBlock.py | 0 {newbinding => llvmpy}/src/Bitcode/ReaderWriter.py | 0 {newbinding => llvmpy}/src/Bitcode/__init__.py | 0 {newbinding => llvmpy}/src/CallingConv.py | 0 .../src/CodeGen/MachineCodeInfo.py | 0 {newbinding => llvmpy}/src/CodeGen/__init__.py | 0 {newbinding => llvmpy}/src/Constant.py | 6 +++--- {newbinding => llvmpy}/src/DataLayout.py | 2 +- {newbinding => llvmpy}/src/DerivedTypes.py | 2 +- {newbinding => llvmpy}/src/EngineBuilder.py | 0 .../src/ExecutionEngine/ExecutionEngine.py | 2 +- .../src/ExecutionEngine/__init__.py | 0 {newbinding => llvmpy}/src/Function.py | 0 {newbinding => llvmpy}/src/GenericValue.py | 0 {newbinding => llvmpy}/src/GlobalValue.py | 0 {newbinding => llvmpy}/src/GlobalVariable.py | 0 {newbinding => llvmpy}/src/IRBuilder.py | 12 ++++++------ {newbinding => llvmpy}/src/InlineAsm.py | 0 {newbinding => llvmpy}/src/Instruction.py | 0 {newbinding => llvmpy}/src/Intrinsics.py | 0 {newbinding => llvmpy}/src/JITMemoryManager.py | 0 {newbinding => llvmpy}/src/LLVMContext.py | 0 {newbinding => llvmpy}/src/Linker.py | 0 {newbinding => llvmpy}/src/Metadata.py | 2 +- {newbinding => llvmpy}/src/Module.py | 2 +- {newbinding => llvmpy}/src/Pass.py | 0 {newbinding => llvmpy}/src/PassManager.py | 0 {newbinding => llvmpy}/src/Support/CodeGen.py | 0 {newbinding => llvmpy}/src/Support/CommandLine.py | 0 {newbinding => llvmpy}/src/Support/DynamicLibrary.py | 0 .../src/Support/FormattedStream.py | 0 {newbinding => llvmpy}/src/Support/SourceMgr.py | 0 {newbinding => llvmpy}/src/Support/Target.py | 0 {newbinding => llvmpy}/src/Support/TargetSelect.py | 0 {newbinding => llvmpy}/src/Support/__init__.py | 0 {newbinding => llvmpy}/src/Support/raw_ostream.py | 0 .../src/Target/TargetLibraryInfo.py | 0 {newbinding => llvmpy}/src/Target/TargetMachine.py | 0 {newbinding => llvmpy}/src/Target/__init__.py | 0 {newbinding => llvmpy}/src/TargetTransformInfo.py | 0 {newbinding => llvmpy}/src/Transforms/IPO.py | 0 .../src/Transforms/PassManagerBuilder.py | 0 .../src/Transforms/Utils/Cloning.py | 0 .../src/Transforms/Utils/__init__.py | 0 {newbinding => llvmpy}/src/Transforms/__init__.py | 0 {newbinding => llvmpy}/src/Type.py | 2 +- {newbinding => llvmpy}/src/User.py | 0 {newbinding => llvmpy}/src/Value.py | 2 +- {newbinding => llvmpy}/src/__init__.py | 0 {newbinding => llvmpy}/src/namespace.py | 0 {newbinding => llvmpy}/test_binding.py | 11 +++++++---- 77 files changed, 27 insertions(+), 23 deletions(-) rename {newbinding => llvmpy}/Makefile (100%) rename {newbinding => llvmpy}/README (100%) create mode 100644 llvmpy/__init__.py rename {newbinding => llvmpy}/capsule.cpp (100%) rename {newbinding => llvmpy}/capsule.py (100%) rename {newbinding => llvmpy}/extra.py (89%) rename {newbinding => llvmpy}/gen/binding.py (99%) rename {newbinding => llvmpy}/gen/codegen.py (100%) rename {newbinding => llvmpy}/gen/gen.py (100%) rename {newbinding => llvmpy}/include/llvm_binding/auto_pyobject.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/binding.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/capsule_context.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/conversion.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/extra.h (99%) rename {newbinding => llvmpy}/setup.py (100%) rename {newbinding => llvmpy}/src/ADT/SmallVector.py (100%) rename {newbinding => llvmpy}/src/ADT/StringRef.py (100%) rename {newbinding => llvmpy}/src/ADT/Triple.py (100%) rename {newbinding => llvmpy}/src/ADT/__init__.py (100%) rename {newbinding => llvmpy}/src/Analysis/Verifier.py (100%) rename {newbinding => llvmpy}/src/Analysis/__init__.py (100%) rename {newbinding => llvmpy}/src/Argument.py (100%) rename {newbinding => llvmpy}/src/Assembly/AssemblyAnnotationWriter.py (100%) rename {newbinding => llvmpy}/src/Assembly/Parser.py (100%) rename {newbinding => llvmpy}/src/Assembly/__init__.py (100%) rename {newbinding => llvmpy}/src/Attributes.py (100%) rename {newbinding => llvmpy}/src/BasicBlock.py (100%) rename {newbinding => llvmpy}/src/Bitcode/ReaderWriter.py (100%) rename {newbinding => llvmpy}/src/Bitcode/__init__.py (100%) rename {newbinding => llvmpy}/src/CallingConv.py (100%) rename {newbinding => llvmpy}/src/CodeGen/MachineCodeInfo.py (100%) rename {newbinding => llvmpy}/src/CodeGen/__init__.py (100%) rename {newbinding => llvmpy}/src/Constant.py (98%) rename {newbinding => llvmpy}/src/DataLayout.py (99%) rename {newbinding => llvmpy}/src/DerivedTypes.py (96%) rename {newbinding => llvmpy}/src/EngineBuilder.py (100%) rename {newbinding => llvmpy}/src/ExecutionEngine/ExecutionEngine.py (99%) rename {newbinding => llvmpy}/src/ExecutionEngine/__init__.py (100%) rename {newbinding => llvmpy}/src/Function.py (100%) rename {newbinding => llvmpy}/src/GenericValue.py (100%) rename {newbinding => llvmpy}/src/GlobalValue.py (100%) rename {newbinding => llvmpy}/src/GlobalVariable.py (100%) rename {newbinding => llvmpy}/src/IRBuilder.py (98%) rename {newbinding => llvmpy}/src/InlineAsm.py (100%) rename {newbinding => llvmpy}/src/Instruction.py (100%) rename {newbinding => llvmpy}/src/Intrinsics.py (100%) rename {newbinding => llvmpy}/src/JITMemoryManager.py (100%) rename {newbinding => llvmpy}/src/LLVMContext.py (100%) rename {newbinding => llvmpy}/src/Linker.py (100%) rename {newbinding => llvmpy}/src/Metadata.py (98%) rename {newbinding => llvmpy}/src/Module.py (98%) rename {newbinding => llvmpy}/src/Pass.py (100%) rename {newbinding => llvmpy}/src/PassManager.py (100%) rename {newbinding => llvmpy}/src/Support/CodeGen.py (100%) rename {newbinding => llvmpy}/src/Support/CommandLine.py (100%) rename {newbinding => llvmpy}/src/Support/DynamicLibrary.py (100%) rename {newbinding => llvmpy}/src/Support/FormattedStream.py (100%) rename {newbinding => llvmpy}/src/Support/SourceMgr.py (100%) rename {newbinding => llvmpy}/src/Support/Target.py (100%) rename {newbinding => llvmpy}/src/Support/TargetSelect.py (100%) rename {newbinding => llvmpy}/src/Support/__init__.py (100%) rename {newbinding => llvmpy}/src/Support/raw_ostream.py (100%) rename {newbinding => llvmpy}/src/Target/TargetLibraryInfo.py (100%) rename {newbinding => llvmpy}/src/Target/TargetMachine.py (100%) rename {newbinding => llvmpy}/src/Target/__init__.py (100%) rename {newbinding => llvmpy}/src/TargetTransformInfo.py (100%) rename {newbinding => llvmpy}/src/Transforms/IPO.py (100%) rename {newbinding => llvmpy}/src/Transforms/PassManagerBuilder.py (100%) rename {newbinding => llvmpy}/src/Transforms/Utils/Cloning.py (100%) rename {newbinding => llvmpy}/src/Transforms/Utils/__init__.py (100%) rename {newbinding => llvmpy}/src/Transforms/__init__.py (100%) rename {newbinding => llvmpy}/src/Type.py (99%) rename {newbinding => llvmpy}/src/User.py (100%) rename {newbinding => llvmpy}/src/Value.py (98%) rename {newbinding => llvmpy}/src/__init__.py (100%) rename {newbinding => llvmpy}/src/namespace.py (100%) rename {newbinding => llvmpy}/test_binding.py (98%) diff --git a/newbinding/Makefile b/llvmpy/Makefile similarity index 100% rename from newbinding/Makefile rename to llvmpy/Makefile diff --git a/newbinding/README b/llvmpy/README similarity index 100% rename from newbinding/README rename to llvmpy/README diff --git a/llvmpy/__init__.py b/llvmpy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newbinding/capsule.cpp b/llvmpy/capsule.cpp similarity index 100% rename from newbinding/capsule.cpp rename to llvmpy/capsule.cpp diff --git a/newbinding/capsule.py b/llvmpy/capsule.py similarity index 100% rename from newbinding/capsule.py rename to llvmpy/capsule.py diff --git a/newbinding/extra.py b/llvmpy/extra.py similarity index 89% rename from newbinding/extra.py rename to llvmpy/extra.py index d65f84c..a2e744f 100644 --- a/newbinding/extra.py +++ b/llvmpy/extra.py @@ -2,8 +2,8 @@ Wrapped the extra functions in _api.so ''' -import capsule -import _api +from llvmpy import capsule +from llvmpy import _api # # Re-export the native API from the _api.extra and wrap the functions # diff --git a/newbinding/gen/binding.py b/llvmpy/gen/binding.py similarity index 99% rename from newbinding/gen/binding.py rename to llvmpy/gen/binding.py index cfe4394..6d73cd3 100644 --- a/newbinding/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -135,7 +135,7 @@ class SubModule(object): filepath = os.path.join(rootdir, '%s.py' % name) with open(filepath, 'w') as pyfile: println = cg.wrap_println_from_file(pyfile) - println('import _api, capsule') + println('from llvmpy import _api, capsule') for ns in self.namespaces: println('from . import %s' % ns.localname) println() diff --git a/newbinding/gen/codegen.py b/llvmpy/gen/codegen.py similarity index 100% rename from newbinding/gen/codegen.py rename to llvmpy/gen/codegen.py diff --git a/newbinding/gen/gen.py b/llvmpy/gen/gen.py similarity index 100% rename from newbinding/gen/gen.py rename to llvmpy/gen/gen.py diff --git a/newbinding/include/llvm_binding/auto_pyobject.h b/llvmpy/include/llvm_binding/auto_pyobject.h similarity index 100% rename from newbinding/include/llvm_binding/auto_pyobject.h rename to llvmpy/include/llvm_binding/auto_pyobject.h diff --git a/newbinding/include/llvm_binding/binding.h b/llvmpy/include/llvm_binding/binding.h similarity index 100% rename from newbinding/include/llvm_binding/binding.h rename to llvmpy/include/llvm_binding/binding.h diff --git a/newbinding/include/llvm_binding/capsule_context.h b/llvmpy/include/llvm_binding/capsule_context.h similarity index 100% rename from newbinding/include/llvm_binding/capsule_context.h rename to llvmpy/include/llvm_binding/capsule_context.h diff --git a/newbinding/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h similarity index 100% rename from newbinding/include/llvm_binding/conversion.h rename to llvmpy/include/llvm_binding/conversion.h diff --git a/newbinding/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h similarity index 99% rename from newbinding/include/llvm_binding/extra.h rename to llvmpy/include/llvm_binding/extra.h index d045d5c..438f52c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -358,6 +358,7 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, return NULL; } std::vector vec_args; + Py_ssize_t nargs = PyTuple_Size(Args); vec_args.reserve(nargs); for (Py_ssize_t i = 0; i < nargs; ++i) { diff --git a/newbinding/setup.py b/llvmpy/setup.py similarity index 100% rename from newbinding/setup.py rename to llvmpy/setup.py diff --git a/newbinding/src/ADT/SmallVector.py b/llvmpy/src/ADT/SmallVector.py similarity index 100% rename from newbinding/src/ADT/SmallVector.py rename to llvmpy/src/ADT/SmallVector.py diff --git a/newbinding/src/ADT/StringRef.py b/llvmpy/src/ADT/StringRef.py similarity index 100% rename from newbinding/src/ADT/StringRef.py rename to llvmpy/src/ADT/StringRef.py diff --git a/newbinding/src/ADT/Triple.py b/llvmpy/src/ADT/Triple.py similarity index 100% rename from newbinding/src/ADT/Triple.py rename to llvmpy/src/ADT/Triple.py diff --git a/newbinding/src/ADT/__init__.py b/llvmpy/src/ADT/__init__.py similarity index 100% rename from newbinding/src/ADT/__init__.py rename to llvmpy/src/ADT/__init__.py diff --git a/newbinding/src/Analysis/Verifier.py b/llvmpy/src/Analysis/Verifier.py similarity index 100% rename from newbinding/src/Analysis/Verifier.py rename to llvmpy/src/Analysis/Verifier.py diff --git a/newbinding/src/Analysis/__init__.py b/llvmpy/src/Analysis/__init__.py similarity index 100% rename from newbinding/src/Analysis/__init__.py rename to llvmpy/src/Analysis/__init__.py diff --git a/newbinding/src/Argument.py b/llvmpy/src/Argument.py similarity index 100% rename from newbinding/src/Argument.py rename to llvmpy/src/Argument.py diff --git a/newbinding/src/Assembly/AssemblyAnnotationWriter.py b/llvmpy/src/Assembly/AssemblyAnnotationWriter.py similarity index 100% rename from newbinding/src/Assembly/AssemblyAnnotationWriter.py rename to llvmpy/src/Assembly/AssemblyAnnotationWriter.py diff --git a/newbinding/src/Assembly/Parser.py b/llvmpy/src/Assembly/Parser.py similarity index 100% rename from newbinding/src/Assembly/Parser.py rename to llvmpy/src/Assembly/Parser.py diff --git a/newbinding/src/Assembly/__init__.py b/llvmpy/src/Assembly/__init__.py similarity index 100% rename from newbinding/src/Assembly/__init__.py rename to llvmpy/src/Assembly/__init__.py diff --git a/newbinding/src/Attributes.py b/llvmpy/src/Attributes.py similarity index 100% rename from newbinding/src/Attributes.py rename to llvmpy/src/Attributes.py diff --git a/newbinding/src/BasicBlock.py b/llvmpy/src/BasicBlock.py similarity index 100% rename from newbinding/src/BasicBlock.py rename to llvmpy/src/BasicBlock.py diff --git a/newbinding/src/Bitcode/ReaderWriter.py b/llvmpy/src/Bitcode/ReaderWriter.py similarity index 100% rename from newbinding/src/Bitcode/ReaderWriter.py rename to llvmpy/src/Bitcode/ReaderWriter.py diff --git a/newbinding/src/Bitcode/__init__.py b/llvmpy/src/Bitcode/__init__.py similarity index 100% rename from newbinding/src/Bitcode/__init__.py rename to llvmpy/src/Bitcode/__init__.py diff --git a/newbinding/src/CallingConv.py b/llvmpy/src/CallingConv.py similarity index 100% rename from newbinding/src/CallingConv.py rename to llvmpy/src/CallingConv.py diff --git a/newbinding/src/CodeGen/MachineCodeInfo.py b/llvmpy/src/CodeGen/MachineCodeInfo.py similarity index 100% rename from newbinding/src/CodeGen/MachineCodeInfo.py rename to llvmpy/src/CodeGen/MachineCodeInfo.py diff --git a/newbinding/src/CodeGen/__init__.py b/llvmpy/src/CodeGen/__init__.py similarity index 100% rename from newbinding/src/CodeGen/__init__.py rename to llvmpy/src/CodeGen/__init__.py diff --git a/newbinding/src/Constant.py b/llvmpy/src/Constant.py similarity index 98% rename from newbinding/src/Constant.py rename to llvmpy/src/Constant.py index 42541c4..5407d71 100644 --- a/newbinding/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -227,7 +227,7 @@ class ConstantExpr: @CustomPythonStaticMethod def getGetElementPtr(*args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -242,7 +242,7 @@ class ConstantExpr: @CustomPythonStaticMethod def getExtractValue(*args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_unsigned(*valuelist) @@ -254,7 +254,7 @@ class ConstantExpr: @CustomPythonStaticMethod def getInsertValue(*args): - import extra + from llvmpy import extra args = list(args) valuelist = args[2] args[1] = extra.make_small_vector_from_unsigned(*valuelist) diff --git a/newbinding/src/DataLayout.py b/llvmpy/src/DataLayout.py similarity index 99% rename from newbinding/src/DataLayout.py rename to llvmpy/src/DataLayout.py index 704c4b1..d704723 100644 --- a/newbinding/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -81,7 +81,7 @@ class DataLayout: @CustomPythonMethod def getIndexedOffset(self, *args): - import extra + from llvmpy import extra args = list(args) args[1] = extra.make_small_vector_from_values(args[1]) return self.getIndexedOffset(*args) diff --git a/newbinding/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py similarity index 96% rename from newbinding/src/DerivedTypes.py rename to llvmpy/src/DerivedTypes.py index e71f1a8..a34c2f1 100644 --- a/newbinding/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -17,7 +17,7 @@ class FunctionType: @CustomPythonStaticMethod def get(*args): - import extra + from llvmpy import extra if len(args) == 3: typelist = args[1] sv = extra.make_small_vector_from_types(*typelist) diff --git a/newbinding/src/EngineBuilder.py b/llvmpy/src/EngineBuilder.py similarity index 100% rename from newbinding/src/EngineBuilder.py rename to llvmpy/src/EngineBuilder.py diff --git a/newbinding/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py similarity index 99% rename from newbinding/src/ExecutionEngine/ExecutionEngine.py rename to llvmpy/src/ExecutionEngine/ExecutionEngine.py index f4bdb14..1188de3 100644 --- a/newbinding/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -88,7 +88,7 @@ class ExecutionEngine: @CustomPythonMethod def runFunction(self, fn, args): - import capsule + from llvmpy import capsule unwrapped = map(capsule.unwrap, args) return self._runFunction(fn, tuple(unwrapped)) diff --git a/newbinding/src/ExecutionEngine/__init__.py b/llvmpy/src/ExecutionEngine/__init__.py similarity index 100% rename from newbinding/src/ExecutionEngine/__init__.py rename to llvmpy/src/ExecutionEngine/__init__.py diff --git a/newbinding/src/Function.py b/llvmpy/src/Function.py similarity index 100% rename from newbinding/src/Function.py rename to llvmpy/src/Function.py diff --git a/newbinding/src/GenericValue.py b/llvmpy/src/GenericValue.py similarity index 100% rename from newbinding/src/GenericValue.py rename to llvmpy/src/GenericValue.py diff --git a/newbinding/src/GlobalValue.py b/llvmpy/src/GlobalValue.py similarity index 100% rename from newbinding/src/GlobalValue.py rename to llvmpy/src/GlobalValue.py diff --git a/newbinding/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py similarity index 100% rename from newbinding/src/GlobalVariable.py rename to llvmpy/src/GlobalVariable.py diff --git a/newbinding/src/IRBuilder.py b/llvmpy/src/IRBuilder.py similarity index 98% rename from newbinding/src/IRBuilder.py rename to llvmpy/src/IRBuilder.py index 2965367..095122f 100644 --- a/newbinding/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -68,7 +68,7 @@ class IRBuilder: @CustomPythonMethod def CreateInvoke(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[3] args[3] = extra.make_small_vector_from_values(*valuelist) @@ -181,7 +181,7 @@ class IRBuilder: @CustomPythonMethod def CreateGEP(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -194,7 +194,7 @@ class IRBuilder: @CustomPythonMethod def CreateInBoundsGEP(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -241,7 +241,7 @@ class IRBuilder: @CustomPythonMethod def CreateCall(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -282,7 +282,7 @@ class IRBuilder: @CustomPythonMethod def CreateExtractValue(self, args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_unsigned(*valuelist) @@ -295,7 +295,7 @@ class IRBuilder: @CustomPythonMethod def CreateInsertValue(self, args): - import extra + from llvmpy import extra args = list(args) valuelist = args[2] args[1] = extra.make_small_vector_from_unsigned(*valuelist) diff --git a/newbinding/src/InlineAsm.py b/llvmpy/src/InlineAsm.py similarity index 100% rename from newbinding/src/InlineAsm.py rename to llvmpy/src/InlineAsm.py diff --git a/newbinding/src/Instruction.py b/llvmpy/src/Instruction.py similarity index 100% rename from newbinding/src/Instruction.py rename to llvmpy/src/Instruction.py diff --git a/newbinding/src/Intrinsics.py b/llvmpy/src/Intrinsics.py similarity index 100% rename from newbinding/src/Intrinsics.py rename to llvmpy/src/Intrinsics.py diff --git a/newbinding/src/JITMemoryManager.py b/llvmpy/src/JITMemoryManager.py similarity index 100% rename from newbinding/src/JITMemoryManager.py rename to llvmpy/src/JITMemoryManager.py diff --git a/newbinding/src/LLVMContext.py b/llvmpy/src/LLVMContext.py similarity index 100% rename from newbinding/src/LLVMContext.py rename to llvmpy/src/LLVMContext.py diff --git a/newbinding/src/Linker.py b/llvmpy/src/Linker.py similarity index 100% rename from newbinding/src/Linker.py rename to llvmpy/src/Linker.py diff --git a/newbinding/src/Metadata.py b/llvmpy/src/Metadata.py similarity index 98% rename from newbinding/src/Metadata.py rename to llvmpy/src/Metadata.py index 338cbbd..94088ca 100644 --- a/newbinding/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -46,7 +46,7 @@ class NamedMDNode: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() \ No newline at end of file diff --git a/newbinding/src/Module.py b/llvmpy/src/Module.py similarity index 98% rename from newbinding/src/Module.py rename to llvmpy/src/Module.py index 7718cd6..d68be36 100644 --- a/newbinding/src/Module.py +++ b/llvmpy/src/Module.py @@ -77,7 +77,7 @@ class Module: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() diff --git a/newbinding/src/Pass.py b/llvmpy/src/Pass.py similarity index 100% rename from newbinding/src/Pass.py rename to llvmpy/src/Pass.py diff --git a/newbinding/src/PassManager.py b/llvmpy/src/PassManager.py similarity index 100% rename from newbinding/src/PassManager.py rename to llvmpy/src/PassManager.py diff --git a/newbinding/src/Support/CodeGen.py b/llvmpy/src/Support/CodeGen.py similarity index 100% rename from newbinding/src/Support/CodeGen.py rename to llvmpy/src/Support/CodeGen.py diff --git a/newbinding/src/Support/CommandLine.py b/llvmpy/src/Support/CommandLine.py similarity index 100% rename from newbinding/src/Support/CommandLine.py rename to llvmpy/src/Support/CommandLine.py diff --git a/newbinding/src/Support/DynamicLibrary.py b/llvmpy/src/Support/DynamicLibrary.py similarity index 100% rename from newbinding/src/Support/DynamicLibrary.py rename to llvmpy/src/Support/DynamicLibrary.py diff --git a/newbinding/src/Support/FormattedStream.py b/llvmpy/src/Support/FormattedStream.py similarity index 100% rename from newbinding/src/Support/FormattedStream.py rename to llvmpy/src/Support/FormattedStream.py diff --git a/newbinding/src/Support/SourceMgr.py b/llvmpy/src/Support/SourceMgr.py similarity index 100% rename from newbinding/src/Support/SourceMgr.py rename to llvmpy/src/Support/SourceMgr.py diff --git a/newbinding/src/Support/Target.py b/llvmpy/src/Support/Target.py similarity index 100% rename from newbinding/src/Support/Target.py rename to llvmpy/src/Support/Target.py diff --git a/newbinding/src/Support/TargetSelect.py b/llvmpy/src/Support/TargetSelect.py similarity index 100% rename from newbinding/src/Support/TargetSelect.py rename to llvmpy/src/Support/TargetSelect.py diff --git a/newbinding/src/Support/__init__.py b/llvmpy/src/Support/__init__.py similarity index 100% rename from newbinding/src/Support/__init__.py rename to llvmpy/src/Support/__init__.py diff --git a/newbinding/src/Support/raw_ostream.py b/llvmpy/src/Support/raw_ostream.py similarity index 100% rename from newbinding/src/Support/raw_ostream.py rename to llvmpy/src/Support/raw_ostream.py diff --git a/newbinding/src/Target/TargetLibraryInfo.py b/llvmpy/src/Target/TargetLibraryInfo.py similarity index 100% rename from newbinding/src/Target/TargetLibraryInfo.py rename to llvmpy/src/Target/TargetLibraryInfo.py diff --git a/newbinding/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py similarity index 100% rename from newbinding/src/Target/TargetMachine.py rename to llvmpy/src/Target/TargetMachine.py diff --git a/newbinding/src/Target/__init__.py b/llvmpy/src/Target/__init__.py similarity index 100% rename from newbinding/src/Target/__init__.py rename to llvmpy/src/Target/__init__.py diff --git a/newbinding/src/TargetTransformInfo.py b/llvmpy/src/TargetTransformInfo.py similarity index 100% rename from newbinding/src/TargetTransformInfo.py rename to llvmpy/src/TargetTransformInfo.py diff --git a/newbinding/src/Transforms/IPO.py b/llvmpy/src/Transforms/IPO.py similarity index 100% rename from newbinding/src/Transforms/IPO.py rename to llvmpy/src/Transforms/IPO.py diff --git a/newbinding/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py similarity index 100% rename from newbinding/src/Transforms/PassManagerBuilder.py rename to llvmpy/src/Transforms/PassManagerBuilder.py diff --git a/newbinding/src/Transforms/Utils/Cloning.py b/llvmpy/src/Transforms/Utils/Cloning.py similarity index 100% rename from newbinding/src/Transforms/Utils/Cloning.py rename to llvmpy/src/Transforms/Utils/Cloning.py diff --git a/newbinding/src/Transforms/Utils/__init__.py b/llvmpy/src/Transforms/Utils/__init__.py similarity index 100% rename from newbinding/src/Transforms/Utils/__init__.py rename to llvmpy/src/Transforms/Utils/__init__.py diff --git a/newbinding/src/Transforms/__init__.py b/llvmpy/src/Transforms/__init__.py similarity index 100% rename from newbinding/src/Transforms/__init__.py rename to llvmpy/src/Transforms/__init__.py diff --git a/newbinding/src/Type.py b/llvmpy/src/Type.py similarity index 99% rename from newbinding/src/Type.py rename to llvmpy/src/Type.py index 4078a9d..ec0bf88 100644 --- a/newbinding/src/Type.py +++ b/llvmpy/src/Type.py @@ -125,7 +125,7 @@ class Type: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os) return os.str() diff --git a/newbinding/src/User.py b/llvmpy/src/User.py similarity index 100% rename from newbinding/src/User.py rename to llvmpy/src/User.py diff --git a/newbinding/src/Value.py b/llvmpy/src/Value.py similarity index 98% rename from newbinding/src/Value.py rename to llvmpy/src/Value.py index 27bcda0..88f221c 100644 --- a/newbinding/src/Value.py +++ b/llvmpy/src/Value.py @@ -56,7 +56,7 @@ class Value: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() diff --git a/newbinding/src/__init__.py b/llvmpy/src/__init__.py similarity index 100% rename from newbinding/src/__init__.py rename to llvmpy/src/__init__.py diff --git a/newbinding/src/namespace.py b/llvmpy/src/namespace.py similarity index 100% rename from newbinding/src/namespace.py rename to llvmpy/src/namespace.py diff --git a/newbinding/test_binding.py b/llvmpy/test_binding.py similarity index 98% rename from newbinding/test_binding.py rename to llvmpy/test_binding.py index 7fa5e2c..e1e12e5 100644 --- a/newbinding/test_binding.py +++ b/llvmpy/test_binding.py @@ -1,8 +1,11 @@ -from api import llvm -import extra -import _capsule from StringIO import StringIO -llvm.capsule.set_debug(True) + +from llvmpy.api import llvm +from llvmpy import extra +from llvmpy import _capsule +import llvmpy.capsule +llvmpy.capsule.set_debug(True) + def test_basic_jit_use(): llvm.InitializeNativeTarget() From 2d8c6f0a410469ee0276c120e63414f0b3eb3e7f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 18:13:38 -0600 Subject: [PATCH 090/338] Add PassRegistry, PassSupport, TargetRegistry, TargetOptions, and functions in Host.h And a few other fixes --- llvmpy/.gitignore | 4 + llvmpy/capsule.py | 7 ++ llvmpy/include/llvm_binding/auto_pyobject.h | 3 +- llvmpy/include/llvm_binding/extra.h | 97 +++++++++++++++++++ llvmpy/src/Analysis/Verifier.py | 2 +- llvmpy/src/DataLayout.py | 15 ++- llvmpy/src/ExecutionEngine/ExecutionEngine.py | 15 ++- llvmpy/src/GlobalVariable.py | 2 +- llvmpy/src/Instruction.py | 12 ++- llvmpy/src/Pass.py | 8 +- llvmpy/src/PassManager.py | 2 +- llvmpy/src/PassRegistry.py | 21 ++++ llvmpy/src/PassSupport.py | 24 +++++ llvmpy/src/Support/Host.py | 25 +++++ llvmpy/src/Support/Target.py | 27 ------ llvmpy/src/Support/TargetRegistry.py | 68 +++++++++++++ llvmpy/src/Target/TargetLibraryInfo.py | 9 +- llvmpy/src/Target/TargetMachine.py | 21 ++-- llvmpy/src/Target/TargetOptions.py | 12 +++ llvmpy/test_binding.py | 41 +++++++- 20 files changed, 352 insertions(+), 63 deletions(-) create mode 100644 llvmpy/.gitignore create mode 100644 llvmpy/src/PassRegistry.py create mode 100644 llvmpy/src/PassSupport.py create mode 100644 llvmpy/src/Support/Host.py delete mode 100644 llvmpy/src/Support/Target.py create mode 100644 llvmpy/src/Support/TargetRegistry.py create mode 100644 llvmpy/src/Target/TargetOptions.py diff --git a/llvmpy/.gitignore b/llvmpy/.gitignore new file mode 100644 index 0000000..ab608aa --- /dev/null +++ b/llvmpy/.gitignore @@ -0,0 +1,4 @@ +api.cpp +api/*.py +api/*/*.py + diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index d98a23d..7a7ceaf 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -102,6 +102,13 @@ def release_ownership(old): _addr2dtor[addr] = None +def obtain_ownership(cap): + cls = cap.get_class() + if cls._has_dtor(): + addr = cap.pointer + assert _addr2dtor[addr] is None + _addr2dtor[addr] = cls._delete_ + def has_ownership(cap): addr = Capsule.getPointer(cap) return _addr2dtor.get(addr) is not None diff --git a/llvmpy/include/llvm_binding/auto_pyobject.h b/llvmpy/include/llvm_binding/auto_pyobject.h index 451f2d9..368e64f 100644 --- a/llvmpy/include/llvm_binding/auto_pyobject.h +++ b/llvmpy/include/llvm_binding/auto_pyobject.h @@ -34,5 +34,4 @@ private: void operator = (const auto_pyobject&); }; -#endif AUTO_PYOBJECT_H_ - +#endif // AUTO_PYOBJECT_H_ diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 438f52c..2bbad42 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,9 @@ #include #include #include +#include +#include + #include "auto_pyobject.h" @@ -774,3 +778,96 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, } } +class PassRegistryEnumerator : public llvm::PassRegistrationListener{ +public: + PyObject* List; +public: + PassRegistryEnumerator(PyObject* list) : List(list) { } + + inline virtual void passEnumerate(const llvm::PassInfo * pass_info){ + PyObject* passArg = PyString_FromString(pass_info->getPassArgument()); + PyObject* passName = PyString_FromString(pass_info->getPassName()); + PyList_Append(List, Py_BuildValue("(OO)", passArg, passName)); + } +}; + +static +PyObject* PassRegistry_enumerate(llvm::PassRegistry* PR) +{ + using namespace llvm; + PassRegistryEnumerator PRE(PyList_New(0)); + PR->enumerateWith(&PRE); + return PRE.List; +} + +static +PyObject* TargetRegistry_lookupTarget(const std::string &Triple, + PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::lookupTarget(Triple, error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } +} + + +static +PyObject* TargetRegistry_lookupTarget(const std::string &Arch, + llvm::Triple &Triple, + PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::lookupTarget(Arch, Triple, error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } +} + + +static +PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::getClosestTargetForJIT(error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } + +} + +static +PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) +{ + using namespace llvm::sys; + using namespace llvm; + typedef StringMap::iterator iterator; + StringMap features; + bool ok = getHostCPUFeatures(features); + if (ok) { + for (iterator it = features.begin(); it != features.end(); ++it) { + const char *key = it->getKey().data(); + PyObject *val = it->getValue() ? Py_True : Py_False; + Py_INCREF(val); + if (-1 == PyDict_SetItemString(Features, key, val)) { + return NULL; + } + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/llvmpy/src/Analysis/Verifier.py b/llvmpy/src/Analysis/Verifier.py index 5b47740..3afa075 100644 --- a/llvmpy/src/Analysis/Verifier.py +++ b/llvmpy/src/Analysis/Verifier.py @@ -1,7 +1,7 @@ from binding import * from ..namespace import llvm from ..Module import Module -from ..Function import Function +from ..Value import Function llvm.includes.add('llvm/Analysis/Verifier.h') diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index d704723..9582d53 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -1,15 +1,17 @@ from binding import * from namespace import llvm +from Pass import ImmutablePass + +DataLayout = llvm.Class(ImmutablePass) +StructLayout = llvm.Class() + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Module import Module from Type import Type, IntegerType, StructType from ADT.SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable -from Pass import ImmutablePass -DataLayout = llvm.Class(ImmutablePass) -StructLayout = llvm.Class() @DataLayout class DataLayout: @@ -93,4 +95,9 @@ class DataLayout: @StructLayout class StructLayout: - pass + getSizeInBytes = Method(cast(Uint64, int)) + getSizeInBits = Method(cast(Uint64, int)) + getAlignment = Method(cast(Unsigned, int)) + getElementContainingOffset = Method(cast(Unsigned, int), cast(int, Uint64)) + getElementOffset = Method(cast(Uint64, int), cast(int, Unsigned)) + getElementOffsetInBits = Method(cast(Uint64, int), cast(int, Unsigned)) diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 1188de3..0bd4714 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -34,16 +34,25 @@ class ExecutionEngine: Reloc.Model, CodeModel.Model).require_only(1) - addModule = Method(Void, ptr(Module)) + addModule = Method(Void, ownedptr(Module)) getDataLayout = Method(const(ownedptr(DataLayout))) - removeModule = Method(cast(Bool, bool), ptr(Module)) + _removeModule = Method(cast(Bool, bool), ptr(Module)) + _removeModule.realname = 'removeModule' + @CustomPythonMethod + def removeModule(self, module): + if self._removeModule(module): + capsule.obtain_ownership(module._ptr) + return True + return False FindFunctionNamed = Method(ptr(Function), cast(str, ConstCharPtr)) getPointerToNamedFunction = Method(cast(VoidPtr, int), cast(str, StdString), cast(bool, Bool)).require_only(1) - runStaticConstructorsDestructors = Method(Void, cast(Bool, bool)) + runStaticConstructorsDestructors = Method(Void, + cast(Bool, bool), # is dtor + ) runStaticConstructorsDestructors |= Method(Void, ptr(Module), cast(Bool, bool)) diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index 4ee91fb..2280e24 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -4,10 +4,10 @@ from namespace import llvm from GlobalValue import GlobalValue GlobalVariable = llvm.Class(GlobalValue) -from Constant import Constant from Module import Module from Type import Type from ADT.StringRef import StringRef +from Value import Constant @GlobalVariable class GlobalVariable: diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index ca64072..b3fa701 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,11 +1,6 @@ from binding import * from namespace import llvm from Value import Value, MDNode, User, BasicBlock, Function -from ADT.StringRef import StringRef -from CallingConv import CallingConv -from Attributes import Attributes -from Constant import ConstantInt -from Type import Type Instruction = llvm.Class(User) @@ -68,6 +63,13 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', +from ADT.StringRef import StringRef +from CallingConv import CallingConv +from Attributes import Attributes +from Constant import ConstantInt +from Type import Type + + @Instruction class Instruction: diff --git a/llvmpy/src/Pass.py b/llvmpy/src/Pass.py index 39e894b..f36856c 100644 --- a/llvmpy/src/Pass.py +++ b/llvmpy/src/Pass.py @@ -1,14 +1,14 @@ from binding import * from namespace import llvm -from ADT.StringRef import StringRef -from Module import Module -from Function import Function Pass = llvm.Class() ModulePass = llvm.Class(Pass) FunctionPass = llvm.Class(Pass) ImmutablePass = llvm.Class(ModulePass) +from ADT.StringRef import StringRef +from Module import Module +from Value import Function @Pass class Pass: @@ -16,7 +16,7 @@ class Pass: delete = Destructor() getPassName = Method(cast(StringRef, str)) - + dump = Method() @ModulePass class ModulePass: diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index f969192..91a98f4 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -2,7 +2,7 @@ from binding import * from namespace import llvm from Pass import Pass from Module import Module -from Function import Function +from Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) diff --git a/llvmpy/src/PassRegistry.py b/llvmpy/src/PassRegistry.py new file mode 100644 index 0000000..495de51 --- /dev/null +++ b/llvmpy/src/PassRegistry.py @@ -0,0 +1,21 @@ +from binding import * +from namespace import llvm +from src.ADT.StringRef import StringRef + +PassRegistry = llvm.Class() + +from src.PassSupport import PassInfo + +@PassRegistry +class PassRegistry: + _include_ = 'llvm/PassRegistry.h' + + delete = Destructor() + + getPassRegistry = StaticMethod(ownedptr(PassRegistry)) + + getPassInfo = Method(const(ptr(PassInfo)), cast(str, StringRef)) + + # This is a custom method that wraps enumerateWith + # Returns list of tuples of (pass-arg, pass-name) + enumerate = CustomMethod('PassRegistry_enumerate', PyObjectPtr) \ No newline at end of file diff --git a/llvmpy/src/PassSupport.py b/llvmpy/src/PassSupport.py new file mode 100644 index 0000000..8dba872 --- /dev/null +++ b/llvmpy/src/PassSupport.py @@ -0,0 +1,24 @@ +from binding import * +from namespace import llvm + +PassInfo = llvm.Class() + +from src.Pass import Pass +from src.PassRegistry import PassRegistry + +@PassInfo +class PassInfo: + _include_ = 'llvm/PassSupport.h' + + createPass = Method(ptr(Pass)) + +llvm.Function('initializeCore', Void, ref(PassRegistry)) +llvm.Function('initializeScalarOpts', Void, ref(PassRegistry)) +llvm.Function('initializeVectorization', Void, ref(PassRegistry)) +llvm.Function('initializeIPO', Void, ref(PassRegistry)) +llvm.Function('initializeAnalysis', Void, ref(PassRegistry)) +llvm.Function('initializeIPA', Void, ref(PassRegistry)) +llvm.Function('initializeTransformUtils', Void, ref(PassRegistry)) +llvm.Function('initializeInstCombine', Void, ref(PassRegistry)) +llvm.Function('initializeInstrumentation', Void, ref(PassRegistry)) +llvm.Function('initializeTarget', Void, ref(PassRegistry)) diff --git a/llvmpy/src/Support/Host.py b/llvmpy/src/Support/Host.py new file mode 100644 index 0000000..8163ebe --- /dev/null +++ b/llvmpy/src/Support/Host.py @@ -0,0 +1,25 @@ +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)) + +getHostCPUName = sys.Function('getHostCPUName', + cast(ConstStdString, str)) + +getHostCPUFeatures = sys.CustomFunction('getHostCPUFeatures', + 'llvm_sys_getHostCPUFeatures', + PyObjectPtr, # bool: success? + PyObjectPtr, # dict: store feature map + ) + diff --git a/llvmpy/src/Support/Target.py b/llvmpy/src/Support/Target.py deleted file mode 100644 index bdaeff5..0000000 --- a/llvmpy/src/Support/Target.py +++ /dev/null @@ -1,27 +0,0 @@ -from binding import * -from ..namespace import llvm -from ..ADT.StringRef import StringRef -Target = llvm.Class() - -@Target -class Target: - _include_ = 'llvm/Support/TargetRegistry.h' - - getNext = Method(const(ptr(Target))) - - getName = Method(cast(StringRef, str)) - getShortDescription = Method(cast(StringRef, str)) - - def _has(): - return Method(cast(Bool, bool)) - - hasJIT = _has() - hasTargetMachine = _has() - hasMCAsmBackend = _has() - hasMCAsmParser = _has() - hasAsmPrinter = _has() - hasMCDisassembler = _has() - hasMCInstPrinter = _has() - hasMCCodeEmitter = _has() - hasMCObjectStreamer = _has() - hasAsmStreamer = _has() diff --git a/llvmpy/src/Support/TargetRegistry.py b/llvmpy/src/Support/TargetRegistry.py new file mode 100644 index 0000000..640364b --- /dev/null +++ b/llvmpy/src/Support/TargetRegistry.py @@ -0,0 +1,68 @@ +from binding import * +from src.namespace import llvm + +llvm.includes.add('llvm/Support/TargetRegistry.h') + +Target = llvm.Class() +TargetRegistry = llvm.Class() + +from src.ADT.Triple import Triple +from src.ADT.StringRef import StringRef +from src.Target.TargetMachine import TargetMachine +from src.Target.TargetOptions import TargetOptions +from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt + +@Target +class Target: + getNext = Method(const(ptr(Target))) + + getName = Method(cast(StringRef, str)) + getShortDescription = Method(cast(StringRef, str)) + + def _has(): + return Method(cast(Bool, bool)) + + hasJIT = _has() + hasTargetMachine = _has() + hasMCAsmBackend = _has() + hasMCAsmParser = _has() + hasAsmPrinter = _has() + hasMCDisassembler = _has() + hasMCInstPrinter = _has() + hasMCCodeEmitter = _has() + hasMCObjectStreamer = _has() + hasAsmStreamer = _has() + + createTargetMachine = Method(ptr(TargetMachine), + cast(str, StringRef), # triple + cast(str, StringRef), # cpu + cast(str, StringRef), # features + ref(TargetOptions), + Reloc.Model, # = Reloc::Default + CodeModel.Model, # = CodeModel.Default + CodeGenOpt.Level, # = CodeGenOpt.Default + ).require_only(4) + + +@TargetRegistry +class TargetRegistry: + printRegisteredTargetsForVersion = StaticMethod() + + lookupTarget = CustomStaticMethod('TargetRegistry_lookupTarget', + PyObjectPtr, # const Target* + cast(str, ConstCharPtr), # triple + PyObjectPtr, # std::string &Error + ) + + lookupTarget |= CustomStaticMethod('TargetRegistry_lookupTarget', + PyObjectPtr, # const Target* + cast(str, ConstCharPtr), # arch + ref(Triple), # triple + PyObjectPtr, # std::string &Error + ) + + getClosestTargetForJIT = CustomStaticMethod( + 'TargetRegistry_getClosestTargetForJIT', + PyObjectPtr, # const Target* + PyObjectPtr, # std::string &Error + ) diff --git a/llvmpy/src/Target/TargetLibraryInfo.py b/llvmpy/src/Target/TargetLibraryInfo.py index d98b00b..9c47814 100644 --- a/llvmpy/src/Target/TargetLibraryInfo.py +++ b/llvmpy/src/Target/TargetLibraryInfo.py @@ -1,8 +1,7 @@ from binding import * from ..namespace import llvm -from ..ADT.Triple import Triple -from ..Pass import ImmutablePass -from ..ADT.StringRef import StringRef + +from src.Pass import ImmutablePass TargetLibraryInfo = llvm.Class(ImmutablePass) @@ -54,6 +53,10 @@ LibFunc.Enum('Func', ''' # not in llvm-3.2 abs, ffs, ffsl, ffsll, fprintf, isascii, # isdigit, labs, llabs, printf, sprintf, toascii +from src.ADT.Triple import Triple +from src.ADT.StringRef import StringRef + + @TargetLibraryInfo class TargetLibraryInfo: _include_ = 'llvm/Target/TargetLibraryInfo.h' diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index e60ed5c..29960fa 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -1,17 +1,18 @@ from binding import * -from ..namespace import llvm -from ..ADT.StringRef import StringRef -from ..Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc -from ..GlobalValue import GlobalValue -from ..Support.Target import Target -from ..DataLayout import DataLayout -from ..TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) -from ..PassManager import PassManagerBase -from ..Support.FormattedStream import formatted_raw_ostream +from src.namespace import llvm TargetMachine = llvm.Class() +from src.Support.TargetRegistry import Target +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) +from src.PassManager import PassManagerBase +from src.Support.FormattedStream import formatted_raw_ostream + @TargetMachine class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' diff --git a/llvmpy/src/Target/TargetOptions.py b/llvmpy/src/Target/TargetOptions.py new file mode 100644 index 0000000..0e28677 --- /dev/null +++ b/llvmpy/src/Target/TargetOptions.py @@ -0,0 +1,12 @@ +from binding import * +from src.namespace import llvm + +llvm.includes.add('llvm/Target/TargetOptions.h') + +TargetOptions = llvm.Class() + +@TargetOptions +class TargetOptions: + new = Constructor() + delete = Destructor() + diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index e1e12e5..01e6c38 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -7,9 +7,10 @@ import llvmpy.capsule llvmpy.capsule.set_debug(True) +llvm.InitializeNativeTarget() +llvm.InitializeNativeTargetAsmPrinter() + def test_basic_jit_use(): - llvm.InitializeNativeTarget() - llvm.InitializeNativeTargetAsmPrinter() context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) @@ -332,6 +333,42 @@ def test_intrinsic(): fn.eraseFromParent() assert 'llvm.sin.f32' not in str(m) +def test_passregistry(): + passreg = llvm.PassRegistry.getPassRegistry() + + llvm.initializeScalarOpts(passreg) + + passinfo = passreg.getPassInfo("dce") + dcepass = passinfo.createPass() + print dcepass.getPassName() + + print passreg.enumerate() + +def test_targetregistry(): + llvm.TargetRegistry.printRegisteredTargetsForVersion() + errmsg = StringIO() + + target = llvm.TargetRegistry.getClosestTargetForJIT(errmsg) + errmsg.close() + + print target.getName() + print target.getShortDescription() + assert target.hasJIT() + assert target.hasTargetMachine() + + next = target.getNext() + if next: + print next.getName() + print next.getShortDescription() + + triple = llvm.sys.getDefaultTargetTriple() + cpu = llvm.sys.getHostCPUName() + features = {} + assert not llvm.sys.getHostCPUFeatures(features), "Only for Linux and ARM?" + + targetoptions = llvm.TargetOptions.new() + tm = target.createTargetMachine(triple, cpu, "", targetoptions) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value): From a97b26415e7e21d63abfe66ed9c31b3e9a1d1e7d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 18:15:22 -0600 Subject: [PATCH 091/338] Update old API to use the new binding. Have not run the testsuite yet. --- llvm/__init__.py | 4 + llvm/core.py | 30 ++++ llvm/ee.py | 334 ++++++++++++++++++++++++++++++++++++++++++ llvm/passes.py | 371 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 739 insertions(+) diff --git a/llvm/__init__.py b/llvm/__init__.py index 23f3f4d..4cf374c 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,5 +1,6 @@ class Wrapper(object): def __init__(self, ptr): + assert ptr self.__ptr = ptr @property @@ -9,3 +10,6 @@ class Wrapper(object): def _extract_ptrs(objs): return [x._ptr for x in objs] + +class LLVMException(Exception): + pass diff --git a/llvm/core.py b/llvm/core.py index 2f7adb5..3c3e027 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1,3 +1,33 @@ +# +# Copyright (c) 2008-10, Mahadevan R All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of this software, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + try: from cStringIO import StringIO except ImportError: diff --git a/llvm/ee.py b/llvm/ee.py index e69de29..8523998 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -0,0 +1,334 @@ +# +# Copyright (c) 2008-10, Mahadevan R All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of this software, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +"Execution Engine and related classes." + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +import contextlib + +import llvm +from llvm import core +from llvmpy import api + +#===----------------------------------------------------------------------=== +# Enumerations +#===----------------------------------------------------------------------=== + +BO_BIG_ENDIAN = 0 +BO_LITTLE_ENDIAN = 1 + +# CodeModel +CM_DEFAULT = api.llvm.CodeModel.Model.Default +CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault +CM_SMALL = api.llvm.CodeModel.Model.Small +CM_KERNEL = api.llvm.CodeModel.Model.Kernel +CM_MEDIUM = api.llvm.CodeModel.Model.Medium +CM_LARGE = api.llvm.CodeModel.Model.Large + +#===----------------------------------------------------------------------=== +# Generic value +#===----------------------------------------------------------------------=== + +class GenericValue(llvm.Wrapper): + + @staticmethod + def int(ty, intval): + ptr = api.llvm.CreateInt(ty._ptr, intval, False) + return GenericValue(ptr) + + @staticmethod + def int_signed(ty, intval): + ptr = api.llvm.CreateInt(ty._ptr, intval, True) + return GenericValue(ptr) + + @staticmethod + def real(ty, floatval): + if str(ty) == 'float': + ptr = api.llvm.CreateFloat(floatval) + elif str(ty) == 'double': + ptr = api.llvm.CreateDouble(floatval) + else: + raise Exception('Unreachable') + return GenericValue(ptr) + + @staticmethod + def pointer(addr): + ''' + One argument version takes (addr). + Two argument version takes (ty, addr). [Deprecated] + + `ty` is unused. + `addr` is an integer representing an address. + + ''' + ptr = api.llvm.CreatePointer(addr) + return GenericValue(ptr) + + def as_int(self): + return self._ptr.toUnsignedInt() + + def as_int_signed(self): + return self._ptr.toSignedInt() + + def as_real(self, ty): + return self._ptr.toFloat() + + def as_pointer(self): + return self._ptr.toPointer() + +#===----------------------------------------------------------------------=== +# Engine builder +#===----------------------------------------------------------------------=== + +class EngineBuilder(llvm.Wrapper): + @staticmethod + def new(module): + ptr = api.llvm.EngineBuilder.new(module) + return EngineBuilder(ptr) + + def force_jit(self): + self._ptr.setEngineKind(api.llvm.EngineKind.Kind.JIT) + return self + + def force_interpreter(self): + self._ptr.setEngineKind(api.llvm.EngineKind.Kind.Interpreter) + return self + + def opt(self, level): + ''' + level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] + ''' + assert 0 <= level <= 3 + self._ptr.setOptLevel = level + return self + + def mattrs(self, string): + '''set machine attributes as a comma/space separated string + + e.g: +sse,-3dnow + ''' + self._ptr.setMAttrs(string.split(',')) + return self + + def create(self, tm=None): + ''' + tm --- Optional. Provide a TargetMachine. Ownership is transfered + to the returned execution engine. + ''' + if tm is not None: + engine = self._ptr.create(tm._ptr) + else: + engine = self._ptr.create() + return ExecutionEngine(engine) + + def select_target(self, *args): + '''get the corresponding target machine + + Accept no arguments or (triple, march, mcpu, mattrs) + ''' + if args: + triple, march, mcpu, mattrs = args + ptr = self._ptr.select_target(triple, march, mcpu, + mattrs.split(',')) + else: + ptr = self._ptr.select_target() + return TargetMachine(ptr) + + +#===----------------------------------------------------------------------=== +# Execution engine +#===----------------------------------------------------------------------=== + +class ExecutionEngine(llvm.Wrapper): + + @staticmethod + def new(module, force_interpreter=False): + eb = EngineBuilder.new(module) + if force_interpreter: + eb.force_interpreter() + return eb.create() + + def disable_lazy_compilation(self, disabled=True): + self._ptr.DisableLazyCompilation(disabled) + + def run_function(self, fn, args): + return self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + + def get_pointer_to_function(self, fn): + return self._ptr.getPointerToFunction(fn._ptr) + + def get_pointer_to_global(self, val): + return self._ptr.getPointerToGlobal(val._ptr) + + def add_global_mapping(self, gvar, addr): + assert addr >= 0, "Address cannot not be negative" + self._ptr.addGlobalMapping(gvar._ptr, addr) + + def run_static_ctors(self): + self._ptr.runStaticConstructorDestructors(False) + + def run_static_dtors(self): + self._ptr.runStaticConstructorDestructors(True) + + def free_machine_code_for(self, fn): + self.freeMachineCodeForFunction(fn._ptr) + + def add_module(self, module): + self._ptr.addModule(module._ptr) + + def remove_module(self, module): + return self._ptr.removeModule(module._ptr) + + @property + def target_data(self): + ptr = self._ptr.getDataLayout() + return TargetData(ptr) + +#===----------------------------------------------------------------------=== +# Target machine +#===----------------------------------------------------------------------=== + +def print_registered_targets(): + ''' + Note: print directly to stdout + ''' + llvm.TargetRegistry.printRegisteredTargetsForVersion() + +def get_host_cpu_name(): + '''return the string name of the host CPU + ''' + return llvm.sys.getHostCPUName() + +def get_default_triple(): + '''return the target triple of the host in str-rep + ''' + return llvm.sys.getDefaultTargetTriple() + + +class TargetMachine(llvm.Wrapper): + + @staticmethod + def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT): + if not triple: + triple = get_default_triple() + if not cpu: + cpu = get_host_cpu_name() + with contextlib.closing(StringIO) as error: + target = api.llvm.TargetRegistry.lookupTarget(triple, error) + if not target: + raise llvm.LLVMException(error) + if not target.hasTargetMachine(): + raise llvm.LLVMException(target, "No target machine.") + target_options = api.llvm.TargetOptions() + tm = target.createTargetMachine(triple, cpu, features, + target_options, + api.llvm.Reloc.Model.Default, + cm, opt) + if not tm: + raise llvm.LLVMException("Cannot create target machine") + return TargetMachine(ptr) + + @staticmethod + def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): + '''create a targetmachine given an architecture name + + For a list of architectures, + use: `llc -help` + + For a list of available CPUs, + use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help` + + For a list of available attributes (features), + use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` + ''' + triple = api.llvm.Triple.new() + with contextlib.closing(StringIO) as error: + target = api.llvm.TargetMachine.lookupTarget(arch, triple, error) + if not target: + raise llvm.LLVMException(error) + if not target.hasTargetMachine(): + raise llvm.LLVMException(target, "No target machine.") + target_options = api.llvm.TargetOptions() + tm = target.createTargetMachine(str(triple), cpu, features, + target_options, + api.llvm.Reloc.Model.Default, + cm, opt) + if not tm: + raise llvm.LLVMException("Cannot create target machine") + return TargetMachine(ptr) + + def _emit_file(self, module, cgft): + pm = api.llvm.PassManager.new() + os = api.extra.make_raw_ostream_for_printing() + failed = self._ptr.addPassesToEmitFile(pm, os, cgft) + pm.run(module) + return os.str() + + def emit_assembly(self, module): + '''returns byte string of the module as assembly code of the target machine + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._emit_file(module, CGFT.CGFT_AssemblyFile) + + def emit_object(self, module): + '''returns byte string of the module as native code of the target machine + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._emit_file(module, CGFT.CGFT_ObjectFile) + + @property + def target_data(self): + '''get target data of this machine + ''' + return TargetData(self._ptr.getDataLayout) + + @property + def target_name(self): + return self._ptr.getTarget().getName() + + @property + def target_short_description(self): + return self._ptr.getTarget().getShortDescription() + + @property + def triple(self): + return self._ptr.getTargetTriple() + + @property + def cpu(self): + return self._ptr.getTargetCPU() + + @property + def feature_string(self): + return self._ptr.getTargetFeatureString() + diff --git a/llvm/passes.py b/llvm/passes.py index e69de29..545a19d 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -0,0 +1,371 @@ +# +# Copyright (c) 2008-10, Mahadevan R All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of this software, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +"""Pass managers and passes. + +This module provides the LLVM pass managers and the passes themselves. +All transformation passes listed at http://www.llvm.org/docs/Passes.html +are available. +""" + +import llvm # top-level, for common stuff +import llvm.core as core # module, function etc. +from llvmpy import api + +#===----------------------------------------------------------------------=== +# Pass manager builder +#===----------------------------------------------------------------------=== + +class PassManagerBuilder(llvm.Wrapper): + @staticmethod + def new(): + return PassManagerBuilder(api.llvm.PassManagerBuilder()) + + def populate(self, pm): + if isinstance(pm, FunctionPassManager): + self._ptr.populateFunctionPassManager(pm._ptr) + else: + self._ptr.populateModulePassManager(pm._ptr) + + @property + def opt_level(self): + return self._ptr.OptLevel + + @opt_level.setter + def _set_opt_level(self, optlevel): + self._ptr.OptLevel = optlevel + + @property + def size_level(self): + return self._ptr.SizeLevel + + @size_level.setter + def _set_size_level(self, sizelevel): + self._ptr.SizeLevel = sizelevel + + @property + def vectorize(self): + return self._ptr.Vectorize + + @vectorize.setter + def _set_vectorize(self, enable): + self._ptr.Vectroize = enable + + @property + def loop_vectorize(self): + try: + return self._ptr.LoopVectorize + except AttributeError: + return False + + @loop_vectorize.setter + def loop_vectorize(self, enable): + if llvm.version >= (3, 2): + self._ptr.LoopVectorize = enable + elif enable: + warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.") + + @property + def disable_unit_at_a_time(self): + return self._ptr.DisableUnitAtATime + + @disable_unit_at_a_time.setter + def disable_unit_at_a_time(self, disable): + self._ptr.DisableUnitAtATime = disable + + @property + def disable_unroll_loops(self): + return self._ptr.DisableUnrollLoops + + @disable_unroll_loops.setter + def disable_unroll_loops(self, disable): + self._ptr.DisableUnrollLoops = disable + + @property + def disable_simplify_lib_calls(self): + return self._ptr.DisableSimplifyLibCalls + + @disable_simplify_lib_calls.setter + def disable_simplify_lib_calls(self, disable): + self._ptr.DisableSimplifyLibCalls = disable + + def use_inliner_with_threshold(self, threshold): + self._ptr.Inliner = api.llvm.createFunctionInliningPass(threshold) + + +#===----------------------------------------------------------------------=== +# Pass manager +#===----------------------------------------------------------------------=== + +class PassManager(llvm.Wrapper): + + @staticmethod + def new(): + return PassManager(api.llvm.PassManager.new()) + + def add(self, pass_obj): + '''Add a pass to the pass manager. + + pass_obj --- Either a Pass instance, a string name of a pass + ''' + if isinstance(pass_obj, Pass): + self._ptr.add(pass_obj._ptr) + else: + self._add_pass(str(pass_obj)) + + def _add_pass(self, pass_name): + passreg = api.llvm.PassRegistry.getPassRegistry() + a_pass = passreg.getPassInfo(pass_name) + if not a_pass: + assert pass_name not in PASSES, "Registered but not found?" + raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) + self._ptr.add(a_pass) + + def run(self, module): + return self._ptr.run(module._ptr) + +class FunctionPassManager(PassManager): + + @staticmethod + def new(module): + ptr = api.llvm.FunctionPassManager.new(module) + return FunctionPassManager(ptr) + + def __init__(self, ptr): + PassManager.__init__(self, ptr) + + def initialize(self): + self._ptr.doInitization() + + def run(self, fn): + return self._ptr.run(fn) + + def finalize(self): + self._ptr.doFinalization() + +#===----------------------------------------------------------------------=== +# Passes +#===----------------------------------------------------------------------=== + +class Pass(llvm.Wrapper): + '''Pass Inferface + ''' + + @staticmethod + def new(name): + '''Create a new pass by name. + + Note: Not all pass has a default constructor. LLVM will kill + the process if an the pass requires arguments to construct. + The error cannot be caught. + ''' + passreg = api.llvm.PassRegistry.getPassRegistry() + a_pass = passreg.getPassInfo(pass_name) + p = Pass(a_pass) + p.__name = name + return p + + @property + def name(self): + '''The name used in PassRegistry. + ''' + return p.__name + + @property + def description(self): + return self._ptr.getPassName() + + def dump(self): + return self._ptr.dump() + +#===----------------------------------------------------------------------=== +# Target data +#===----------------------------------------------------------------------=== + +class TargetData(Pass): + + @staticmethod + def new(strrep): + ptr = api.llvm.DataLayout.new(strrep) + return TargetData(ptr) + + def clone(self): + return TargetData.new(str(self)) + + def __str__(self): + return self._ptr.getStringRepresentation() + + @property + def byte_order(self): + if self._ptr.isLittleEndian(): + return 1 + else: + return 0 + + @property + def pointer_size(self): + return self._ptr.getPointerSize() + + @property + def target_integer_type(self): + return self._ptr.core.IntegerType(core.Type.getInt32Ty()) + + def size(self, ty): + return self._ptr.getTypeSizeInBits(ty._ptr) + + def store_size(self, ty): + return self._ptr.getTypeStoreSize(ty._ptr) + + def abi_size(self, ty): + return self._ptr.getTypeAllocSize(ty._ptr) + + def abi_alignment(self, ty): + return self._ptr.getABITypeAlignment(ty._ptr) + + def callframe_alignment(self, ty): + return self._ptr.getCallFrameTypeAlignment(ty._ptr) + + def preferred_alignment(self, ty_or_gv): + if isinstance(ty_or_gv, core.Type): + return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr) + elif isinstance(ty_or_gv, core.GlobalVariable): + return self._ptr._core.getPreferredAlignment(ty_or_gv._ptr) + else: + raise core.LLVMException("argument is neither a type nor a global variable") + + def element_at_offset(self, ty, ofs): + return self._ptr.getStructLayout(ty).getElementContainingOffset(ofs) + + def offset_of_element(self, ty, el): + return self._ptr.getStructLayout(ty).getElementOffset(el) + +#===----------------------------------------------------------------------=== +# Target Library Info +#===----------------------------------------------------------------------=== + +class TargetLibraryInfo(Pass): + @staticmethod + def new(triple): + triple = api.llvm.Triple.new(str(triple)) + ptr = api.llvm.TargetLibraryInfo.new(triple) + return TargetLibraryInfo(ptr) + +#===----------------------------------------------------------------------=== +# Helpers +#===----------------------------------------------------------------------=== + +def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False, + inline_threshold=2000, pm=True, fpm=True, mod=None): + ''' + tm --- The TargetMachine for which the passes are optimizing for. + The TargetMachine must stay alive until the pass managers + are removed. + opt --- [0-3] Optimization level. Default to 2. + loop_vectorize --- [boolean] Whether to use loop-vectorizer. + vectorize --- [boolean] Whether to use basic-block vectorizer. + inline_threshold --- [int] Threshold for the inliner. + features --- [str] CPU feature string. + pm --- [boolean] Whether to build a module-level pass-manager. + fpm --- [boolean] Whether to build a function-level pass-manager. + mod --- [Module] The module object for the FunctionPassManager. + ''' + if pm: + pm = PassManager.new() + if fpm: + if not mod: + raise TypeError("Keyword 'mod' must be defined") + fpm = FunctionPassManager.new(mod) + + # Populate PassManagers with target specific passes + pmb = PassManagerBuilder.new() + pmb.opt_level = opt + pmb.vectorize = vectorize + pmb.loop_vectorize = loop_vectorize + if inline_threshold: + pmb.use_inliner_with_threshold(inline_threshold) + if pm: + pm.add(tm.target_data.clone()) + pm.add(TargetLibraryInfo.new(tm.triple)) + if llvm.version >= (3, 2): + pm.add(TargetTransformInfo.new(tm)) + pmb.populate(pm) + + if fpm: + fpm.add(tm.target_data) + fpm.add(TargetLibraryInfo.new(tm.triple)) + if llvm.version >= (3, 2): + fpm.add(TargetTransformInfo.new(tm)) + pmb.populate(fpm) + fpm.initialize() + + from collections import namedtuple + return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm) + +#===----------------------------------------------------------------------=== +# Misc. +#===----------------------------------------------------------------------=== + +# Intialize passes +PASSES = None + +def _dump_all_passes(): + passreg = api.llvm.PassRegistry.getPassRegistry() + for name, desc in passreg.enumerate(): + yield name, desc + +def _initialize_passes(): + global PASSES + + passreg = api.llvm.PassRegistry.getPassRegistry() + + api.llvm.initializeCore(passreg) + api.llvm.initializeScalarOpts(passreg) + api.llvm.initializeVectorization(passreg) + api.llvm.initializeIPO(passreg) + api.llvm.initializeAnalysis(passreg) + api.llvm.initializeIPA(passreg) + api.llvm.initializeTransformUtils(passreg) + api.llvm.initializeInstCombine(passreg) + api.llvm.initializeInstrumentation(passreg) + api.llvm.initializeTarget(passreg) + + PASSES = dict(_dump_all_passes()) + + # build globals + def transform(name): + return "PASS_%s" % (name.upper().replace('-', '_')) + + global_symbols = globals() + for i in PASSES: + assert i not in global_symbols + global_symbols[transform(i)] = i + +_initialize_passes() + From b4f4483809c006918056d932f5f93639efd221e5 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 12 Feb 2013 11:24:36 -0600 Subject: [PATCH 092/338] Py3k fixes for Windows --- llvm-config-win32.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 595452c..2fbe662 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -1,4 +1,6 @@ -import sys, os +import sys +import os + def find_path_of(filename, envvar='PATH'): """Finds the path from $PATH where the file exists, returns None if not found.""" @@ -8,11 +10,12 @@ def find_path_of(filename, envvar='PATH'): return os.path.abspath(path) return None + if sys.argv[1] == '--version': cmd = 'llvm-tblgen --version' # Hardcoded extraction, only tested on llvm 3.1 result = os.popen(cmd).read().split('\n')[1].strip().split(' ')[2] - print result + print(result) elif sys.argv[1] == '--libs': # NOTE: instead of actually looking at the components requested, # we just spit out a bunch of libs @@ -70,7 +73,7 @@ elif sys.argv[1] == '--includedir': incdir = os.path.abspath(os.path.join(llvmbin, '../include')) if not os.path.exists(os.path.join(incdir, 'llvm/BasicBlock.h')): raise RuntimeError('Could not find LLVM include dir') - print incdir + print(incdir) elif sys.argv[1] == '--libdir': llvmbin = find_path_of('llvm-tblgen.exe') if llvmbin is None: @@ -78,6 +81,6 @@ elif sys.argv[1] == '--libdir': libdir = os.path.abspath(os.path.join(llvmbin, '../lib')) if not os.path.exists(os.path.join(libdir, 'LLVMCore.lib')): raise RuntimeError('Could not find LLVM lib dir') - print libdir + print(libdir) else: raise RuntimeError('Unrecognized llvm-config command %s' % sys.argv[1]) From 0036d55eead8782bd603e5202c22f8d5dde0b027 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 12 Feb 2013 11:55:04 -0600 Subject: [PATCH 093/338] remove excess whitespace --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 78079fd..c24aa66 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ def get_enabled_components(): return run_llvm_config(['--components']).split() def get_llvm_version(): - return run_llvm_config([' --version']) + return run_llvm_config(['--version']) def auto_intrinsic_gen(incdir): From a09394cacdcc841c22d205976ef3d059686cd716 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 13 Feb 2013 15:09:26 -0600 Subject: [PATCH 094/338] Fix a lots of bugs in the newbinding to pass all the tests. NOTE: debug info has not been implemented yet. --- llvm/__init__.py | 22 +- llvm/_version.py | 193 +++ llvm/core.py | 1065 ++++++++------ llvm/ee.py | 60 +- llvm/passes.py | 49 +- llvm/tbaa.py | 51 + llvm/test_llvmpy.py | 1243 +++++++++++++++++ llvmpy/capsule.py | 6 +- llvmpy/gen/binding.py | 17 +- llvmpy/include/llvm_binding/conversion.h | 21 +- llvmpy/include/llvm_binding/extra.h | 54 +- llvmpy/src/Argument.py | 4 +- llvmpy/src/Attributes.py | 2 +- llvmpy/src/BasicBlock.py | 4 +- llvmpy/src/Constant.py | 33 +- llvmpy/src/DerivedTypes.py | 1 + llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 +- llvmpy/src/Function.py | 4 +- llvmpy/src/GenericValue.py | 4 +- llvmpy/src/IRBuilder.py | 7 +- llvmpy/src/Instruction.py | 6 +- llvmpy/src/Metadata.py | 2 + llvmpy/src/Target/TargetMachine.py | 6 +- llvmpy/src/TargetTransformInfo.py | 10 +- llvmpy/src/Transforms/PassManagerBuilder.py | 11 +- llvmpy/src/Transforms/Utils/Cloning.py | 10 +- llvmpy/src/Type.py | 20 +- llvmpy/src/Value.py | 9 + test/constants.py | 2 - test/malloc.py | 16 + test/operands.py | 2 + test/testall.py | 29 +- 32 files changed, 2419 insertions(+), 546 deletions(-) create mode 100644 llvm/_version.py create mode 100644 llvm/tbaa.py create mode 100644 llvm/test_llvmpy.py create mode 100644 test/malloc.py diff --git a/llvm/__init__.py b/llvm/__init__.py index 4cf374c..c18d066 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,3 +1,12 @@ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions + + +from llvmpy import extra +version = extra.get_llvm_version() +del extra + class Wrapper(object): def __init__(self, ptr): assert ptr @@ -9,7 +18,18 @@ class Wrapper(object): def _extract_ptrs(objs): - return [x._ptr for x in objs] + return [(x._ptr if x is not None else None) + for x in objs] class LLVMException(Exception): pass + +def test(verbosity=1): + """test(verbosity=1) -> TextTestResult + + Run self-test, and return unittest.runner.TextTestResult object. + """ + from llvm.test_llvmpy import run + + return run(verbosity=verbosity) + diff --git a/llvm/_version.py b/llvm/_version.py new file mode 100644 index 0000000..a90c5b8 --- /dev/null +++ b/llvm/_version.py @@ -0,0 +1,193 @@ + +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by github's download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7+ (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "$Format:%d$" +git_full = "$Format:%H$" +GIT = "git" + +import subprocess +import sys + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % args[0]) + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%s', no digits" % ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %s" % ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "" +parentdir_prefix = "llvmpy-" +versionfile_source = "llvm/_version.py" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver diff --git a/llvm/core.py b/llvm/core.py index 3c3e027..1c3184c 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -32,11 +32,12 @@ try: from cStringIO import StringIO except ImportError: from StringIO import StringIO -import contextlib +import contextlib, weakref import llvm +from llvm._intrinsic_ids import * -import api +from llvmpy import api #===----------------------------------------------------------------------=== # Enumerations @@ -88,167 +89,180 @@ VALUE_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.PseudoSourceVal VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.FixedStackPseudoSourceValueVal VALUE_INSTRUCTION = api.llvm.Value.ValueTy.InstructionVal -## 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 -# -## calling conventions -#CC_C = 0 -#CC_FASTCALL = 8 -#CC_COLDCALL = 9 -#CC_GHC = 10 -#CC_X86_STDCALL = 64 -#CC_X86_FASTCALL = 65 -#CC_ARM_APCS = 66 -#CC_ARM_AAPCS = 67 -#CC_ARM_AAPCS_VFP = 68 -#CC_MSP430_INTR = 69 -#CC_X86_THISCALL = 70 -#CC_PTX_KERNEL = 71 -#CC_PTX_DEVICE = 72 -#CC_MBLAZE_INTR = 73 -#CC_MBLAZE_SVOL = 74 -# -# -## int predicates -#ICMP_EQ = 32 -#ICMP_NE = 33 -#ICMP_UGT = 34 -#ICMP_UGE = 35 -#ICMP_ULT = 36 -#ICMP_ULE = 37 -#ICMP_SGT = 38 -#ICMP_SGE = 39 -#ICMP_SLT = 40 -#ICMP_SLE = 41 -# -## same as ICMP_xx, for backward compatibility -#IPRED_EQ = ICMP_EQ -#IPRED_NE = ICMP_NE -#IPRED_UGT = ICMP_UGT -#IPRED_UGE = ICMP_UGE -#IPRED_ULT = ICMP_ULT -#IPRED_ULE = ICMP_ULE -#IPRED_SGT = ICMP_SGT -#IPRED_SGE = ICMP_SGE -#IPRED_SLT = ICMP_SLT -#IPRED_SLE = ICMP_SLE -# -## real predicates -#FCMP_FALSE = 0 -#FCMP_OEQ = 1 -#FCMP_OGT = 2 -#FCMP_OGE = 3 -#FCMP_OLT = 4 -#FCMP_OLE = 5 -#FCMP_ONE = 6 -#FCMP_ORD = 7 -#FCMP_UNO = 8 -#FCMP_UEQ = 9 -#FCMP_UGT = 10 -#FCMP_UGE = 11 -#FCMP_ULT = 12 -#FCMP_ULE = 13 -#FCMP_UNE = 14 -#FCMP_TRUE = 15 -# -## real predicates -#RPRED_FALSE = FCMP_FALSE -#RPRED_OEQ = FCMP_OEQ -#RPRED_OGT = FCMP_OGT -#RPRED_OGE = FCMP_OGE -#RPRED_OLT = FCMP_OLT -#RPRED_OLE = FCMP_OLE -#RPRED_ONE = FCMP_ONE -#RPRED_ORD = FCMP_ORD -#RPRED_UNO = FCMP_UNO -#RPRED_UEQ = FCMP_UEQ -#RPRED_UGT = FCMP_UGT -#RPRED_UGE = FCMP_UGE -#RPRED_ULT = FCMP_ULT -#RPRED_ULE = FCMP_ULE -#RPRED_UNE = FCMP_UNE -#RPRED_TRUE = FCMP_TRUE -# -## linkages (see llvm-c/Core.h) -#LINKAGE_EXTERNAL = 0 -#LINKAGE_AVAILABLE_EXTERNALLY = 1 -#LINKAGE_LINKONCE_ANY = 2 -#LINKAGE_LINKONCE_ODR = 3 -#LINKAGE_WEAK_ANY = 4 -#LINKAGE_WEAK_ODR = 5 -#LINKAGE_APPENDING = 6 -#LINKAGE_INTERNAL = 7 -#LINKAGE_PRIVATE = 8 -#LINKAGE_DLLIMPORT = 9 -#LINKAGE_DLLEXPORT = 10 -#LINKAGE_EXTERNAL_WEAK = 11 -#LINKAGE_GHOST = 12 -#LINKAGE_COMMON = 13 -#LINKAGE_LINKER_PRIVATE = 14 -#LINKAGE_LINKER_PRIVATE_WEAK = 15 -#LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 -# -## visibility (see llvm/GlobalValue.h) -#VISIBILITY_DEFAULT = 0 -#VISIBILITY_HIDDEN = 1 -#VISIBILITY_PROTECTED = 2 +# 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 + +# 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 + + +# 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 + +# same as ICMP_xx, for backward compatibility +IPRED_EQ = ICMP_EQ +IPRED_NE = ICMP_NE +IPRED_UGT = ICMP_UGT +IPRED_UGE = ICMP_UGE +IPRED_ULT = ICMP_ULT +IPRED_ULE = ICMP_ULE +IPRED_SGT = ICMP_SGT +IPRED_SGE = ICMP_SGE +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 + +# real predicates +RPRED_FALSE = FCMP_FALSE +RPRED_OEQ = FCMP_OEQ +RPRED_OGT = FCMP_OGT +RPRED_OGE = FCMP_OGE +RPRED_OLT = FCMP_OLT +RPRED_OLE = FCMP_OLE +RPRED_ONE = FCMP_ONE +RPRED_ORD = FCMP_ORD +RPRED_UNO = FCMP_UNO +RPRED_UEQ = FCMP_UEQ +RPRED_UGT = FCMP_UGT +RPRED_UGE = FCMP_UGE +RPRED_ULT = FCMP_ULT +RPRED_ULE = FCMP_ULE +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 + +# 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 # parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) ATTR_NONE = api.llvm.Attributes.AttrVal.None_ @@ -291,6 +305,16 @@ class Module(llvm.Wrapper): module_obj = Module.new('my_module') """ + __cache = weakref.WeakValueDictionary() + + def __new__(cls, ptr): + cached = cls.__cache.get(ptr) + if cached: + return cached + obj = object.__new__(cls) + cls.__cache[ptr] = obj + return obj + @staticmethod def new(id): """Create a new Module instance. @@ -314,6 +338,7 @@ class Module(llvm.Wrapper): else: bc = fileobj_or_str.read() errbuf = StringIO() + context = api.llvm.getGlobalContext() m = api.llvm.ParseBitCodeFile(bc, context, errbuf) if not m: raise Exception(errbuf.getvalue()) @@ -335,7 +360,9 @@ class Module(llvm.Wrapper): else: ir = fileobj_or_str.read() errbuf = StringIO() - m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDIagnostic.new(), context) + context = api.llvm.getGlobalContext() + m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDiagnostic.new(), + context) errbuf.close() return Module(m) @@ -351,6 +378,7 @@ class Module(llvm.Wrapper): return str(self._ptr) def __eq__(self, rhs): + assert isinstance(rhs, Module), type(rhs) if isinstance(rhs, Module): return str(self) == str(rhs) else: @@ -386,7 +414,7 @@ class Module(llvm.Wrapper): @property def pointer_size(self): - return self.getPointerSize() + return self._ptr.getPointerSize() def link_in(self, other, preserve=False): """Link the `other' module into this one. @@ -401,20 +429,21 @@ class Module(llvm.Wrapper): Linker class. """ assert isinstance(other, Module) - enum_mode = api.llvm.Linker.LinkMode + enum_mode = api.llvm.Linker.LinkerMode mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource with contextlib.closing(StringIO()) as errmsg: - failed = api.llvm.Linker.LinkModule(self._ptr, - other._ptr, - mode, - errmsg) + failed = api.llvm.Linker.LinkModules(self._ptr, + other._ptr, + mode, + errmsg) if failed: raise llvm.LLVMException(errmsg) def get_type_named(self, name): typ = self._ptr.getTypeByName(name) - return StructType(typ) + if typ: + return StructType(typ) def add_global_variable(self, ty, name, addrspace=0): """Add a global variable of given type with given name.""" @@ -422,7 +451,7 @@ class Module(llvm.Wrapper): notthreadlocal = api.llvm.GlobalVariable.ThreadLocalMode.NotThreadLocal init = None insertbefore = None - ptr = api.llvm.GlobalVariable.new(self, + ptr = api.llvm.GlobalVariable.new(self._ptr, ty._ptr, False, external, @@ -431,16 +460,18 @@ class Module(llvm.Wrapper): insertbefore, notthreadlocal, addrspace) - return GlobalVariable(ptr) + return _make_value(ptr) def get_global_variable_named(self, name): """Return a GlobalVariable object for the given name.""" ptr = self._ptr.getNamedGlobal(name) - return GlobalVariable(ptr) + if ptr is None: + raise llvm.LLVMException("No global named: %s" % name) + return _make_value(ptr) @property def global_variables(self): - return self._ptr.list_globals() + return map(_make_value, self._ptr.list_globals()) def add_function(self, ty, name): """Add a function of given type with given name.""" @@ -452,21 +483,25 @@ class Module(llvm.Wrapper): def get_function_named(self, name): """Return a Function object representing function with given name.""" fn = self._ptr.getFunction(name) - if fn is None: - return None - return Function(fn) + if fn is not None: + return _make_value(fn) def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" constant = self._ptr.getOrInsertFunction(name, ty._ptr) - fn = constant._downcast(api.llvm.Function) - return Function(fn) + try: + fn = constant._downcast(api.llvm.Function) + except ValueError: + # bitcasted to function type + return _make_value(constant) + else: + return _make_value(fn) @property def functions(self): """All functions in this module.""" - return map(Function, self._ptr.list_functions()) + return map(_make_value, self._ptr.list_functions()) def verify(self): """Verify module. @@ -498,7 +533,7 @@ class Module(llvm.Wrapper): return fileobj.getvalue() def _get_id(self): - return self._ptr.getModuleIdentifier(self._ptr) + return self._ptr.getModuleIdentifier() def _set_id(self, string): self._ptr.setModuleIdentifier(string) @@ -506,13 +541,18 @@ class Module(llvm.Wrapper): id = property(_get_id, _set_id) def _to_native_something(self, fileobj, cgft): - ret = False - if fileobj is None: - ret = True - fileobj = StringIO() + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_ObjectFile - failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + + from llvm.ee import TargetMachine + from llvm.passes import PassManager + from llvmpy import extra + tm = TargetMachine.new()._ptr + pm = PassManager.new()._ptr + formatted + failed = tm.addPassesToEmitFile(pm, fileobj, cgft, False) + if failed: raise llvm.LLVMException("Failed to write native object file") if ret: @@ -525,8 +565,16 @@ class Module(llvm.Wrapper): If a fileobj is given, the output is written to it; Otherwise, the output is returned ''' - CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._to_native_something(fileobj, CGFT.CGFT_ObjectFile) + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + from llvm.ee import TargetMachine + tm = TargetMachine.new() + fileobj.write(tm.emit_object(self)) + if ret: + return fileobj.getvalue() + def to_native_assembly(self, fileobj=None): '''Outputs the byte string of the module as native assembly code @@ -534,17 +582,27 @@ class Module(llvm.Wrapper): If a fileobj is given, the output is written to it; Otherwise, the output is returned ''' - CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._to_native_something(fileobj, CGFT.CGFT_AssemblyFile) + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + from llvm.ee import TargetMachine + tm = TargetMachine.new() + fileobj.write(tm.emit_assembly(self)) + if ret: + return fileobj.getvalue() + def get_or_insert_named_metadata(self, name): - return NamedMetadata(self._ptr.getOrInsertNamedMetadata(name)) + return NamedMetaData(self._ptr.getOrInsertNamedMetadata(name)) def get_named_metadata(self, name): - return NamedMetadata(self._ptr.get_named_metadata(name)) + md = self._ptr.getNamedMetadata(name) + if md: + return NamedMetaData(md) def clone(self): - return NamedMetadata(api.llvm.CloneModule(self._ptr)) + return Module(api.llvm.CloneModule(self._ptr)) class Type(llvm.Wrapper): """Represents a type, like a 32-bit integer or an 80-bit x86 float. @@ -552,6 +610,11 @@ class Type(llvm.Wrapper): Use one of the static methods to create an instance. Example: ty = Type.double() """ + _type_ = api.llvm.Type + + def __init__(self, ptr): + ptr = ptr._downcast(type(self)._type_) + super(Type, self).__init__(ptr) @staticmethod def int(bits=32): @@ -614,6 +677,8 @@ class Type(llvm.Wrapper): def opaque(name): """Create a opaque StructType""" context = api.llvm.getGlobalContext() + if not name: + raise llvm.LLVMException("Opaque type must have a non-empty name") ptr = api.llvm.StructType.create(context, name) return StructType(ptr) @@ -629,8 +694,15 @@ class Type(llvm.Wrapper): otherwise, creates a literal type.""" context = api.llvm.getGlobalContext() is_packed = False - ptr = api.llvm.StructType.create(context) - ptr.setBody(_extract_ptrs(element_tys), is_packed) + if name: + ptr = api.llvm.StructType.create(context, name) + ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) + else: + ptr = api.llvm.StructType.get(context, + llvm._extract_ptrs(element_tys), + is_packed) + + return StructType(ptr) @staticmethod @@ -646,7 +718,7 @@ class Type(llvm.Wrapper): context = api.llvm.getGlobalContext() is_packed = True ptr = api.llvm.StructType.create(context) - ptr.setBody(_extract_ptrs(element_tys), is_packed) + ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) return StructType(ptr) @staticmethod @@ -723,6 +795,7 @@ class Type(llvm.Wrapper): class IntegerType(Type): """Represents an integer type.""" + _type_ = api.llvm.IntegerType @property def width(self): @@ -731,6 +804,7 @@ class IntegerType(Type): class FunctionType(Type): """Represents a function type.""" + _type_ = api.llvm.FunctionType @property def return_type(self): @@ -746,7 +820,7 @@ class FunctionType(Type): def args(self): """An iterable that yields Type objects, representing the types of the arguments accepted by this function, in order.""" - tys = [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] + return [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] @property def arg_count(self): @@ -759,6 +833,7 @@ class FunctionType(Type): class StructType(Type): """Represents a structure type.""" + _type_ = api.llvm.StructType @property def element_count(self): @@ -798,18 +873,19 @@ class StructType(Type): @property def is_literal(self): - return self.isLiteral() + return self._ptr.isLiteral() @property def is_identified(self): - return not self.is_literal() + return not self.is_literal @property def is_opaque(self): - return self.isOpaque() + return self._ptr.isOpaque() class ArrayType(Type): """Represents an array type.""" + _type_ = api.llvm.ArrayType @property def element(self): @@ -820,6 +896,7 @@ class ArrayType(Type): return self._ptr.getNumElements() class PointerType(Type): + _type_ = api.llvm.PointerType @property def pointee(self): @@ -830,7 +907,8 @@ class PointerType(Type): return self._ptr.getAddressSpace() class VectorType(Type): - + _type_ = api.llvm.VectorType + @property def element(self): return self._ptr.getVectorElementType() @@ -840,6 +918,34 @@ class VectorType(Type): return self._ptr.getNumElements() class Value(llvm.Wrapper): + _type_ = api.llvm.Value + + + def __init__(self, builder, ptr): + assert builder is _ValueFactory + + if type(self._type_) is type: + if isinstance(ptr, self._type_): # is not downcast + casted = ptr + else: + casted = ptr._downcast(self._type_) + else: + try: + for ty in self._type_: + if isinstance(ptr, ty): # is not downcast + casted = ptr + else: + try: + casted = ptr._downcast(ty) + except ValueError: + pass + else: + break + else: + casted = ptr + except TypeError: + casted = ptr + super(Value, self).__init__(casted) def __str__(self): return str(self._ptr) @@ -875,9 +981,10 @@ class Value(llvm.Wrapper): @property def uses(self): - return map(User, self._ptr.list_use()) + return map(_make_value, self._ptr.list_use()) class User(Value): + _type_ = api.llvm.User @property def operand_count(self): @@ -886,193 +993,198 @@ class User(Value): @property def operands(self): """Yields operands of this instruction.""" - return [Value(self._ptr.getOperand(i)) + return [_make_value(self._ptr.getOperand(i)) for i in range(self.operand_count)] - def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self._ptr, i)) class Constant(User): + _type_ = api.llvm.Constant @staticmethod def null(ty): - return Value(api.llvm.Constant.getNullValue(ty._ptr)) + return _make_value(api.llvm.Constant.getNullValue(ty._ptr)) @staticmethod def all_ones(ty): - return Value(api.llvm.Constant.getAllOnesValue(ty._ptr)) + return _make_value(api.llvm.Constant.getAllOnesValue(ty._ptr)) @staticmethod def undef(ty): - return Value(api.llvm.UndefValue.get(ty._ptr)) + return _make_value(api.llvm.UndefValue.get(ty._ptr)) @staticmethod def int(ty, value): - return Value(api.llvm.ConstantInt.get(ty._ptr, value, False)) + return _make_value(api.llvm.ConstantInt.get(ty._ptr, int(value), False)) @staticmethod def int_signextend(ty, value): - return Value(api.llvm.ConstantInt.get(ty._ptr, value, True)) + return _make_value(api.llvm.ConstantInt.get(ty._ptr, int(value), True)) @staticmethod def real(ty, value): - return Value(api.llvm.ConstantFP.get(ty._ptr, value)) + return _make_value(api.llvm.ConstantFP.get(ty._ptr, float(value))) @staticmethod def string(strval): # dont_null_terminate=True - return Value(api.llvm.ConstantDataArray.getString(strval, False)) + cxt = api.llvm.getGlobalContext() + return _make_value(api.llvm.ConstantDataArray.getString(cxt, strval, False)) @staticmethod def stringz(strval): # dont_null_terminate=False - return Value(api.llvm.ConstantDataArray.getString(strval, True)) + cxt = api.llvm.getGlobalContext() + return _make_value(api.llvm.ConstantDataArray.getString(cxt, strval, True)) @staticmethod def array(ty, consts): - return Value(api.llvm.ConstantArray.get(ty._ptr, consts)) + aryty = Type.array(ty, len(consts)) + return _make_value(api.llvm.ConstantArray.get(aryty._ptr, + llvm._extract_ptrs(consts))) @staticmethod def struct(consts): # not packed - return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + return _make_value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), False)) @staticmethod def packed_struct(consts): - return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + return _make_value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), False)) @staticmethod def vector(consts): - return Value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) + return _make_value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) @staticmethod def sizeof(ty): - return Value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) + return _make_value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) def neg(self): - return Value(api.llvm.ConstantExpr.getNeg(self._ptr)) + return _make_value(api.llvm.ConstantExpr.getNeg(self._ptr)) def not_(self): - return Value(api.llvm.ConstantExpr.getNot(self._ptr)) + return _make_value(api.llvm.ConstantExpr.getNot(self._ptr)) def add(self, rhs): - return Value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) def fadd(self, rhs): - return Value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) def sub(self, rhs): - return Value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) def fsub(self, rhs): - return Value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) def mul(self, rhs): - return Value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) def fmul(self, rhs): - return Value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) def udiv(self, rhs): - return Value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) def sdiv(self, rhs): - return Value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) def fdiv(self, rhs): - return Value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) def urem(self, rhs): - return Value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) def srem(self, rhs): - return Value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) def frem(self, rhs): - return Value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) def and_(self, rhs): - return Value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) def or_(self, rhs): - return Value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) def xor(self, rhs): - return Value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) def icmp(self, int_pred, rhs): - return Value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) def fcmp(self, real_pred, rhs): - return Value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) def shl(self, rhs): - return Value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) def lshr(self, rhs): - return Value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) def ashr(self, rhs): - return Value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) def gep(self, indices): indices = llvm._extract_ptrs(indices) - return Value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) + return _make_value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) def trunc(self, ty): - return Value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty._ptr)) def sext(self, ty): - return Value(api.llvm.ConstantExpr.getSExt(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getSExt(self._ptr, ty._ptr)) def zext(self, ty): - return Value(api.llvm.ConstantExpr.getZExt(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getZExt(self._ptr, ty._ptr)) def fptrunc(self, ty): - return Value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty._ptr)) def fpext(self, ty): - return Value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty._ptr)) def uitofp(self, ty): - return Value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty._ptr)) def sitofp(self, ty): - return Value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty._ptr)) def fptoui(self, ty): - return Value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty._ptr)) def fptosi(self, ty): - return Value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty._ptr)) def ptrtoint(self, ty): - return Value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty._ptr)) def inttoptr(self, ty): - return Value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty._ptr)) def bitcast(self, ty): - return Value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty._ptr)) def select(self, true_const, false_const): - return Value(api.llvm.ConstantExpr.getSelect(self._ptr, + return _make_value(api.llvm.ConstantExpr.getSelect(self._ptr, true_const._ptr, false_const._ptr)) def extract_element(self, index): # note: self must be a _vector_ constant - return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) + return _make_value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) def insert_element(self, value, index): - return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, + return _make_value(api.llvm.ConstantExpr.getExtractElement(self._ptr, value._ptr, index._ptr)) def shuffle_vector(self, vector_b, mask): - return Value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, + return _make_value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, vector_b._ptr, mask._ptr)) class ConstantExpr(Constant): + _type_ = api.llvm.ConstantExpr + @property def opcode(self): return self._ptr.getOpcode() @@ -1094,6 +1206,8 @@ class ConstantDataVector(Constant): class ConstantInt(Constant): + _type_ = api.llvm.ConstantInt + @property def z_ext_value(self): '''Obtain the zero extended value for an integer constant value.''' @@ -1130,8 +1244,8 @@ class ConstantPointerNull(Constant): class UndefValue(Constant): pass - class GlobalValue(Constant): + _type_ = api.llvm.GlobalValue def _get_linkage(self): return self._ptr.getLinkage() @@ -1176,6 +1290,7 @@ class GlobalValue(Constant): class GlobalVariable(GlobalValue): + _type_ = api.llvm.GlobalVariable @staticmethod def new(module, ty, name, addrspace=0): @@ -1183,7 +1298,7 @@ class GlobalVariable(GlobalValue): external_linkage = linkage.ExternalLinkage tlmode = api.llvm.GlobalVariable.ThreadLocalMode not_threadlocal = tlmode.NotThreadLocal - gv = api.llvm.GlobalVariablel.new(module._ptr, + gv = api.llvm.GlobalVariable.new(module._ptr, ty._ptr, False, # is constant external_linkage, @@ -1192,22 +1307,23 @@ class GlobalVariable(GlobalValue): None, # insert before not_threadlocal, addrspace) - return GlobalVariable(gv) + return _make_value(gv) @staticmethod def get(module, name): - gv = GlobalVariable(module._ptr.getNamedGlobal(name)) + gv = _make_value(module._ptr.getNamedGlobal(name)) if not gv: llvm.LLVMException("no global named `%s`" % name) return gv def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() def _get_initializer(self): if not self._ptr.hasInitializer(): return None - return Constant(self._ptr.getInitializer()) + return _make_value(self._ptr.getInitializer()) def _set_initializer(self, const): self._ptr.setInitializer(const._ptr) @@ -1235,21 +1351,25 @@ class GlobalVariable(GlobalValue): thread_local = property(_get_thread_local, _set_thread_local) class Argument(Value): + _type_ = api.llvm.Argument def add_attribute(self, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttr(attrs) def remove_attribute(self, attr): - attrbldr = api.llvm.AttrBuilder() + 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): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAlignmentAttr(align) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttr(attrs) @@ -1261,6 +1381,7 @@ class Argument(Value): _set_alignment) class Function(GlobalValue): + _type_ = api.llvm.Function @staticmethod def new(module, func_ty, name): @@ -1277,11 +1398,12 @@ class Function(GlobalValue): @staticmethod def intrinsic(module, intrinsic_id, types): fn = api.llvm.Intrinsic.getDeclaration(module._ptr, - intrinsic_id, - types) - return Function(fn) + intrinsic_id, + llvm._extract_ptrs(types)) + return _make_value(fn) def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() @property @@ -1310,13 +1432,14 @@ class Function(GlobalValue): def _set_does_not_throw(self,value): assert value - self._ptr.setDoesNotThow() + self._ptr.setDoesNotThrow() does_not_throw = property(_get_does_not_throw, _set_does_not_throw) @property def args(self): - return self._ptr.getArgumentList() + args = self._ptr.getArgumentList() + return map(_make_value, args) @property def basic_block_count(self): @@ -1324,25 +1447,27 @@ class Function(GlobalValue): @property def entry_basic_block(self): - return self._ptr.getEntryBlock() + assert self.basic_block_count + return _make_value(self._ptr.getEntryBlock()) def append_basic_block(self, name): context = api.llvm.getGlobalContext() bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) - return BasicBlock(bb) + return _make_value(bb) @property def basic_blocks(self): - return self._ptr.getBasicBlockList() + return map(_make_value, self._ptr.getBasicBlockList()) def viewCFG(self): return self._ptr.viewCFG() def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self._ptr, attr) + self._ptr.addFnAttr(attr) def remove_attribute(self, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeFnAttr(attrs) @@ -1356,25 +1481,30 @@ class Function(GlobalValue): # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. - return api.llvm.verifyFunction() + actions = api.llvm.VerifierFailureAction + return api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) #===----------------------------------------------------------------------=== # InlineAsm #===----------------------------------------------------------------------=== class InlineAsm(Value): + _type_ = api.llvm.InlineAsm + @staticmethod def get(functype, asm, constrains, side_effect=False, align_stack=False, dialect=api.llvm.InlineAsm.AsmDialect.AD_ATT): - ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, contrains, side_effect, - align_stack, dialect) - return InlineAsm(ilasm) + ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, constrains, + side_effect, align_stack, dialect) + return _make_value(ilasm) #===----------------------------------------------------------------------=== # MetaData #===----------------------------------------------------------------------=== class MetaData(Value): + _type_ = api.llvm.MDNode + @staticmethod def get(module, values): ''' @@ -1382,13 +1512,15 @@ class MetaData(Value): ''' context = api.llvm.getGlobalContext() ptr = api.llvm.MDNode.get(context, llvm._extract_ptrs(values)) - return MetaData(ptr) + return _make_value(ptr) @staticmethod def get_named_operands(module, name): - namedmd = module.get_named_metadata(name)._ptr - return [MetaData(namedmd.getOperand(i)) - for i in namedmd.getNumOperands()] + namedmd = module.get_named_metadata(name) + if not namedmd: + return [] + return [_make_value(namedmd._ptr.getOperand(i)) + for i in range(namedmd._ptr.getNumOperands())] @staticmethod def add_named_operand(module, name, operand): @@ -1397,20 +1529,28 @@ class MetaData(Value): @property def operand_count(self): - return self._ptr.getOperand() + return self._ptr.getNumOperands() @property def operands(self): """Yields operands of this metadata.""" - return [Value(self._ptr.getOperand(i)) for i in self.operand_count] - + res = [] + for i in range(self.operand_count): + op = self._ptr.getOperand(i) + if op is None: + res.append(None) + else: + res.append(_make_value(op)) + return res class MetaDataString(Value): + _type_ = api.llvm.MDString + @staticmethod def get(module, s): context = api.llvm.getGlobalContext() ptr = api.llvm.MDString.get(context, s) - return MetaDataString(ptr) + return _make_value(ptr) @property def string(self): @@ -1419,6 +1559,7 @@ class MetaDataString(Value): class NamedMetaData(llvm.Wrapper): + @staticmethod def get_or_insert(mod, name): return mod.get_or_insert_named_metadata(name) @@ -1446,10 +1587,11 @@ class NamedMetaData(llvm.Wrapper): #===----------------------------------------------------------------------=== class Instruction(User): + _type_ = api.llvm.Instruction @property def basic_block(self): - return BasicBlock(self._ptr.getParent()) + return _make_value(self._ptr.getParent()) @property def is_terminator(self): @@ -1517,6 +1659,7 @@ class Instruction(User): class CallOrInvokeInstruction(Instruction): + _type_ = api.llvm.CallInst, api.llvm.InvokeInst def _get_cc(self): return self._ptr.getCallingConv() @@ -1527,19 +1670,22 @@ class CallOrInvokeInstruction(Instruction): calling_convention = property(_get_cc, _set_cc) def add_parameter_attribute(self, idx, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttribute(idx, attrs) def remove_parameter_attribute(self, idx, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeAttribute(idx, attrs) def set_parameter_alignment(self, idx, align): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAlignmentAttr(align) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttribute(idx, attrs) @@ -1547,7 +1693,7 @@ class CallOrInvokeInstruction(Instruction): def _get_called_function(self): function = self._ptr.getCalledFunction() if function: # Return value can be None on indirect call/invoke - return Value(function) + return _make_value(function) def _set_called_function(self, function): self._ptr.setCalledFunction(function) @@ -1556,6 +1702,7 @@ class CallOrInvokeInstruction(Instruction): class PHINode(Instruction): + _type_ = api.llvm.PHINode @property def incoming_count(self): @@ -1565,10 +1712,10 @@ class PHINode(Instruction): self._ptr.addIncoming(value._ptr, block._ptr) def get_incoming_value(self, idx): - return self._ptr.getIncomingValue(idx) + return _make_value(self._ptr.getIncomingValue(idx)) def get_incoming_block(self, idx): - return self._ptr.getIncomingBlock(idx) + return _make_value(self._ptr.getIncomingBlock(idx)) class SwitchInstruction(Instruction): @@ -1582,36 +1729,108 @@ class CompareInstruction(Instruction): @property def predicate(self): return self._ptr.getPredicate() - - #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== class BasicBlock(Value): + _type_ = api.llvm.BasicBlock def insert_before(self, name): context = api.llvm.getGlobalContext() ptr = api.llvm.BasicBlock.Create(context, name, self.function._ptr, self._ptr) - return BasicBlock(ptr) + return _make_value(ptr) def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() @property def function(self): - return Function(self._ptr.getParent()) + return _make_value(self._ptr.getParent()) @property def instructions(self): - return map(Value, self._ptr.getInstList()) + return map(_make_value, self._ptr.getInstList()) +#===----------------------------------------------------------------------=== +# Value factory method +#===----------------------------------------------------------------------=== + + +class _ValueFactory(object): + cache = weakref.WeakValueDictionary() + + # value ID -> class map + class_for_valueid = { + VALUE_ARGUMENT : Argument, + VALUE_BASIC_BLOCK : BasicBlock, + VALUE_FUNCTION : Function, + VALUE_GLOBAL_ALIAS : GlobalValue, + VALUE_GLOBAL_VARIABLE : GlobalVariable, + VALUE_UNDEF_VALUE : UndefValue, + VALUE_CONSTANT_EXPR : ConstantExpr, + VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, + VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, + VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, + VALUE_CONSTANT_INT : ConstantInt, + VALUE_CONSTANT_FP : ConstantFP, + VALUE_CONSTANT_ARRAY : ConstantArray, + VALUE_CONSTANT_STRUCT : ConstantStruct, + VALUE_CONSTANT_VECTOR : ConstantVector, + VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, + VALUE_MD_NODE : MetaData, + VALUE_MD_STRING : MetaDataString, + VALUE_INLINE_ASM : InlineAsm, + VALUE_INSTRUCTION + OPCODE_PHI : PHINode, + VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, + VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, + VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, + VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, + VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction + } + + @classmethod + def build(cls, ptr): + # try to look in the cache + addr = ptr._capsule.pointer + try: + obj = cls.cache[addr] + return obj + except KeyError: + pass + # find class by value id + id = ptr.getValueID() + ctorcls = cls.class_for_valueid.get(id) + if not ctorcls: + if id > VALUE_INSTRUCTION: # "generic" instruction + ctorcls = Instruction + else: # "generic" value + ctorcls = Value + # cache the obj + obj = ctorcls(_ValueFactory, ptr) + cls.cache[addr] = obj + return obj + + @classmethod + def delete(cls, ptr): + del cls.cache[ptr._capsule.pointer] + +def _make_value(ptr): + return _ValueFactory.build(ptr) #===----------------------------------------------------------------------=== # Builder #===----------------------------------------------------------------------=== +_atomic_orderings = { 'unordered' : api.llvm.AtomicOrdering.Unordered, + 'monotonic' : api.llvm.AtomicOrdering.Monotonic, + 'acquire' : api.llvm.AtomicOrdering.Acquire, + 'release' : api.llvm.AtomicOrdering.Release, + 'acq_rel' : api.llvm.AtomicOrdering.AcquireRelease, + 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent} + class Builder(llvm.Wrapper): @staticmethod @@ -1628,7 +1847,7 @@ class Builder(llvm.Wrapper): # Instruction list won't be long anyway, # Does not matter much to build a list of all instructions - instrs = bblk._ptr.getInstList() + instrs = bblk.instructions if instrs: self.position_before(instrs[0]) else: @@ -1650,150 +1869,163 @@ class Builder(llvm.Wrapper): @property def basic_block(self): """The basic block where the builder is positioned.""" - return BasicBlock(self._ptr.GetInsertBlock()) + return _make_value(self._ptr.GetInsertBlock()) # terminator instructions + def _guard_terminators(self): + if __debug__: + import warnings + for instr in self.basic_block.instructions: + if instr.is_terminator: + warnings.warn("BasicBlock can only have one terminator") def ret_void(self): - return Value(self._ptr.CreateRetVoid()) + self._guard_terminators() + return _make_value(self._ptr.CreateRetVoid()) def ret(self, value): - return Value(self._ptr.CreateRet(value._ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateRet(value._ptr)) def ret_many(self, values): + self._guard_terminators() values = llvm._extract_ptrs(values) - return Value(self._ptr.CreateAggregateRet(values, len(values))) + return _make_value(self._ptr.CreateAggregateRet(values, len(values))) def branch(self, bblk): - if __debug__: - for instr in self.basic_block.instructions: - assert not instr.is_terminator, "BasicBlock can only have one terminator" - return Value(self._ptr.CreateBr(bblk._ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateBr(bblk._ptr)) def cbranch(self, if_value, then_blk, else_blk): - return Value(self._ptr.CreateCondBr(if_value._ptr, + self._guard_terminators() + return _make_value(self._ptr.CreateCondBr(if_value._ptr, then_blk._ptr, else_blk._ptr)) def switch(self, value, else_blk, n=10): - return Value(self._ptr.CreateSwitch(self.value._ptr, - self.else_blk._ptr, - n)) + self._guard_terminators() + return _make_value(self._ptr.CreateSwitch(value._ptr, + else_blk._ptr, + n)) def invoke(self, func, args, then_blk, catch_blk, name=""): - return Value(self._ptr.CreateInvoke(self.func._ptr, - self.then_blk._ptr, - self.catch_blk._ptr, - args)) + self._guard_terminators() + return _make_value(self._ptr.CreateInvoke(func._ptr, + then_blk._ptr, + catch_blk._ptr, + llvm._extract_ptrs(args))) def unreachable(self): - return Value(self._ptr.CreateUnreachable()) + self._guard_terminators() + return _make_value(self._ptr.CreateUnreachable()) # arithmethic, bitwise and logical def add(self, lhs, rhs, name=""): - return Value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) def fadd(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) def sub(self, lhs, rhs, name=""): - return Value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) def fsub(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) def mul(self, lhs, rhs, name=""): - return Value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) def fmul(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) def udiv(self, lhs, rhs, name=""): - return Value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) def sdiv(self, lhs, rhs, name=""): - return Value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) def fdiv(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) def urem(self, lhs, rhs, name=""): - return Value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) def srem(self, lhs, rhs, name=""): - return Value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) def frem(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) def shl(self, lhs, rhs, name=""): - return Value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) def lshr(self, lhs, rhs, name=""): - return Value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) def ashr(self, lhs, rhs, name=""): - return Value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) def and_(self, lhs, rhs, name=""): - return Value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) def or_(self, lhs, rhs, name=""): - return Value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) def xor(self, lhs, rhs, name=""): - return Value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) def neg(self, val, name=""): - return Value(self._ptr.CreateNeg(val._ptr, name)) + return _make_value(self._ptr.CreateNeg(val._ptr, name)) def not_(self, val, name=""): - return Value(self._ptr.CreateNot(val._ptr, name)) + return _make_value(self._ptr.CreateNot(val._ptr, name)) # memory def malloc(self, ty, name=""): context = api.llvm.getGlobalContext() - intty = api.llvm.Type.getInt32Ty(context) - sizeof = api.llvm.ConstantExpr.getSizeOf(ty) - zero = api.llvm.ConstantInt.get(intty, 0) - # XXX: how do I know when to insert? - # assume to end of block for now - inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, - intty, - ty._ptr, - sizeof, - zero, - None, - name) - return Value(inst) - + allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) + ity = allocsz.getType() + malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + ity, + ty._ptr, + allocsz, + None, + None, + "") + inst = self._ptr.Insert(malloc, name) + return _make_value(inst) + def malloc_array(self, ty, size, name=""): - sizeof = api.llvm.ConstantExpr.getSizeOf(ty) - # XXX: how do I know when to insert? - # assume to end of block for now - inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, - size.type._ptr, - ty._ptr, - sizeof, - size._ptr, - None, - name) - return Value(inst) + context = api.llvm.getGlobalContext() + allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) + ity = allocsz.getType() + malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + ity, + ty._ptr, + allocsz, + size._ptr, + None, + "") + inst = self._ptr.Insert(malloc, name) + return _make_value(inst) def alloca(self, ty, name=""): - zero = api.llvm.ConstantInt.get(intty, 0) - return Value(self._ptr.CreateAlloca(ty._ptr, zero, name)) + intty = Type.int() + zero = api.llvm.ConstantInt.get(intty._ptr, 0) + return _make_value(self._ptr.CreateAlloca(ty._ptr, zero, name)) def alloca_array(self, ty, size, name=""): - return Value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) + return _make_value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) def free(self, ptr): - return Value(api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr)) + free = api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr) + inst = self._ptr.Insert(free) + return _make_value(inst) def load(self, ptr, name="", align=0, volatile=False, invariant=False): - inst = Value(self._ptr.CreateLoad(ptr._ptr, name)) + inst = _make_value(self._ptr.CreateLoad(ptr._ptr, name)) if align: inst._ptr.setAlignment(align) if volatile: @@ -1805,7 +2037,7 @@ class Builder(llvm.Wrapper): return inst def store(self, value, ptr, align=0, volatile=False): - inst = Value(self._ptr.CreateStore(value._ptr, ptr._ptr)) + inst = _make_value(self._ptr.CreateStore(value._ptr, ptr._ptr)) if align: inst._ptr.setAlignment(align) if volatile: @@ -1821,118 +2053,119 @@ class Builder(llvm.Wrapper): ret = self._ptr.CreateGEP(ptr._ptr, llvm._extract_ptrs(indices), name) - return Value(ret) + return _make_value(ret) # casts and extensions def trunc(self, value, dest_ty, name=""): - return Value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) def zext(self, value, dest_ty, name=""): - return Value(self._ptr.CreateZext(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateZExt(value._ptr, dest_ty._ptr, name)) def sext(self, value, dest_ty, name=""): - return Value(self._ptr.CreateSext(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateSExt(value._ptr, dest_ty._ptr, name)) def fptoui(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) def fptosi(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) def uitofp(self, value, dest_ty, name=""): - return Value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) def sitofp(self, value, dest_ty, name=""): - return Value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) def fptrunc(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) def fpext(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) def ptrtoint(self, value, dest_ty, name=""): - return Value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) def inttoptr(self, value, dest_ty, name=""): - return Value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) def bitcast(self, value, dest_ty, name=""): - return Value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) # comparisons def icmp(self, ipred, lhs, rhs, name=""): - return Value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) def fcmp(self, rpred, lhs, rhs, name=""): - return Value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) # misc def extract_value(self, retval, idx, name=""): - return Value(self._ptr.CreateExtractValue(retval._ptr, [idx], name)) + return _make_value(self._ptr.CreateExtractValue(retval._ptr, [idx], name)) # obsolete synonym for extract_value getresult = extract_value def insert_value(self, retval, rhs, idx, name=""): - return Value(self._ptr.CreateInsertValue(retval._ptr, + return _make_value(self._ptr.CreateInsertValue(retval._ptr, rhs._ptr, [idx], name)) def phi(self, ty, name=""): - return Value(self._ptr.CreatePHI(ty._ptr, 2, name)) + return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name)) def call(self, fn, args, name=""): err_template = 'Argument type mismatch: expected %s but got %s' + for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): if t != v.type: raise TypeError(err_template % (t, v.type)) arg_ptrs = llvm._extract_ptrs(args) - return Value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) + return _make_value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) def select(self, cond, then_value, else_value, name=""): - return Value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, + return _make_value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, else_value._ptr, name)) def vaarg(self, list_val, ty, name=""): - return Value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) + return _make_value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) def extract_element(self, vec_val, idx_val, name=""): - return Value(self._ptr.CreateExtractElement(vec_val._ptr, - idx_val_.ptr, - name)) + return _make_value(self._ptr.CreateExtractElement(vec_val._ptr, + idx_val._ptr, + name)) def insert_element(self, vec_val, elt_val, idx_val, name=""): - return Value(self._ptr.CreateExtractElement(vec_val._ptr, - elt_val._ptr, - idx_val_.ptr, - name)) + return _make_value(self._ptr.CreateInsertElement(vec_val._ptr, + elt_val._ptr, + idx_val._ptr, + name)) def shuffle_vector(self, vecA, vecB, mask, name=""): - return Value(self._ptr.CreateShuffleVector(vecA._ptr, - vecB._ptr, - mask._ptr, - name)) + return _make_value(self._ptr.CreateShuffleVector(vecA._ptr, + vecB._ptr, + mask._ptr, + name)) # atomics def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): - return Value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, + return _make_value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, old._ptr, new._ptr, - ordering, + _atomic_orderings[ordering], _sync_scope(crossthread))) def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): op_dict = dict((k.lower(), v) - for k, v in vars(api.llvm.AtomicRMWInst.BinOp)) + for k, v in vars(api.llvm.AtomicRMWInst.BinOp).items()) op = op_dict[op] - return Value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, - ordering, + return _make_value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, + _atomic_orderings[ordering], _sync_scope(crossthread))) def atomic_xchg(self, *args, **kwargs): @@ -1970,21 +2203,22 @@ class Builder(llvm.Wrapper): def atomic_load(self, ptr, ordering, align=1, crossthread=True, volatile=False, name=""): - inst = self._ptr.load(ptr, align=align, volatile=volatile, name=name) - inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + inst = self.load(ptr, align=align, volatile=volatile, name=name) + inst._ptr.setAtomic(_atomic_orderings[ordering], + _sync_scope(crossthread)) return inst def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, volatile=False): - inst = self._ptr.store(ptr, value, align=align, volatile=volatile, - name=name) - inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + inst = self.store(value, ptr, align=align, volatile=volatile) + inst._ptr.setAtomic(_atomic_orderings[ordering], + _sync_scope(crossthread)) return inst def fence(self, ordering, crossthread=True): - return Value(self._ptr.CreateFence(ordering, - _sync_scope(crossthread))) + return _make_value(self._ptr.CreateFence(_atomic_orderings[ordering], + _sync_scope(crossthread))) def _sync_scope(crossthread): if crossthread: @@ -2000,12 +2234,13 @@ def load_library_permanently(filename): path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" with contextlib.closing(StringIO()) as errmsg: - failed = api.llvm.sys.LoadLibraryPermanently(filename, errmsg) + failed = api.llvm.sys.DynamicLibrary.LoadPermanentLibrary(filename, + errmsg) if failed: raise llvm.LLVMException(errmsg.getvalue()) def inline_function(call): - info = api.llvm.InlineFunctionInfo() + info = api.llvm.InlineFunctionInfo.new() return api.llvm.InlineFunction(call._ptr, info) def parse_environment_options(progname, envname): diff --git a/llvm/ee.py b/llvm/ee.py index 8523998..8598ad9 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -38,8 +38,8 @@ import contextlib import llvm from llvm import core -from llvmpy import api - +from llvm.passes import TargetData, TargetTransformInfo +from llvmpy import api, extra #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== @@ -63,20 +63,20 @@ class GenericValue(llvm.Wrapper): @staticmethod def int(ty, intval): - ptr = api.llvm.CreateInt(ty._ptr, intval, False) + ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), False) return GenericValue(ptr) @staticmethod def int_signed(ty, intval): - ptr = api.llvm.CreateInt(ty._ptr, intval, True) + ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), True) return GenericValue(ptr) @staticmethod def real(ty, floatval): if str(ty) == 'float': - ptr = api.llvm.CreateFloat(floatval) + ptr = api.llvm.GenericValue.CreateFloat(float(floatval)) elif str(ty) == 'double': - ptr = api.llvm.CreateDouble(floatval) + ptr = api.llvm.GenericValue.CreateDouble(float(floatval)) else: raise Exception('Unreachable') return GenericValue(ptr) @@ -91,7 +91,7 @@ class GenericValue(llvm.Wrapper): `addr` is an integer representing an address. ''' - ptr = api.llvm.CreatePointer(addr) + ptr = api.llvm.GenericValue.CreatePointer(int(addr)) return GenericValue(ptr) def as_int(self): @@ -101,7 +101,7 @@ class GenericValue(llvm.Wrapper): return self._ptr.toSignedInt() def as_real(self, ty): - return self._ptr.toFloat() + return self._ptr.toFloat(ty._ptr) def as_pointer(self): return self._ptr.toPointer() @@ -113,7 +113,7 @@ class GenericValue(llvm.Wrapper): class EngineBuilder(llvm.Wrapper): @staticmethod def new(module): - ptr = api.llvm.EngineBuilder.new(module) + ptr = api.llvm.EngineBuilder.new(module._ptr) return EngineBuilder(ptr) def force_jit(self): @@ -158,10 +158,10 @@ class EngineBuilder(llvm.Wrapper): ''' if args: triple, march, mcpu, mattrs = args - ptr = self._ptr.select_target(triple, march, mcpu, + ptr = self._ptr.selectTarget(triple, march, mcpu, mattrs.split(',')) else: - ptr = self._ptr.select_target() + ptr = self._ptr.selectTarget() return TargetMachine(ptr) @@ -182,7 +182,8 @@ class ExecutionEngine(llvm.Wrapper): self._ptr.DisableLazyCompilation(disabled) def run_function(self, fn, args): - return self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + ptr = self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + return GenericValue(ptr) def get_pointer_to_function(self, fn): return self._ptr.getPointerToFunction(fn._ptr) @@ -195,13 +196,13 @@ class ExecutionEngine(llvm.Wrapper): self._ptr.addGlobalMapping(gvar._ptr, addr) def run_static_ctors(self): - self._ptr.runStaticConstructorDestructors(False) + self._ptr.runStaticConstructorsDestructors(False) def run_static_dtors(self): - self._ptr.runStaticConstructorDestructors(True) + self._ptr.runStaticConstructorsDestructors(True) def free_machine_code_for(self, fn): - self.freeMachineCodeForFunction(fn._ptr) + self._ptr.freeMachineCodeForFunction(fn._ptr) def add_module(self, module): self._ptr.addModule(module._ptr) @@ -222,17 +223,17 @@ def print_registered_targets(): ''' Note: print directly to stdout ''' - llvm.TargetRegistry.printRegisteredTargetsForVersion() + api.llvm.TargetRegistry.printRegisteredTargetsForVersion() def get_host_cpu_name(): '''return the string name of the host CPU ''' - return llvm.sys.getHostCPUName() + return api.llvm.sys.getHostCPUName() def get_default_triple(): '''return the target triple of the host in str-rep ''' - return llvm.sys.getDefaultTargetTriple() + return api.llvm.sys.getDefaultTargetTriple() class TargetMachine(llvm.Wrapper): @@ -243,20 +244,20 @@ class TargetMachine(llvm.Wrapper): triple = get_default_triple() if not cpu: cpu = get_host_cpu_name() - with contextlib.closing(StringIO) as error: + with contextlib.closing(StringIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(triple, error) if not target: raise llvm.LLVMException(error) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") - target_options = api.llvm.TargetOptions() + target_options = api.llvm.TargetOptions.new() tm = target.createTargetMachine(triple, cpu, features, target_options, api.llvm.Reloc.Model.Default, cm, opt) if not tm: raise llvm.LLVMException("Cannot create target machine") - return TargetMachine(ptr) + return TargetMachine(tm) @staticmethod def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): @@ -272,24 +273,25 @@ class TargetMachine(llvm.Wrapper): use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` ''' triple = api.llvm.Triple.new() - with contextlib.closing(StringIO) as error: - target = api.llvm.TargetMachine.lookupTarget(arch, triple, error) + with contextlib.closing(StringIO()) as error: + target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error) if not target: raise llvm.LLVMException(error) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") - target_options = api.llvm.TargetOptions() + target_options = api.llvm.TargetOptions.new() tm = target.createTargetMachine(str(triple), cpu, features, target_options, api.llvm.Reloc.Model.Default, cm, opt) if not tm: raise llvm.LLVMException("Cannot create target machine") - return TargetMachine(ptr) + return TargetMachine(tm) def _emit_file(self, module, cgft): pm = api.llvm.PassManager.new() - os = api.extra.make_raw_ostream_for_printing() + os = extra.make_raw_ostream_for_printing() + pm.add(api.llvm.DataLayout.new(str(self.target_data))) failed = self._ptr.addPassesToEmitFile(pm, os, cgft) pm.run(module) return os.str() @@ -298,19 +300,19 @@ class TargetMachine(llvm.Wrapper): '''returns byte string of the module as assembly code of the target machine ''' CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._emit_file(module, CGFT.CGFT_AssemblyFile) + return self._emit_file(module._ptr, CGFT.CGFT_AssemblyFile) def emit_object(self, module): '''returns byte string of the module as native code of the target machine ''' CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._emit_file(module, CGFT.CGFT_ObjectFile) + return self._emit_file(module._ptr, CGFT.CGFT_ObjectFile) @property def target_data(self): '''get target data of this machine ''' - return TargetData(self._ptr.getDataLayout) + return TargetData(self._ptr.getDataLayout()) @property def target_name(self): diff --git a/llvm/passes.py b/llvm/passes.py index 545a19d..36e7d97 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -46,7 +46,7 @@ from llvmpy import api class PassManagerBuilder(llvm.Wrapper): @staticmethod def new(): - return PassManagerBuilder(api.llvm.PassManagerBuilder()) + return PassManagerBuilder(api.llvm.PassManagerBuilder.new()) def populate(self, pm): if isinstance(pm, FunctionPassManager): @@ -59,7 +59,7 @@ class PassManagerBuilder(llvm.Wrapper): return self._ptr.OptLevel @opt_level.setter - def _set_opt_level(self, optlevel): + def opt_level(self, optlevel): self._ptr.OptLevel = optlevel @property @@ -67,7 +67,7 @@ class PassManagerBuilder(llvm.Wrapper): return self._ptr.SizeLevel @size_level.setter - def _set_size_level(self, sizelevel): + def size_level(self, sizelevel): self._ptr.SizeLevel = sizelevel @property @@ -75,8 +75,9 @@ class PassManagerBuilder(llvm.Wrapper): return self._ptr.Vectorize @vectorize.setter - def _set_vectorize(self, enable): - self._ptr.Vectroize = enable + def vectorize(self, enable): + self._ptr.Vectorize = enable + @property def loop_vectorize(self): @@ -142,10 +143,11 @@ class PassManager(llvm.Wrapper): def _add_pass(self, pass_name): passreg = api.llvm.PassRegistry.getPassRegistry() - a_pass = passreg.getPassInfo(pass_name) + a_pass = passreg.getPassInfo(pass_name).createPass() if not a_pass: assert pass_name not in PASSES, "Registered but not found?" raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) + print a_pass self._ptr.add(a_pass) def run(self, module): @@ -155,17 +157,17 @@ class FunctionPassManager(PassManager): @staticmethod def new(module): - ptr = api.llvm.FunctionPassManager.new(module) + ptr = api.llvm.FunctionPassManager.new(module._ptr) return FunctionPassManager(ptr) def __init__(self, ptr): PassManager.__init__(self, ptr) def initialize(self): - self._ptr.doInitization() + self._ptr.doInitialization() def run(self, fn): - return self._ptr.run(fn) + return self._ptr.run(fn._ptr) def finalize(self): self._ptr.doFinalization() @@ -187,7 +189,7 @@ class Pass(llvm.Wrapper): The error cannot be caught. ''' passreg = api.llvm.PassRegistry.getPassRegistry() - a_pass = passreg.getPassInfo(pass_name) + a_pass = passreg.getPassInfo(name).createPass() p = Pass(a_pass) p.__name = name return p @@ -196,7 +198,10 @@ class Pass(llvm.Wrapper): def name(self): '''The name used in PassRegistry. ''' - return p.__name + try: + return self.__name + except AttributeError: + return @property def description(self): @@ -235,7 +240,8 @@ class TargetData(Pass): @property def target_integer_type(self): - return self._ptr.core.IntegerType(core.Type.getInt32Ty()) + context = api.llvm.getGlobalContext() + return api.llvm.IntegerType(api.llvm.Type.getInt32Ty(context)) def size(self, ty): return self._ptr.getTypeSizeInBits(ty._ptr) @@ -256,15 +262,15 @@ class TargetData(Pass): if isinstance(ty_or_gv, core.Type): return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr) elif isinstance(ty_or_gv, core.GlobalVariable): - return self._ptr._core.getPreferredAlignment(ty_or_gv._ptr) + return self._ptr.getPreferredAlignment(ty_or_gv._ptr) else: raise core.LLVMException("argument is neither a type nor a global variable") def element_at_offset(self, ty, ofs): - return self._ptr.getStructLayout(ty).getElementContainingOffset(ofs) + return self._ptr.getStructLayout(ty._ptr).getElementContainingOffset(ofs) def offset_of_element(self, ty, el): - return self._ptr.getStructLayout(ty).getElementOffset(el) + return self._ptr.getStructLayout(ty._ptr).getElementOffset(el) #===----------------------------------------------------------------------=== # Target Library Info @@ -277,6 +283,19 @@ class TargetLibraryInfo(Pass): ptr = api.llvm.TargetLibraryInfo.new(triple) return TargetLibraryInfo(ptr) +#===----------------------------------------------------------------------=== +# Target Transformation Info +#===----------------------------------------------------------------------=== + +class TargetTransformInfo(Pass): + @staticmethod + def new(targetmachine): + scalartti = targetmachine._ptr.getScalarTargetTransformInfo() + vectortti = targetmachine._ptr.getVectorTargetTransformInfo() + ptr = api.llvm.TargetTransformInfo.new(scalartti, vectortti) + return TargetTransformInfo(ptr) + + #===----------------------------------------------------------------------=== # Helpers #===----------------------------------------------------------------------=== diff --git a/llvm/tbaa.py b/llvm/tbaa.py new file mode 100644 index 0000000..b510ce2 --- /dev/null +++ b/llvm/tbaa.py @@ -0,0 +1,51 @@ +from llvm.core import * + +class TBAABuilder(object): + '''Simplify creation of TBAA metadata. + + Each TBAABuidler object operates on a module. + User can create multiple TBAABuilder on a module + ''' + + def __init__(self, module, rootid): + ''' + module --- the module to use. + root --- string name to identify the TBAA root. + ''' + self.__module = module + self.__rootid = rootid + self.__rootmd = self.__new_md(rootid) + + @classmethod + def new(cls, module, rootid): + return cls(module, rootid) + + def get_node(self, name, parent=None, const=False): + '''Returns a MetaData object representing a TBAA node. + + Use loadstore_instruction.set_metadata('tbaa', node) to + bind a type to a memory. + ''' + parent = parent or self.root + const = Constant.int(Type.int(), int(bool(const))) + return self.__new_md(name, parent, const) + + @property + def module(self): + return self.__module + + @property + def root(self): + return self.__rootmd + + @property + def root_name(self): + return self.__rootid + + def __new_md(self, *args): + contents = list(args) + for i, v in enumerate(contents): + if isinstance(v, str): + contents[i] = MetaDataString.get(self.module, v) + return MetaData.get(self.module, contents) + diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py new file mode 100644 index 0000000..5b26e39 --- /dev/null +++ b/llvm/test_llvmpy.py @@ -0,0 +1,1243 @@ +""" +LLVM tests +""" +import os +import sys +import math +import shutil +import unittest +import subprocess +import tempfile +import contextlib + +is_py3k = bool(sys.version_info[0] == 3) +BITS = tuple.__itemsize__ * 8 + +if is_py3k: + from io import StringIO +else: + from cStringIO import StringIO + + +import llvm +from llvm.core import (Module, Type, GlobalVariable, Function, Builder, + Constant, MetaData, MetaDataString, inline_function) +from llvm.ee import EngineBuilder +import llvm.core as lc +import llvm.passes as lp +import llvm.ee as le +import llvmpy + + +tests = [] + + +# --------------------------------------------------------------------------- + +if sys.version_info[:2] <= (2, 6): + # create custom TestCase + class TestCase(unittest.TestCase): + def assertIn(self, item, container): + self.assertTrue(item in container) + + def assertNotIn(self, item, container): + self.assertFalse(item in container) + + def assertLess(self, a, b): + self.assertTrue(a < b) + + def assertIs(self, a, b): + self.assertTrue(a is b) + + @contextlib.contextmanager + def assertRaises(self, exc): + try: + yield + except exc: + pass + else: + raise self.failureException("Did not raise %s" % exc) + +else: + TestCase = unittest.TestCase + + +# --------------------------------------------------------------------------- + +class TestAsm(TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + def test_asm(self): + # create a module + m = Module.new('module1') + m.add_global_variable(Type.int(), 'i') + + # write it's assembly representation to a file + asm = str(m) + + testasm_ll = os.path.join(self.tmpdir, 'testasm.ll') + with open(testasm_ll, "w") as fout: + fout.write(asm) + + # read it back into a module + with open(testasm_ll) as fin: + m2 = Module.from_assembly(fin) + # The default `m.id` is ''. + m2.id = m.id # Copy the name from `m` + + self.assertEqual(str(m2).strip(), asm.strip()) + + def test_bitcode(self): + # create a module + m = Module.new('module1') + m.add_global_variable(Type.int(), 'i') + + # write it's assembly representation to a file + asm = str(m) + + testasm_bc = os.path.join(self.tmpdir, 'testasm.bc') + with open(testasm_bc, "wb") as fout: + m.to_bitcode(fout) + + # read it back into a module + with open(testasm_bc, "rb") as fin: + m2 = Module.from_bitcode(fin) + # The default `m.id` is ''. + m2.id = m.id # Copy the name from `m` + + self.assertEqual(str(m2).strip(), asm.strip()) + +tests.append(TestAsm) + +# --------------------------------------------------------------------------- + +class TestAttr(TestCase): + def make_module(self): + test_module = """ + define void @sum(i32*, i32*) { + entry: + ret void + } + """ + return Module.from_assembly(StringIO(test_module)) + + def test_align(self): + m = self.make_module() + f = m.get_function_named('sum') + f.args[0].alignment = 16 + self.assert_("align 16" in str(f)) + self.assertEqual(f.args[0].alignment, 16) + +tests.append(TestAttr) + +# --------------------------------------------------------------------------- + +class TestAtomic(TestCase): + orderings = ['unordered', 'monotonic', 'acquire', + 'release', 'acq_rel', 'seq_cst'] + + atomic_op = ['xchg', 'add', 'sub', 'and', 'nand', 'or', 'xor', + 'max', 'min', 'umax', 'umin'] + + def test_atomic_cmpxchg(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + old = bldr.load(ptr) + new = Constant.int(Type.int(), 1234) + + for ordering in self.orderings: + inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) + self.assertEqual(ordering, str(inst).strip().split(' ')[-1]) + + inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) + self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) + + def test_atomic_rmw(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + old = bldr.load(ptr) + val = Constant.int(Type.int(), 1234) + + for ordering in self.orderings: + inst = bldr.atomic_rmw('xchg', ptr, val, ordering) + self.assertEqual(ordering, str(inst).split(' ')[-1]) + + for op in self.atomic_op: + inst = bldr.atomic_rmw(op, ptr, val, ordering) + self.assertEqual(op, str(inst).strip().split(' ')[3]) + + inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False) + self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) + + for op in self.atomic_op: + atomic_op = getattr(bldr, 'atomic_%s' % op) + inst = atomic_op(ptr, val, ordering) + self.assertEqual(op, str(inst).strip().split(' ')[3]) + + def test_atomic_ldst(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + val = Constant.int(Type.int(), 1234) + + for ordering in self.orderings: + loaded = bldr.atomic_load(ptr, ordering) + self.assert_('load atomic' in str(loaded)) + self.assertEqual(ordering, + str(loaded).strip().split(' ')[-3].rstrip(',')) + self.assert_('align 1' in str(loaded)) + + stored = bldr.atomic_store(loaded, ptr, ordering) + self.assert_('store atomic' in str(stored)) + self.assertEqual(ordering, + str(stored).strip().split(' ')[-3].rstrip(',')) + self.assert_('align 1' in str(stored)) + + fenced = bldr.fence(ordering) + self.assertEqual(['fence', ordering], + str(fenced).strip().split(' ')) + +tests.append(TestAtomic) + +# --------------------------------------------------------------------------- + +class TestConstExpr(TestCase): + + def test_constexpr_opcode(self): + mod = Module.new('test_constexpr_opcode') + func = mod.add_function(Type.function(Type.void(), []), name="foo") + builder = Builder.new(func.append_basic_block('entry')) + a = builder.inttoptr(Constant.int(Type.int(), 123), + Type.pointer(Type.int())) + self.assertTrue(isinstance(a, lc.ConstantExpr)) + self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) + self.assertEqual(a.opcode_name, "inttoptr") + +tests.append(TestConstExpr) + +# --------------------------------------------------------------------------- + +class TestOperands(TestCase): + # implement a test function + test_module = """ +define i32 @prod(i32, i32) { +entry: + %2 = mul i32 %0, %1 + ret i32 %2 +} + +define i32 @test_func(i32, i32, i32) { +entry: + %tmp1 = call i32 @prod(i32 %0, i32 %1) + %tmp2 = add i32 %tmp1, %2 + %tmp3 = add i32 %tmp2, 1 + %tmp4 = add i32 %tmp3, -1 + %tmp5 = add i64 -81985529216486895, 12297829382473034410 + ret i32 %tmp4 +} +""" + def test_operands(self): + m = Module.from_assembly(StringIO(self.test_module)) + + test_func = m.get_function_named("test_func") + prod = m.get_function_named("prod") + + # test operands + i1 = test_func.basic_blocks[0].instructions[0] + i2 = test_func.basic_blocks[0].instructions[1] + i3 = test_func.basic_blocks[0].instructions[2] + i4 = test_func.basic_blocks[0].instructions[3] + i5 = test_func.basic_blocks[0].instructions[4] + + self.assertEqual(i1.operand_count, 3) + self.assertEqual(i2.operand_count, 2) + + self.assertEqual(i3.operands[1].z_ext_value, 1) + self.assertEqual(i3.operands[1].s_ext_value, 1) + self.assertEqual(i4.operands[1].z_ext_value, 0xffffffff) + self.assertEqual(i4.operands[1].s_ext_value, -1) + self.assertEqual(i5.operands[0].s_ext_value, -81985529216486895) + self.assertEqual(i5.operands[1].z_ext_value, 12297829382473034410) + + self.assert_(i1.operands[-1] is prod) + self.assert_(i1.operands[0] is test_func.args[0]) + self.assert_(i1.operands[1] is test_func.args[1]) + self.assert_(i2.operands[0] is i1) + self.assert_(i2.operands[1] is test_func.args[2]) + self.assertEqual(len(i1.operands), 3) + self.assertEqual(len(i2.operands), 2) + + self.assert_(i1.called_function is prod) + +tests.append(TestOperands) + +# --------------------------------------------------------------------------- + +class TestPasses(TestCase): + # Create a module. + asm = """ + +define i32 @test() nounwind { + ret i32 42 +} + +define i32 @test1() nounwind { +entry: + %tmp = alloca i32 + store i32 42, i32* %tmp, align 4 + %tmp1 = load i32* %tmp, align 4 + %tmp2 = call i32 @test() + %tmp3 = load i32* %tmp, align 4 + %tmp4 = load i32* %tmp, align 4 + ret i32 %tmp1 +} + +define i32 @test2() nounwind { +entry: + %tmp = call i32 @test() + ret i32 %tmp +} +""" + def test_passes(self): + m = Module.from_assembly(StringIO(self.asm)) + + fn_test1 = m.get_function_named('test1') + fn_test2 = m.get_function_named('test2') + + original_test1 = str(fn_test1) + original_test2 = str(fn_test2) + + # Let's run a module-level inlining pass. First, create a pass manager. + pm = lp.PassManager.new() + + # Add the target data as the first "pass". This is mandatory. + pm.add(le.TargetData.new('')) + + # Add the inlining pass. + pm.add(lp.PASS_INLINE) + + # Run it! + pm.run(m) + + # Done with the pass manager. + del pm + + # Make sure test2 is inlined + self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) + + bb_entry = fn_test2.basic_blocks[0] + + self.assertEqual(len(bb_entry.instructions), 1) + self.assertEqual(bb_entry.instructions[0].opcode_name, 'ret') + + # Let's run a DCE pass on the the function 'test1' now. First create a + # function pass manager. + fpm = lp.FunctionPassManager.new(m) + + # Add the target data as first "pass". This is mandatory. + fpm.add(le.TargetData.new('')) + + # Add a DCE pass + fpm.add(lp.PASS_ADCE) + + # Run the pass on the function 'test1' + fpm.run(m.get_function_named('test1')) + + # Make sure test1 is modified + self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) + + def test_passes_with_pmb(self): + m = Module.from_assembly(StringIO(self.asm)) + + fn_test1 = m.get_function_named('test1') + fn_test2 = m.get_function_named('test2') + + original_test1 = str(fn_test1) + original_test2 = str(fn_test2) + + # Try out the PassManagerBuilder + + pmb = lp.PassManagerBuilder.new() + + self.assertEqual(pmb.opt_level, 2) # ensure default is level 2 + pmb.opt_level = 3 + self.assertEqual(pmb.opt_level, 3) # make sure it works + + self.assertEqual(pmb.size_level, 0) # ensure default is level 0 + pmb.size_level = 2 + self.assertEqual(pmb.size_level, 2) # make sure it works + + self.assertFalse(pmb.vectorize) # ensure default is False + pmb.vectorize = True + self.assertTrue(pmb.vectorize) # make sure it works + + # make sure the default is False + self.assertFalse(pmb.disable_unit_at_a_time) + self.assertFalse(pmb.disable_unroll_loops) + self.assertFalse(pmb.disable_simplify_lib_calls) + + pmb.disable_unit_at_a_time = True + self.assertTrue(pmb.disable_unit_at_a_time) + + # Do function pass + fpm = lp.FunctionPassManager.new(m) + pmb.populate(fpm) + fpm.run(fn_test1) + + # Make sure test1 has changed + self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) + + # Do module pass + pm = lp.PassManager.new() + pmb.populate(pm) + pm.run(m) + + # Make sure test2 has changed + self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) + + def test_dump_passes(self): + self.assertTrue(len(lp.PASSES)>0, msg="Cannot have no passes") + +tests.append(TestPasses) + +# --------------------------------------------------------------------------- + +class TestEngineBuilder(TestCase): + + def make_test_module(self): + module = Module.new("testmodule") + fnty = Type.function(Type.int(), []) + function = module.add_function(fnty, 'foo') + bb_entry = function.append_basic_block('entry') + builder = Builder.new(bb_entry) + builder.ret(Constant.int(Type.int(), 0xcafe)) + module.verify() + return module + + def run_foo(self, ee, module): + function = module.get_function_named('foo') + retval = ee.run_function(function, []) + self.assertEqual(retval.as_int(), 0xcafe) + + + def test_enginebuilder_basic(self): + module = self.make_test_module() + self.assertTrue(llvmpy.capsule.has_ownership(module._ptr._ptr)) + ee = EngineBuilder.new(module).create() + self.assertFalse(llvmpy.capsule.has_ownership(module._ptr._ptr)) + self.run_foo(ee, module) + + + def test_enginebuilder_with_tm(self): + tm = le.TargetMachine.new() + module = self.make_test_module() + self.assertTrue(llvmpy.capsule.has_ownership(module._ptr._ptr)) + ee = EngineBuilder.new(module).create(tm) + self.assertFalse(llvmpy.capsule.has_ownership(module._ptr._ptr)) + self.run_foo(ee, module) + + def test_enginebuilder_force_jit(self): + module = self.make_test_module() + ee = EngineBuilder.new(module).force_jit().create() + + self.run_foo(ee, module) +# +# def test_enginebuilder_force_interpreter(self): +# module = self.make_test_module() +# ee = EngineBuilder.new(module).force_interpreter().create() +# +# self.run_foo(ee, module) + + def test_enginebuilder_opt(self): + module = self.make_test_module() + ee = EngineBuilder.new(module).opt(3).create() + + self.run_foo(ee, module) + +tests.append(TestEngineBuilder) + +# --------------------------------------------------------------------------- + +class TestExecutionEngine(TestCase): + def test_get_pointer_to_global(self): + module = lc.Module.new(str(self)) + gvar = module.add_global_variable(Type.int(), 'hello') + X = 1234 + gvar.initializer = lc.Constant.int(Type.int(), X) + + ee = le.ExecutionEngine.new(module) + ptr = ee.get_pointer_to_global(gvar) + from ctypes import c_void_p, cast, c_int, POINTER + casted = cast(c_void_p(ptr), POINTER(c_int)) + self.assertEqual(X, casted[0]) + + def test_add_global_mapping(self): + module = lc.Module.new(str(self)) + gvar = module.add_global_variable(Type.int(), 'hello') + + fnty = lc.Type.function(Type.int(), []) + foo = module.add_function(fnty, name='foo') + bldr = lc.Builder.new(foo.append_basic_block('entry')) + bldr.ret(bldr.load(gvar)) + + ee = le.ExecutionEngine.new(module) + from ctypes import c_int, addressof, CFUNCTYPE + value = 0xABCD + value_ctype = c_int(value) + value_pointer = addressof(value_ctype) + + ee.add_global_mapping(gvar, value_pointer) + + foo_addr = ee.get_pointer_to_function(foo) + prototype = CFUNCTYPE(c_int) + foo_callable = prototype(foo_addr) + self.assertEqual(foo_callable(), value) + + + +tests.append(TestExecutionEngine) +# --------------------------------------------------------------------------- + +class TestObjCache(TestCase): + + def test_objcache(self): + # Testing module aliasing + m1 = Module.new('a') + t = Type.int() + ft = Type.function(t, [t]) + f1 = m1.add_function(ft, "func") + m2 = f1.module + self.assert_(m1 is m2) + + # Testing global vairable aliasing 1 + gv1 = GlobalVariable.new(m1, t, "gv") + gv2 = GlobalVariable.get(m1, "gv") + self.assert_(gv1 is gv2) + + # Testing global vairable aliasing 2 + gv3 = m1.global_variables[0] + self.assert_(gv1 is gv3) + + # Testing global vairable aliasing 3 + gv2 = None + gv3 = None + + gv1.delete() + + gv4 = GlobalVariable.new(m1, t, "gv") + + self.assert_(gv1 is not gv4) + + # Testing function aliasing 1 + b1 = f1.append_basic_block('entry') + f2 = b1.function + self.assert_(f1 is f2) + + # Testing function aliasing 2 + f3 = m1.get_function_named("func") + self.assert_(f1 is f3) + + # Testing function aliasing 3 + f4 = Function.get_or_insert(m1, ft, "func") + self.assert_(f1 is f4) + + # Testing function aliasing 4 + f5 = Function.get(m1, "func") + self.assert_(f1 is f5) + + # Testing function aliasing 5 + f6 = m1.get_or_insert_function(ft, "func") + self.assert_(f1 is f6) + + # Testing function aliasing 6 + f7 = m1.functions[0] + self.assert_(f1 is f7) + + # Testing argument aliasing + a1 = f1.args[0] + a2 = f1.args[0] + self.assert_(a1 is a2) + + # Testing basic block aliasing 1 + b2 = f1.basic_blocks[0] + self.assert_(b1 is b2) + + # Testing basic block aliasing 2 + b3 = f1.entry_basic_block + self.assert_(b1 is b3) + + # Testing basic block aliasing 3 + b31 = f1.entry_basic_block + self.assert_(b1 is b31) + + # Testing basic block aliasing 4 + bldr = Builder.new(b1) + b4 = bldr.basic_block + self.assert_(b1 is b4) + + # Testing basic block aliasing 5 + i1 = bldr.ret_void() + b5 = i1.basic_block + self.assert_(b1 is b5) + + # Testing instruction aliasing 1 + i2 = b5.instructions[0] + self.assert_(i1 is i2) + + # phi node + phi = bldr.phi(t) + phi.add_incoming(f1.args[0], b1) + v2 = phi.get_incoming_value(0) + b6 = phi.get_incoming_block(0) + + # Testing PHI / basic block aliasing 5 + self.assert_(b1 is b6) + + # Testing PHI / value aliasing + self.assert_(f1.args[0] is v2) + +tests.append(TestObjCache) + +# --------------------------------------------------------------------------- + +class TestTargetMachines(TestCase): + '''Exercise target machines + + Require PTX backend + ''' + def test_native(self): + m, _ = self._build_module() + tm = le.EngineBuilder.new(m).select_target() + + self.assertTrue(tm.target_name) + self.assertTrue(tm.target_data) + self.assertTrue(tm.target_short_description) + self.assertTrue(tm.triple) + self.assertIn('foo', tm.emit_assembly(m).decode('utf-8')) + self.assertTrue(le.get_host_cpu_name()) + + def test_ptx(self): + if lc.HAS_PTX: + arch = 'ptx64' + elif lc.HAS_NVPTX: + arch = 'nvptx64' + else: + return # skip this test + print arch + m, func = self._build_module() + func.calling_convention = lc.CC_PTX_KERNEL # set calling conv + ptxtm = le.TargetMachine.lookup(arch=arch, cpu='sm_20') + self.assertTrue(ptxtm.triple) + self.assertTrue(ptxtm.cpu) + ptxasm = ptxtm.emit_assembly(m).decode('utf-8') + self.assertIn('foo', ptxasm) + if lc.HAS_NVPTX: + self.assertIn('.address_size 64', ptxasm) + self.assertIn('sm_20', ptxasm) + + def _build_module(self): + m = Module.new('TestTargetMachines') + + fnty = Type.function(Type.void(), []) + func = m.add_function(fnty, name='foo') + + bldr = Builder.new(func.append_basic_block('entry')) + bldr.ret_void() + m.verify() + return m, func + + def _build_bad_archname(self): + with self.assertRaises(RuntimeError): + tm = TargetMachine.lookup("ain't no arch name") + +tests.append(TestTargetMachines) + +# --------------------------------------------------------------------------- + +class TestNative(TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + + def _make_module(self): + m = Module.new('module1') + m.add_global_variable(Type.int(), 'i') + + fty = Type.function(Type.int(), []) + f = m.add_function(fty, name='main') + + bldr = Builder.new(f.append_basic_block('entry')) + bldr.ret(Constant.int(Type.int(), 0xab)) + + return m + + def _compile(self, src): + dst = os.path.join(self.tmpdir, 'llvmobj.out') + s = subprocess.call(['cc', '-o', dst, src]) + if s != 0: + raise Exception("Cannot compile") + + s = subprocess.call([dst]) + self.assertEqual(s, 0xab) + + def test_assembly(self): + if sys.platform == 'darwin': + # skip this test on MacOSX for now + return + + m = self._make_module() + output = m.to_native_assembly() + + src = os.path.join(self.tmpdir, 'llvmasm.s') + with open(src, 'wb') as fout: + fout.write(output) + + self._compile(src) + + def test_object(self): + if sys.platform == 'darwin': + # skip this test on MacOSX for now + return + + m = self._make_module() + output = m.to_native_object() + + src = os.path.join(self.tmpdir, 'llvmobj.o') + with open(src, 'wb') as fout: + fout.write(output) + + self._compile(src) + +if sys.platform != 'win32': + tests.append(TestNative) + +# --------------------------------------------------------------------------- + +class TestNativeAsm(TestCase): + + def test_asm(self): + m = Module.new('module1') + + foo = m.add_function(Type.function(Type.int(), + [Type.int(), Type.int()]), + name="foo") + bldr = Builder.new(foo.append_basic_block('entry')) + x = bldr.add(foo.args[0], foo.args[1]) + bldr.ret(x) + + att_syntax = m.to_native_assembly() + os.environ["LLVMPY_OPTIONS"] = "-x86-asm-syntax=intel" + lc.parse_environment_options(sys.argv[0], "LLVMPY_OPTIONS") + intel_syntax = m.to_native_assembly() + + self.assertNotEqual(att_syntax, intel_syntax) + +tests.append(TestNativeAsm) + +# --------------------------------------------------------------------------- + +class TestUses(TestCase): + + def test_uses(self): + m = Module.new('a') + t = Type.int() + ft = Type.function(t, [t, t, t]) + f = m.add_function(ft, "func") + b = f.append_basic_block('entry') + bld = Builder.new(b) + tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1") + tmp2 = bld.add(tmp1, f.args[1], "tmp2") + tmp3 = bld.add(tmp1, f.args[2], "tmp3") + bld.ret(tmp3) + + # Testing use count + self.assertEqual(f.args[0].use_count, 1) + self.assertEqual(f.args[1].use_count, 1) + self.assertEqual(f.args[2].use_count, 1) + self.assertEqual(tmp1.use_count, 2) + self.assertEqual(tmp2.use_count, 0) + self.assertEqual(tmp3.use_count, 1) + + # Testing uses + self.assert_(f.args[0].uses[0] is tmp1) + self.assertEqual(len(f.args[0].uses), 1) + self.assert_(f.args[1].uses[0] is tmp2) + self.assertEqual(len(f.args[1].uses), 1) + self.assert_(f.args[2].uses[0] is tmp3) + self.assertEqual(len(f.args[2].uses), 1) + self.assertEqual(len(tmp1.uses), 2) + self.assertEqual(len(tmp2.uses), 0) + self.assertEqual(len(tmp3.uses), 1) + +tests.append(TestUses) + +# --------------------------------------------------------------------------- + +class TestMetaData(TestCase): + # test module metadata + def test_metadata(self): + m = Module.new('a') + t = Type.int() + metadata = MetaData.get(m, [Constant.int(t, 100), + MetaDataString.get(m, 'abcdef'), + None]) + MetaData.add_named_operand(m, 'foo', metadata) + self.assertEqual(MetaData.get_named_operands(m, 'foo'), [metadata]) + self.assertEqual(MetaData.get_named_operands(m, 'bar'), []) + self.assertEqual(len(metadata.operands), 3) + self.assertEqual(metadata.operands[0].z_ext_value, 100) + self.assertEqual(metadata.operands[1].string, 'abcdef') + self.assertTrue(metadata.operands[2] is None) + +tests.append(TestMetaData) + +# --------------------------------------------------------------------------- + +class TestInlining(TestCase): + def test_inline_call(self): + mod = Module.new(__name__) + callee = mod.add_function(Type.function(Type.int(), [Type.int()]), + name='bar') + + builder = Builder.new(callee.append_basic_block('entry')) + builder.ret(builder.add(callee.args[0], callee.args[0])) + + caller = mod.add_function(Type.function(Type.int(), []), + name='foo') + + builder = Builder.new(caller.append_basic_block('entry')) + callinst = builder.call(callee, [Constant.int(Type.int(), 1234)]) + builder.ret(callinst) + + pre_inlining = str(caller) + self.assertIn('call', pre_inlining) + + self.assertTrue(inline_function(callinst)) + + post_inlining = str(caller) + self.assertNotIn('call', post_inlining) + self.assertIn('2468', post_inlining) + +tests.append(TestInlining) + +# --------------------------------------------------------------------------- + +class TestIssue10(TestCase): + def test_issue10(self): + m = Module.new('a') + ti = Type.int() + tf = Type.function(ti, [ti, ti]) + + f = m.add_function(tf, "func1") + + bb = f.append_basic_block('entry') + + b = Builder.new(bb) + + # There are no instructions in bb. Positioning of the + # builder at beginning (or end) should succeed (trivially). + b.position_at_end(bb) + b.position_at_beginning(bb) + +tests.append(TestIssue10) + +# --------------------------------------------------------------------------- + +class TestOpaque(TestCase): + + def test_opaque(self): + # Create an opaque type + ts = Type.opaque('mystruct') + self.assertTrue('type opaque' in str(ts)) + self.assertTrue(ts.is_opaque) + self.assertTrue(ts.is_identified) + self.assertFalse(ts.is_literal) + #print(ts) + + # Create a recursive type + ts.set_body([Type.int(), Type.pointer(ts)]) + + self.assertEqual(ts.elements[0], Type.int()) + self.assertEqual(ts.elements[1], Type.pointer(ts)) + self.assertEqual(ts.elements[1].pointee, ts) + self.assertFalse(ts.is_opaque) # is not longer a opaque type + #print(ts) + + with self.assertRaises(llvm.LLVMException): + # Cannot redefine + ts.set_body([]) + + def test_opaque_with_no_name(self): + with self.assertRaises(llvm.LLVMException): + Type.opaque('') + +tests.append(TestOpaque) + +# --------------------------------------------------------------------------- +class TestCPUSupport(TestCase): + + def _build_test_module(self): + mod = Module.new('test') + + float = Type.double() + mysinty = Type.function( float, [float] ) + mysin = mod.add_function(mysinty, "mysin") + block = mysin.append_basic_block("entry") + b = Builder.new(block) + + sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) + cos = Function.intrinsic(mod, lc.INTR_COS, [float]) + + mysin.args[0].name = "x" + x = mysin.args[0] + one = Constant.real(float, "1") + cosx = b.call(cos, [x], "cosx") + cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") + onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub + sin = b.call(sqrt, [onemc2], "sin") + b.ret(sin) + return mod, mysin + + def _template(self, mattrs): + mod, func = self._build_test_module() + ee = self._build_engine(mod, mattrs=mattrs) + + arg = le.GenericValue.real(Type.double(), 1.234) + retval = ee.run_function(func, [arg]) + + golden = math.sin(1.234) + answer = retval.as_real(Type.double()) + self.assertTrue(abs(answer-golden)/golden < 1e-5) + + + def _build_engine(self, mod, mattrs): + if mattrs: + return EngineBuilder.new(mod).mattrs(mattrs).create() + else: + return EngineBuilder.new(mod).create() + + def test_cpu_support2(self): + features = 'sse3', 'sse41', 'sse42', 'avx' + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support3(self): + features = 'sse41', 'sse42', 'avx' + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support4(self): + features = 'sse42', 'avx' + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support5(self): + features = 'avx', + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support6(self): + features = [] + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + +tests.append(TestCPUSupport) + +# --------------------------------------------------------------------------- +class TestIntrinsicBasic(TestCase): + + def _build_module(self, float): + mod = Module.new('test') + functy = Type.function(float, [float]) + func = mod.add_function(functy, "mytest%s" % float) + block = func.append_basic_block("entry") + b = Builder.new(block) + return mod, func, b + + def _template(self, mod, func, pyfunc): + float = func.type.pointee.return_type + ee = le.ExecutionEngine.new(mod) + arg = le.GenericValue.real(float, 1.234) + retval = ee.run_function(func, [arg]) + golden = pyfunc(1.234) + answer = retval.as_real(float) + self.assertTrue(abs(answer - golden) / golden < 1e-7) + + def test_sqrt_f32(self): + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sqrt) + + def test_sqrt_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sqrt) + + def test_cos_f32(self): + if sys.platform == 'win32' and BITS == 32: + # float32 support is known to fail on 32-bit Windows + return + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_COS, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.cos) + + def test_cos_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_COS, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.cos) + + def test_sin_f32(self): + if sys.platform == 'win32' and BITS == 32: + # float32 support is known to fail on 32-bit Windows + return + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sin) + + def test_sin_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sin) + + def test_powi_f32(self): + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) + b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) + self._template(mod, func, lambda x: x**2) + + def test_powi_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) + b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) + self._template(mod, func, lambda x: x**2) + + + +tests.append(TestIntrinsicBasic) + +# --------------------------------------------------------------------------- + +class TestIntrinsic(TestCase): + def test_bswap(self): + # setup a function and a builder + mod = Module.new('test') + functy = Type.function(Type.int(), []) + func = mod.add_function(functy, "showme") + block = func.append_basic_block("entry") + b = Builder.new(block) + + # let's do bswap on a 32-bit integer using llvm.bswap + val = Constant.int(Type.int(), 0x42) + bswap = Function.intrinsic(mod, lc.INTR_BSWAP, [Type.int()]) + + bswap_res = b.call(bswap, [val]) + b.ret(bswap_res) + + # logging.debug(mod) + + # the output is: + # + # ; ModuleID = 'test' + # + # define void @showme() { + # entry: + # %0 = call i32 @llvm.bswap.i32(i32 42) + # ret i32 %0 + # } + + # let's run the function + ee = le.ExecutionEngine.new(mod) + retval = ee.run_function(func, []) + self.assertEqual(retval.as_int(), 0x42000000) + + def test_mysin(self): + if sys.platform == 'win32' and BITS == 32: + # float32 support is known to fail on 32-bit Windows + return + + # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) + mod = Module.new('test') + + float = Type.float() + mysinty = Type.function( float, [float] ) + mysin = mod.add_function(mysinty, "mysin") + block = mysin.append_basic_block("entry") + b = Builder.new(block) + + sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) + cos = Function.intrinsic(mod, lc.INTR_COS, [float]) + + mysin.args[0].name = "x" + x = mysin.args[0] + one = Constant.real(float, "1") + cosx = b.call(cos, [x], "cosx") + cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") + onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub + sin = b.call(sqrt, [onemc2], "sin") + b.ret(sin) + #logging.debug(mod) + +# ; ModuleID = 'test' +# +# define void @showme() { +# entry: +# call i32 @llvm.bswap.i32( i32 42 ) ; :0 [#uses +# } +# +# declare i32 @llvm.bswap.i32(i32) nounwind readnone +# +# define float @mysin(float %x) { +# entry: +# %cosx = call float @llvm.cos.f32( float %x ) ; [#uses +# %sin = call float @llvm.sqrt.f32( float %onemc2 ) +# ret float %sin +# } +# +# declare float @llvm.sqrt.f32(float) nounwind readnone +# +# declare float @llvm.powi.f32(float, i32) nounwind readnone +# +# declare float @llvm.cos.f32(float) nounwind readnone + + # let's run the function + ee = le.ExecutionEngine.new(mod) + arg = le.GenericValue.real(Type.float(), 1.234) + retval = ee.run_function(mysin, [arg]) + + golden = math.sin(1.234) + answer = retval.as_real(Type.float()) + self.assertTrue(abs(answer-golden)/golden < 1e-5) + +tests.append(TestIntrinsic) + +# --------------------------------------------------------------------------- + +class TestVolatile(TestCase): + + def test_volatile(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + # test load inst + val = bldr.load(ptr) + self.assertFalse(val.is_volatile, "default must be non-volatile") + val.set_volatile(True) + self.assertTrue(val.is_volatile, "fail to set volatile") + val.set_volatile(False) + self.assertFalse(val.is_volatile, "fail to unset volatile") + + # test store inst + store_inst = bldr.store(val, ptr) + self.assertFalse(store_inst.is_volatile, "default must be non-volatile") + store_inst.set_volatile(True) + self.assertTrue(store_inst.is_volatile, "fail to set volatile") + store_inst.set_volatile(False) + self.assertFalse(store_inst.is_volatile, "fail to unset volatile") + + def test_volatile_another(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + # test load inst + val = bldr.load(ptr, volatile=True) + self.assertTrue(val.is_volatile, "volatile kwarg does not work") + val.set_volatile(False) + self.assertFalse(val.is_volatile, "fail to unset volatile") + val.set_volatile(True) + self.assertTrue(val.is_volatile, "fail to set volatile") + + # test store inst + store_inst = bldr.store(val, ptr, volatile=True) + self.assertTrue(store_inst.is_volatile, "volatile kwarg does not work") + store_inst.set_volatile(False) + self.assertFalse(store_inst.is_volatile, "fail to unset volatile") + store_inst.set_volatile(True) + self.assertTrue(store_inst.is_volatile, "fail to set volatile") + +tests.append(TestVolatile) + +# --------------------------------------------------------------------------- + +class TestNamedMetaData(TestCase): + def test_named_md(self): + m = Module.new('test_named_md') + nmd = m.get_or_insert_named_metadata('something') + md = MetaData.get(m, [Constant.int(Type.int(), 0xbeef)]) + nmd.add(md) + self.assertTrue(str(nmd).startswith('!something')) + ir = str(m) + self.assertTrue('!something' in ir) + +tests.append(TestNamedMetaData) + +# --------------------------------------------------------------------------- + +def run(verbosity=1): + print('llvmpy is installed in: ' + os.path.dirname(__file__)) + print('llvmpy version: ' + llvm.__version__) + print(sys.version) + + suite = unittest.TestSuite() + for cls in tests: + suite.addTest(unittest.makeSuite(cls)) + + # The default stream fails in IPython qtconsole on Windows, + # so just using sys.stdout + runner = unittest.TextTestRunner(verbosity=verbosity, stream=sys.stdout) + return runner.run(suite) + + +if __name__ == '__main__': + run() diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 7a7ceaf..03aa286 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -196,4 +196,8 @@ def downcast(obj, cls): old = unwrap(obj) new = caster(old) used_to_own = has_ownership(old) - return wrap(new, owned=not used_to_own) + res = wrap(new, owned=not used_to_own) + if not res: + raise ValueError("Downcast failed") + return res + diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 6d73cd3..aaa33e4 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -719,13 +719,26 @@ class cast(_Type): def wrap(self, writer, val): dst = self.python_type.__name__ - return writer.call('py_%(dst)s_from' % locals(), 'PyObject*', val) + if dst == 'int': + unsigned = set([Unsigned, UnsignedLongLong, Uint64, + Size_t, VoidPtr]) + signed = set([LongLong, Int64, Int]) + assert self.binding_type in unsigned|signed + if self.binding_type in signed: + signflag = 'signed' + else: + signflag = 'unsigned' + fn = 'py_%(dst)s_from_%(signflag)s' % locals() + else: + fn = 'py_%(dst)s_from' % locals() + return writer.call(fn, 'PyObject*', val) def unwrap(self, writer, val): src = self.python_type.__name__ dst = self.binding_type.fullname ret = writer.declare(dst) - status = writer.call('py_%(src)s_to' % locals(), 'int', val, ret) + fn = 'py_%(src)s_to' % locals() + status = writer.call(fn, 'int', val, ret) writer.die_if_false(status) return ret diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index cf4e639..7b8e6df 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -67,7 +67,7 @@ int py_str_to(PyObject *strobj, const char* &strref){ static int py_int_to(PyObject *intobj, int64_t & val){ - if (!PyInt_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -88,7 +88,7 @@ int py_int_to(PyObject *intobj, int64_t & val){ static int py_int_to(PyObject *intobj, unsigned & val){ - if (!PyInt_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -100,9 +100,8 @@ int py_int_to(PyObject *intobj, unsigned & val){ static int py_int_to(PyObject *intobj, unsigned long long & val){ - if (!PyInt_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError - puts(PyString_AsString(PyObject_Str(PyObject_Type(intobj)))); PyErr_SetString(PyExc_TypeError, "Expecting an int 2"); return 0; } @@ -126,12 +125,12 @@ int py_int_to(PyObject *intobj, size_t & val){ static int py_int_to(PyObject *intobj, void* & val){ - if (!PyLong_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; } - val = PyLong_FromVoidPtr(intobj); + val = PyLong_AsVoidPtr(intobj); // success return 1; } @@ -202,13 +201,19 @@ PyObject* py_bool_from(bool val){ } } + static -PyObject* py_int_from(const long long & val){ +PyObject* py_int_from_signed(const long long & val){ return PyLong_FromLongLong(val); } static -PyObject* py_int_from(void * addr){ +PyObject* py_int_from_unsigned(const unsigned long long & val){ + return PyLong_FromUnsignedLongLong(val); +} + +static +PyObject* py_int_from_unsigned(void * addr){ return PyLong_FromVoidPtr(addr); } diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 2bbad42..76c8a16 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -137,12 +137,19 @@ PyObject* make_small_vector_from_unsigned(PyObject* self, PyObject* args) return pycapsule_new(SV, "llvm::SmallVector"); } +static +PyObject* get_llvm_version(PyObject* self, PyObject* args) +{ + return Py_BuildValue("(ii)", LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR); +} + static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } method( make_raw_ostream_for_printing ), method( make_small_vector_from_types ), method( make_small_vector_from_values ), method( make_small_vector_from_unsigned ), + method( get_llvm_version ), #undef method { NULL } }; @@ -185,7 +192,8 @@ struct extract { template static - bool from_py_sequence(VecTy& vec, PyObject* seq, const char *capsuleName) + bool from_py_sequence(VecTy& vec, PyObject* seq, const char *capsuleName, + bool accept_null=false) { Py_ssize_t N = PySequence_Size(seq); for (Py_ssize_t i = 0; i < N; ++i) { @@ -193,15 +201,23 @@ struct extract { if (!item) { return false; } - auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); - if (!capsule) { - return false; + if (accept_null and Py_None == *item) { + vec.push_back(NULL); + } else { + auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); + if (!capsule) { + return false; + } + void* ptr = PyCapsule_GetPointer(*capsule, capsuleName); + if (!ptr) { + return false; + } + ElemTy* res = typecast::from(ptr); + if (!res) { + return false; + } + vec.push_back(res); } - void* ptr = PyCapsule_GetPointer(*capsule, capsuleName); - if (!ptr) { - return false; - } - vec.push_back(static_cast(ptr)); } return true; } @@ -609,6 +625,18 @@ PyObject* StructType_setBody(llvm::StructType* Self, Py_RETURN_NONE; } +static +PyObject* StructType_get(llvm::LLVMContext& Cxt, + PyObject* Elems, + bool isPacked=false) +{ + using namespace llvm; + std::vector elements; + extract::from_py_sequence(elements, Elems, "llvm::Type"); + StructType *sty = StructType::get(Cxt, elements, isPacked); + return pycapsule_new(sty, "llvm::Type", "llvm::StructType"); +} + static PyObject* Module_list_globals(llvm::Module* Mod) { @@ -656,7 +684,7 @@ PyObject* ConstantArray_get(llvm::ArrayType* Ty, PyObject* Consts) std::vector vec_consts; bool ok = extract::from_py_sequence(vec_consts, Consts, - "llvm::Value"); + "llvm::Value"); if (not ok) return NULL; Constant* ary = ConstantArray::get(Ty, vec_consts); return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); @@ -724,7 +752,9 @@ static PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) { std::vector vals; - bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value"); + bool accept_null = true; + bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value", + accept_null); if (not ok) return NULL; llvm::MDNode* md = llvm::MDNode::get(Cxt, vals); return pycapsule_new(md, "llvm::Value", "llvm::MDNode"); @@ -750,7 +780,7 @@ PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, if (not ok) return NULL; Value** ptr_values = &vec_values[0]; ReturnInst* inst = builder->CreateAggregateRet(ptr_values, N); - return pycapsule_new(inst, "llvm::Value", "llvm:ReturnInst"); + return pycapsule_new(inst, "llvm::Value", "llvm::ReturnInst"); } static diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index eac4b07..64db072 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -1,12 +1,14 @@ from binding import * from namespace import llvm -from Value import Argument +from Value import Argument, Value from Attributes import Attributes @Argument class Argument: _include_ = 'llvm/Argument.h' + _downcast_ = Value + addAttr = Method(Void, ref(Attributes)) removeAttr = Method(Void, ref(Attributes)) getParamAlignment = Method(cast(Unsigned, int)) diff --git a/llvmpy/src/Attributes.py b/llvmpy/src/Attributes.py index 235d2c8..c6a8d97 100644 --- a/llvmpy/src/Attributes.py +++ b/llvmpy/src/Attributes.py @@ -20,7 +20,7 @@ class Attributes: delete = Destructor() - get = Method(Attributes, ref(LLVMContext), ref(AttrBuilder)) + get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder)) @AttrBuilder diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 81edf37..4ed4f66 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -21,4 +21,6 @@ class BasicBlock: removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool)) removePredecessor |= Method(Void, ptr(BasicBlock)) - getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) \ No newline at end of file + getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) + + eraseFromParent = Method() diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 5407d71..0a79bd3 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -1,18 +1,9 @@ from binding import * from namespace import llvm - -from Value import Constant, Value - -UndefValue = llvm.Class(Constant) -ConstantInt = llvm.Class(Constant) -ConstantFP = llvm.Class(Constant) -ConstantArray = llvm.Class(Constant) -ConstantStruct = llvm.Class(Constant) -ConstantVector = llvm.Class(Constant) -ConstantDataSequential = llvm.Class(Constant) -ConstantDataArray = llvm.Class(ConstantDataSequential) -ConstantExpr = llvm.Class(Constant) - +from Value import Value +from Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray +from Value import ConstantStruct, ConstantVector, ConstantVector +from Value import ConstantDataSequential, ConstantDataArray, ConstantExpr from LLVMContext import LLVMContext from ADT.StringRef import StringRef from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned @@ -81,6 +72,8 @@ class UndefValue: @ConstantInt class ConstantInt: + _downcast_ = Constant, Value + get = StaticMethod(ptr(ConstantInt), ptr(IntegerType), cast(int, Unsigned), @@ -95,6 +88,8 @@ class ConstantInt: @ConstantFP class ConstantFP: + _downcast_ = Constant, Value + get = StaticMethod(ptr(Constant), ptr(Type), cast(float, Double)) getNegativeZero = StaticMethod(ptr(ConstantFP), ptr(Type)) getInfinity = StaticMethod(ptr(ConstantFP), ptr(Type), cast(bool, Bool)) @@ -107,6 +102,8 @@ class ConstantFP: @ConstantArray class ConstantArray: + _downcast_ = Constant, Value + get = CustomStaticMethod('ConstantArray_get', PyObjectPtr, # ptr(Constant), ptr(ArrayType), @@ -116,6 +113,8 @@ class ConstantArray: @ConstantStruct class ConstantStruct: + _downcast_ = Constant, Value + get = CustomStaticMethod('ConstantStruct_get', PyObjectPtr, # ptr(Constant) ptr(StructType), @@ -130,6 +129,8 @@ class ConstantStruct: @ConstantVector class ConstantVector: + _downcast_ = Constant, Value + get = CustomStaticMethod('ConstantVector_get', PyObjectPtr, # ptr(Constant) PyObjectPtr, # constants @@ -138,11 +139,13 @@ class ConstantVector: @ConstantDataSequential class ConstantDataSequential: - pass + _downcast_ = Constant, Value @ConstantDataArray class ConstantDataArray: + _downcast_ = Constant, Value + getString = StaticMethod(ptr(Constant), ref(LLVMContext), cast(str, StringRef), @@ -174,6 +177,8 @@ def _factory_const_type(): @ConstantExpr class ConstantExpr: + _downcast_ = Constant, Value + getAlignOf = _factory(ptr(Type)) getSizeOf = _factory(ptr(Type)) getOffsetOf = _factory(ptr(Type), ptr(Constant)) diff --git a/llvmpy/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py index a34c2f1..40724e0 100644 --- a/llvmpy/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -9,6 +9,7 @@ FunctionType = llvm.Class(Type) @FunctionType class FunctionType: _include_ = 'llvm/DerivedTypes.h' + _downcast_ = Type _get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) _get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 0bd4714..bcf66fd 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -41,7 +41,7 @@ class ExecutionEngine: @CustomPythonMethod def removeModule(self, module): if self._removeModule(module): - capsule.obtain_ownership(module._ptr) + capsule.obtain_ownership(module._capsule) return True return False diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index d82b5d3..52db622 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from Value import GlobalValue, Constant, Function, Argument +from Value import GlobalValue, Constant, Function, Argument, Value from BasicBlock import BasicBlock from Attributes import Attributes from Type import Type @@ -11,7 +11,7 @@ from CallingConv import CallingConv @Function class Function: _include_ = 'llvm/Function.h' - _downcast_ = GlobalValue, Constant + _downcast_ = GlobalValue, Constant, Value getReturnType = Method(ptr(Type)) getFunctionType = Method(ptr(FunctionType)) diff --git a/llvmpy/src/GenericValue.py b/llvmpy/src/GenericValue.py index 74587ba..73a3709 100644 --- a/llvmpy/src/GenericValue.py +++ b/llvmpy/src/GenericValue.py @@ -26,8 +26,8 @@ class GenericValue: valueIntWidth = _accessor('ValueIntWidth', cast(Unsigned, int)) - toSignedInt = _accessor('ToSignedInt', cast(UnsignedLongLong, int)) - toUnsignedInt = _accessor('ToUnsignedInt', cast(LongLong, int)) + toSignedInt = _accessor('ToSignedInt', cast(LongLong, int)) + toUnsignedInt = _accessor('ToUnsignedInt', cast(UnsignedLongLong, int)) toFloat = _accessor('ToFloat', cast(Double, float), ptr(Type)) diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index 095122f..445ff11 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -281,7 +281,7 @@ class IRBuilder: _CreateExtractValue.realname = 'CreateExtractValue' @CustomPythonMethod - def CreateExtractValue(self, args): + def CreateExtractValue(self, *args): from llvmpy import extra args = list(args) valuelist = args[1] @@ -316,3 +316,8 @@ class IRBuilder: # New in llvm 3.3 #CreateVectorSplat = Method(ptr(Value), cast(int, Unsigned), ptr(Value), # cast(str, StringRef)) + + + Insert = Method(ptr(Instruction), + ptr(Instruction), + cast(str, StringRef)).require_only(1) diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index b3fa701..9763e7c 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from Value import Value, MDNode, User, BasicBlock, Function +from Value import Value, MDNode, User, BasicBlock, Function, ConstantInt Instruction = llvm.Class(User) @@ -66,13 +66,14 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', from ADT.StringRef import StringRef from CallingConv import CallingConv from Attributes import Attributes -from Constant import ConstantInt from Type import Type @Instruction class Instruction: + _downcast_ = Value, User + removeFromParent = Method() eraseFromParent = Method() eraseFromParent.disowning = True @@ -133,6 +134,7 @@ class BinaryOperator: @CallInst class CallInst: _downcast_ = Value, Instruction + getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) diff --git a/llvmpy/src/Metadata.py b/llvmpy/src/Metadata.py index 94088ca..d5cc4b1 100644 --- a/llvmpy/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -10,6 +10,7 @@ from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: + _downcast_ = Value replaceOperandWith = Method(Void, cast(int, Unsigned), ptr(Value)) getOperand = Method(ptr(Value), cast(int, Unsigned)) getNumOperands = Method(cast(Unsigned, int)) @@ -24,6 +25,7 @@ class MDNode: @MDString class MDString: + _downcast_ = Value get = StaticMethod(ptr(MDString), ref(LLVMContext), cast(str, StringRef)) getString = Method(cast(StringRef, str)) getLength = Method(cast(int, Unsigned)) diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index 29960fa..1bd6843 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -9,7 +9,7 @@ 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) + VectorTargetTransformInfo) from src.PassManager import PassManagerBase from src.Support.FormattedStream import formatted_raw_ostream @@ -40,9 +40,9 @@ class TargetMachine: getDataLayout = Method(const(ownedptr(DataLayout))) getScalarTargetTransformInfo = Method(const( - ownedptr(ScalarTargetTransformInfo))) + ownedptr(ScalarTargetTransformInfo))) getVectorTargetTransformInfo = Method(const( - ownedptr(VectorTargetTransformInfo))) + ownedptr(VectorTargetTransformInfo))) addPassesToEmitFile = Method(cast(bool, Bool), ref(PassManagerBase), diff --git a/llvmpy/src/TargetTransformInfo.py b/llvmpy/src/TargetTransformInfo.py index 5761281..1208050 100644 --- a/llvmpy/src/TargetTransformInfo.py +++ b/llvmpy/src/TargetTransformInfo.py @@ -1,11 +1,14 @@ from binding import * -from namespace import llvm +from src.namespace import llvm +from src.Pass import ImmutablePass llvm.includes.add('llvm/TargetTransformInfo.h') +TargetTransformInfo = llvm.Class(ImmutablePass) ScalarTargetTransformInfo = llvm.Class() VectorTargetTransformInfo = llvm.Class() + @ScalarTargetTransformInfo class ScalarTargetTransformInfo: delete = Destructor() @@ -14,3 +17,8 @@ class ScalarTargetTransformInfo: class VectorTargetTransformInfo: delete = Destructor() +@TargetTransformInfo +class TargetTransformInfo: + new = Constructor(ptr(ScalarTargetTransformInfo), + ptr(VectorTargetTransformInfo)) + diff --git a/llvmpy/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py index a95b6df..c940062 100644 --- a/llvmpy/src/Transforms/PassManagerBuilder.py +++ b/llvmpy/src/Transforms/PassManagerBuilder.py @@ -1,10 +1,13 @@ from binding import * from ..namespace import llvm -from ..PassManager import PassManagerBase, FunctionPassManager -from ..Target.TargetLibraryInfo import TargetLibraryInfo -from ..Pass import Pass -@llvm.Class() +PassManagerBuilder = llvm.Class() + +from src.PassManager import PassManagerBase, FunctionPassManager +from src.Target.TargetLibraryInfo import TargetLibraryInfo +from src.Pass import Pass + +@PassManagerBuilder class PassManagerBuilder: _include_ = 'llvm/Transforms/IPO/PassManagerBuilder.h' diff --git a/llvmpy/src/Transforms/Utils/Cloning.py b/llvmpy/src/Transforms/Utils/Cloning.py index 1971177..c6eaf0a 100644 --- a/llvmpy/src/Transforms/Utils/Cloning.py +++ b/llvmpy/src/Transforms/Utils/Cloning.py @@ -1,11 +1,15 @@ from binding import * from src.namespace import llvm -from src.Module import Module -from src.Instruction import CallInst llvm.includes.add('llvm/Transforms/Utils/Cloning.h') -@llvm.Class() +InlineFunctionInfo = llvm.Class() + + +from src.Module import Module +from src.Instruction import CallInst + +@InlineFunctionInfo class InlineFunctionInfo: new = Constructor() delete = Destructor() diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index ec0bf88..8e62137 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -146,25 +146,27 @@ class Type: @IntegerType class IntegerType: - pass + _downcast_ = Type @CompositeType class CompositeType: - pass + _downcast_ = Type @SequentialType class SequentialType: - pass + _downcast_ = Type @ArrayType class ArrayType: + _downcast_ = Type getNumElements = Method(cast(Uint64, int)) get = StaticMethod(ptr(ArrayType), ptr(Type), cast(int, Uint64)) isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) @PointerType class PointerType: + _downcast_ = Type getAddressSpace = Method(cast(Unsigned, int)) get = StaticMethod(ptr(PointerType), ptr(Type), cast(int, Unsigned)) getUnqual = StaticMethod(ptr(PointerType), ptr(Type)) @@ -172,6 +174,7 @@ class PointerType: @VectorType class VectorType: + _downcast_ = Type getNumElements = Method(cast(Unsigned, int)) getBitWidth = Method(cast(Unsigned, int)) get = StaticMethod(ptr(VectorType), ptr(Type), cast(int, Unsigned)) @@ -184,6 +187,7 @@ class VectorType: @StructType class StructType: + _downcast_ = Type isPacked = Method(cast(Bool, bool)) isLiteral = Method(cast(Bool, bool)) isOpaque = Method(cast(Bool, bool)) @@ -203,10 +207,12 @@ class StructType: cast(str, StringRef), ).require_only(1) - get = StaticMethod(ptr(StructType), - ref(LLVMContext), - cast(bool, Bool), # is packed - ).require_only(1) + get = CustomStaticMethod('StructType_get', + PyObjectPtr, # StructType* + ref(LLVMContext), + PyObjectPtr, # ArrayRef elements + cast(bool, Bool), # is packed + ).require_only(2) isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index 88f221c..b10807a 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -11,6 +11,15 @@ BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) GlobalValue = llvm.Class(Constant) Function = llvm.Class(GlobalValue) +UndefValue = llvm.Class(Constant) +ConstantInt = llvm.Class(Constant) +ConstantFP = llvm.Class(Constant) +ConstantArray = llvm.Class(Constant) +ConstantStruct = llvm.Class(Constant) +ConstantVector = llvm.Class(Constant) +ConstantDataSequential = llvm.Class(Constant) +ConstantDataArray = llvm.Class(ConstantDataSequential) +ConstantExpr = llvm.Class(Constant) from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter diff --git a/test/constants.py b/test/constants.py index afe1020..90a5a53 100644 --- a/test/constants.py +++ b/test/constants.py @@ -21,8 +21,6 @@ def _build_test_module(datatype, constants): bb_entry = func_subject.append_basic_block('entry') builder = Builder.new(bb_entry) - - for k in constants: builder.call(func_subject.args[0], [k]) diff --git a/test/malloc.py b/test/malloc.py new file mode 100644 index 0000000..1613a36 --- /dev/null +++ b/test/malloc.py @@ -0,0 +1,16 @@ +from llvm.core import * + +def test(): + m = Module.new('sdf') + f = m.add_function(Type.function(Type.void(), []), 'foo') + bb = f.append_basic_block('entry') + b = Builder.new(bb) + alloc = b.malloc(Type.int(), 'ha') + inst = b.free(alloc) + alloc = b.malloc_array(Type.int(), Constant.int(Type.int(), 10), 'hee') + inst = b.free(alloc) + b.ret_void() + print m + +if __name__ == '__main__': + test() diff --git a/test/operands.py b/test/operands.py index 674bc9e..32fb811 100644 --- a/test/operands.py +++ b/test/operands.py @@ -49,6 +49,7 @@ class TestOperands(unittest.TestCase): i1 = test_func.basic_blocks[0].instructions[0] i2 = test_func.basic_blocks[0].instructions[1] + logging.debug("Testing User.operand_count ..") self.assertEqual(i1.operand_count, 3) @@ -61,6 +62,7 @@ class TestOperands(unittest.TestCase): self.assert_(i1.operands[1] is test_func.args[1]) self.assert_(i2.operands[0] is i1) self.assert_(i2.operands[1] is test_func.args[2]) + self.assertEqual(len(i1.operands), 3) self.assertEqual(len(i2.operands), 2) diff --git a/test/testall.py b/test/testall.py index 3b5f0c3..231bca3 100644 --- a/test/testall.py +++ b/test/testall.py @@ -18,16 +18,6 @@ def do_llvmexception(): e = LLVMException() -def do_ownable(): - print(" Testing class Ownable") - o = Ownable(None, lambda x: None) - try: - o._own(None) - o._disown() - except LLVMException: - pass - - def do_misc(): print(" Testing miscellaneous functions") try: @@ -44,7 +34,6 @@ def do_misc(): def do_llvm(): print(" Testing module llvm") do_llvmexception() - do_ownable() do_misc() @@ -208,7 +197,9 @@ def do_constant(): Constant.struct([Constant.int(ti,42)]*10) Constant.packed_struct([Constant.int(ti,42)]*10) Constant.vector([Constant.int(ti,42)]*10) + Constant.sizeof(ti) + k = Constant.int(ti, 10) f = Constant.real(Type.float(), 3.1415) k.neg().not_().add(k).sub(k).mul(k).udiv(k).sdiv(k).urem(k) @@ -271,7 +262,8 @@ def do_global_variable(): def do_argument(): print(" Testing class Argument") m = Module.new('a') - ft = Type.function(ti, [ti]) + tip = Type.pointer(ti) + ft = Type.function(tip, [tip]) f = Function.new(m, ft, 'func') a = f.args[0] a.add_attribute(ATTR_ZEXT) @@ -301,13 +293,14 @@ def do_function(): c = f.collector a = list(f.args) g = f.basic_block_count - g = f.get_entry_basic_block() - g = f.append_basic_block('a') - g = f.get_entry_basic_block() +# g = f.entry_basic_block +# g = f.append_basic_block('a') +# g = f.entry_basic_block g = list(f.basic_blocks) f.add_attribute(ATTR_NO_RETURN) f.add_attribute(ATTR_ALWAYS_INLINE) f.remove_attribute(ATTR_NO_RETURN) + # LLVM misbehaves: #try: # f.verify() @@ -414,7 +407,7 @@ def do_builder(): b.position_at_beginning(blk) b.position_at_end(blk) b.position_before(blk.instructions[0]) - blk2 = b.block + blk2 = b.basic_block b.ret_void() b.ret(Constant.int(ti, 10)) _do_builder_mrv() @@ -552,7 +545,7 @@ def do_genericvalue(): def do_executionengine(): print(" Testing class ExecutionEngine") m = Module.new('a') - ee = ExecutionEngine.new(m, True) + ee = ExecutionEngine.new(m, False) # True) ft = Type.function(ti, []) f = m.add_function(ft, 'func') bb = f.append_basic_block('entry') @@ -573,7 +566,7 @@ def do_executionengine(): ee3 = ExecutionEngine.new(m4, False) ee3.add_module(m5) x = ee3.remove_module(m5) - check_is_module(x) + isinstance(x, Module) def do_llvm_ee(): From d2dc34cdd3f5d772be398efdbcd222ad6b1df826 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 13 Feb 2013 17:12:54 -0600 Subject: [PATCH 095/338] Try to fix invalid dtor call --- llvm/core.py | 72 +++++++++++++++++++++++++------------ llvmpy/capsule.py | 20 ++++++----- llvmpy/gen/binding.py | 2 +- llvmpy/gen/codegen.py | 4 ++- llvmpy/src/IRBuilder.py | 2 +- llvmpy/src/Instruction.py | 75 +++++++++++++++++++++------------------ 6 files changed, 108 insertions(+), 67 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 1c3184c..f2af943 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -475,28 +475,31 @@ class Module(llvm.Wrapper): def add_function(self, ty, name): """Add a function of given type with given name.""" - fn = self.get_function_named(name) - if fn is not None: - raise llvm.LLVMException("Duplicated function %s" % name) - return self.get_or_insert_function(ty, name) + return Function.new(self, ty, name) +# fn = self.get_function_named(name) +# if fn is not None: +# raise llvm.LLVMException("Duplicated function %s" % name) +# return self.get_or_insert_function(ty, name) def get_function_named(self, name): """Return a Function object representing function with given name.""" - fn = self._ptr.getFunction(name) - if fn is not None: - return _make_value(fn) + return Function.get(self, name) +# fn = self._ptr.getFunction(name) +# if fn is not None: +# return _make_value(fn) def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" - constant = self._ptr.getOrInsertFunction(name, ty._ptr) - try: - fn = constant._downcast(api.llvm.Function) - except ValueError: - # bitcasted to function type - return _make_value(constant) - else: - return _make_value(fn) + return Function.get_or_insert(self, ty, name) +# constant = self._ptr.getOrInsertFunction(name, ty._ptr) +# try: +# fn = constant._downcast(api.llvm.Function) +# except ValueError: +# # bitcasted to function type +# return _make_value(constant) +# else: +# return _make_value(fn) @property def functions(self): @@ -616,6 +619,10 @@ class Type(llvm.Wrapper): ptr = ptr._downcast(type(self)._type_) super(Type, self).__init__(ptr) + @property + def kind(self): + return self._ptr.getTypeID() + @staticmethod def int(bits=32): """Create an integer type having the given bit width.""" @@ -830,7 +837,6 @@ class FunctionType(Type): return self._ptr.getNumParams() - class StructType(Type): """Represents a structure type.""" _type_ = api.llvm.StructType @@ -1385,15 +1391,32 @@ class Function(GlobalValue): @staticmethod def new(module, func_ty, name): - return module.add_function(func_ty, name) + try: + fn = Function.get(module, name) + except llvm.LLVMException: + return Function.get_or_insert(module, func_ty, name) + else: + raise llvm.LLVMException("Duplicated function %s" % name) + @staticmethod def get_or_insert(module, func_ty, name): - return module.get_or_insert_function(func_ty, name) + constant = module._ptr.getOrInsertFunction(name, func_ty._ptr) + try: + fn = constant._downcast(api.llvm.Function) + except ValueError: + # bitcasted to function type + return _make_value(constant) + else: + return _make_value(fn) @staticmethod def get(module, name): - return module.get_function_named(name) + fn = module._ptr.getFunction(name) + if fn is None: + raise llvm.LLVMException("no function named `%s`" % name) + else: + return _make_value(fn) @staticmethod def intrinsic(module, intrinsic_id, types): @@ -1450,6 +1473,10 @@ class Function(GlobalValue): assert self.basic_block_count return _make_value(self._ptr.getEntryBlock()) + def get_entry_basic_block(self): + "Deprecated. Use entry_basic_block instead" + return self.entry_basic_block + def append_basic_block(self, name): context = api.llvm.getGlobalContext() bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) @@ -1857,6 +1884,7 @@ class Builder(llvm.Wrapper): """Position the builder at the end of the given block. Next instruction inserted will be last one in the block.""" + self._ptr.SetInsertPoint(bblk._ptr) def position_before(self, instr): @@ -2111,9 +2139,9 @@ class Builder(llvm.Wrapper): def insert_value(self, retval, rhs, idx, name=""): return _make_value(self._ptr.CreateInsertValue(retval._ptr, - rhs._ptr, - [idx], - name)) + rhs._ptr, + [idx], + name)) def phi(self, ty, name=""): return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name)) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 03aa286..0b1f203 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -19,13 +19,14 @@ def set_debug(enabled): def _capsule_weakref_dtor(item): addr = item.pointer + name = item.name _addr2refct[addr] -= 1 refct = _addr2refct[addr] assert refct >= 0, "RefCt drop below 0" if refct == 0: - dtor = _addr2dtor.pop(addr, None) + dtor = _addr2dtor.pop((name, addr), None) if dtor is not None: - logger.debug('Destroy %s %s', item.name, hex(item.pointer)) + logger.debug('Destroy %s %s', name, hex(addr)) dtor(item.capsule) class Capsule(object): @@ -92,26 +93,28 @@ _cache = defaultdict(WeakValueDictionary) def release_ownership(old): logger.debug('Release %s', old) addr = Capsule.getPointer(old) - - if _addr2dtor.get(addr) is None: + name = Capsule.getName(old) + if _addr2dtor.get((name, addr)) is None: clsname = Capsule.getClassName(old) if not _pyclasses[clsname]._has_dtor(): return # Guard duplicated release raise Exception("Already released") - _addr2dtor[addr] = None + _addr2dtor[(name, addr)] = None def obtain_ownership(cap): cls = cap.get_class() if cls._has_dtor(): addr = cap.pointer + name = cap.name assert _addr2dtor[addr] is None - _addr2dtor[addr] = cls._delete_ + _addr2dtor[(name, addr)] = cls._delete_ def has_ownership(cap): addr = Capsule.getPointer(cap) - return _addr2dtor.get(addr) is not None + name = Capsule.getName(cap) + return _addr2dtor.get((name, addr)) is not None def wrap(cap, owned=False): '''Wrap a PyCapsule with the corresponding Wrapper class. @@ -125,11 +128,12 @@ def wrap(cap, owned=False): cap = Capsule(cap) cls = cap.get_class() addr = cap.pointer + name = cap.name try: # lookup cached object return _cache[cls][addr] except KeyError: if not owned and cls._has_dtor(): - _addr2dtor[addr] = cls._delete_ + _addr2dtor[(name, addr)] = cls._delete_ obj = cap.instantiate() _cache[cls][addr] = obj # cache it return obj diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index aaa33e4..4454d72 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -329,7 +329,7 @@ class Class(SubModule, _Type): fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")' name = self.capsule_name raw = writer.declare('void*', fmt % locals()) - writer.die_if_false(raw) + writer.die_if_false(raw, verbose=name) ptrty = ptr(self).fullname ty = self.fullname fmt = 'typecast< %(ty)s >::from(%(raw)s)' diff --git a/llvmpy/gen/codegen.py b/llvmpy/gen/codegen.py index dd499d6..abde437 100644 --- a/llvmpy/gen/codegen.py +++ b/llvmpy/gen/codegen.py @@ -208,8 +208,10 @@ class CppCodeWriter(CodeWriterBase): self.return_null() return ret - def die_if_false(self, val): + def die_if_false(self, val, verbose=None): with self.block('if(!%(val)s)' % locals()): + if verbose: + self.println('puts("Error: %s");' % verbose) self.return_null() def raises(self, exccls, msg): diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index 445ff11..8590430 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -294,7 +294,7 @@ class IRBuilder: _CreateInsertValue.realname = 'CreateInsertValue' @CustomPythonMethod - def CreateInsertValue(self, args): + def CreateInsertValue(self, *args): from llvmpy import extra args = list(args) valuelist = args[2] diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 9763e7c..4761e16 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -120,16 +120,17 @@ class Instruction: @AtomicCmpXchgInst class AtomicCmpXchgInst: - pass + _downcast_ = Value, Instruction @AtomicRMWInst class AtomicRMWInst: + _downcast_ = Value, Instruction BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min', 'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP') @BinaryOperator class BinaryOperator: - pass + _downcast_ = Value, Instruction @CallInst class CallInst: @@ -159,6 +160,7 @@ class CallInst: @CmpInst class CmpInst: + _downcast_ = Value, Instruction Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', 'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO', 'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE', @@ -175,30 +177,31 @@ class CmpInst: @ExtractElementInst class ExtractElementInst: - pass + _downcast_ = Value, Instruction @FenceInst class FenceInst: - pass + _downcast_ = Value, Instruction @GetElementPtrInst class GetElementPtrInst: - pass + _downcast_ = Value, Instruction @InsertElementInst class InsertElementInst: - pass + _downcast_ = Value, Instruction @InsertValueInst class InsertValueInst: - pass + _downcast_ = Value, Instruction @LandingPadInst class LandingPadInst: - pass + _downcast_ = Value, Instruction @PHINode class PHINode: + _downcast_ = Value, Instruction getNumIncomingValues = Method(cast(Unsigned, int)) getIncomingValue = Method(ptr(Value), cast(int, Unsigned)) setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value)) @@ -210,15 +213,15 @@ class PHINode: @SelectInst class SelectInst: - pass + _downcast_ = Value, Instruction @ShuffleVectorInst class ShuffleVectorInst: - pass + _downcast_ = Value, Instruction @StoreInst class StoreInst: - _downcast_ = Instruction + _downcast_ = Value, Instruction isVolatile = Method(cast(Bool, bool)) isSimple = Method(cast(Bool, bool)) isUnordered = Method(cast(Bool, bool)) @@ -237,38 +240,40 @@ class StoreInst: @TerminatorInst class TerminatorInst: + _downcast_ = Value, Instruction getNumSuccessors = Method(cast(Unsigned, int)) getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned)) setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) @UnaryInstruction class UnaryInstruction: - pass + _downcast_ = Value, Instruction #call @IntrinsicInst class IntrinsicInst: - pass + _include_ = 'llvm/IntrinsicInst.h' + _downcast_ = Value, Instruction #compare @FCmpInst class FCmpInst: - pass + _downcast_ = Value, Instruction @ICmpInst class ICmpInst: - pass + _downcast_ = Value, Instruction # terminator @BranchInst class BranchInst: - pass + _downcast_ = Value, Instruction @IndirectBrInst class IndirectBrInst: - pass + _downcast_ = Value, Instruction @InvokeInst class InvokeInst: @@ -284,14 +289,16 @@ class InvokeInst: @ResumeInst class ResumeInst: - pass + _downcast_ = Value, Instruction @ReturnInst class ReturnInst: - pass + _downcast_ = Value, Instruction @SwitchInst class SwitchInst: + _downcast_ = Value, Instruction + getCondition = Method(ptr(Value)) setCondition = Method(Void, ptr(Value)) getDefaultDest = Method(ptr(BasicBlock)) @@ -302,20 +309,20 @@ class SwitchInst: @UnreachableInst class UnreachableInst: - pass + _downcast_ = Value, Instruction # unary @AllocaInst class AllocaInst: - pass + _downcast_ = Value, Instruction @CastInst class CastInst: - pass + _downcast_ = Value, Instruction @ExtractValueInst class ExtractValueInst: - pass + _downcast_ = Value, Instruction @LoadInst class LoadInst: @@ -338,46 +345,46 @@ class LoadInst: @VAArgInst class VAArgInst: - pass + _downcast_ = Value, Instruction # intrinsic @DbgInfoIntrinsic class DbgInfoIntrinsic: - pass + _downcast_ = Value, Instruction @MemIntrinsic class MemIntrinsic: - pass + _downcast_ = Value, Instruction @VACopyInst class VACopyInst: - pass + _downcast_ = Value, Instruction @VAEndInst class VAEndInst: - pass + _downcast_ = Value, Instruction @VAStartInst class VAStartInst: - pass + _downcast_ = Value, Instruction @BitCastInst class BitCastInst: - pass + _downcast_ = Value, Instruction @FPExtInst class FPExtInst: - pass + _downcast_ = Value, Instruction @FPToSIInst class FPToSIInst: - pass + _downcast_ = Value, Instruction @FPToUIInst class FPToUIInst: - pass + _downcast_ = Value, Instruction @FPTruncInst class FPTruncInst: - pass + _downcast_ = Value, Instruction From cb00dcc52c4ddf390a3ef51b33726babbf5e769c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 13 Feb 2013 18:12:45 -0600 Subject: [PATCH 096/338] Fix a bug in CreatInsertValue and one in ConstantInt. --- llvm/core.py | 3 +-- llvmpy/src/Constant.py | 2 +- llvmpy/src/IRBuilder.py | 11 +++++++---- llvmpy/test_binding.py | 5 +++++ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index f2af943..60c05fa 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2041,8 +2041,7 @@ class Builder(llvm.Wrapper): def alloca(self, ty, name=""): intty = Type.int() - zero = api.llvm.ConstantInt.get(intty._ptr, 0) - return _make_value(self._ptr.CreateAlloca(ty._ptr, zero, name)) + return _make_value(self._ptr.CreateAlloca(ty._ptr, None, name)) def alloca_array(self, ty, size, name=""): return _make_value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 0a79bd3..3cbb40b 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -76,7 +76,7 @@ class ConstantInt: get = StaticMethod(ptr(ConstantInt), ptr(IntegerType), - cast(int, Unsigned), + cast(int, Uint64), cast(bool, Bool), ).require_only(2) isValueValidForType = StaticMethod(cast(Bool, bool), diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index 8590430..efdf453 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -288,9 +288,12 @@ class IRBuilder: args[1] = extra.make_small_vector_from_unsigned(*valuelist) return self._CreateExtractValue(*args) - _CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), - ref(SmallVector_Unsigned), cast(str, StringRef)) - _CreateInsertValue.require_only(3) + _CreateInsertValue = Method(ptr(Value), + ptr(Value), # Agg + ptr(Value), # Val + ref(SmallVector_Unsigned), # ArrayRef + cast(str, StringRef), # name + ).require_only(3) _CreateInsertValue.realname = 'CreateInsertValue' @CustomPythonMethod @@ -298,7 +301,7 @@ class IRBuilder: from llvmpy import extra args = list(args) valuelist = args[2] - args[1] = extra.make_small_vector_from_unsigned(*valuelist) + args[2] = extra.make_small_vector_from_unsigned(*valuelist) return self._CreateInsertValue(*args) CreateLandingPad = Method(ptr(LandingPadInst), ptr(Type), ptr(Value), diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index 01e6c38..8eb56f6 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -323,6 +323,11 @@ def test_constants(): aryconst = llvm.ConstantArray.get(ary_int32x4, [intconst] * 4) assert str(aryconst.getAggregateElement(0)) == str(intconst) + bignum = 4415104608 + int64ty = llvm.Type.getInt64Ty(context) + const_bignum = llvm.ConstantInt.get(int64ty, 4415104608) + assert str(bignum) in str(const_bignum) + def test_intrinsic(): context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) From bf121485ad4d9c564cc6f6ed3ad033187ca03e2e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 15 Feb 2013 11:18:51 -0600 Subject: [PATCH 097/338] Fix problem with caching llvm.core.Value objects. --- llvm/__init__.py | 9 ++++++++- llvm/core.py | 17 ++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/llvm/__init__.py b/llvm/__init__.py index c18d066..e3e785f 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -14,7 +14,14 @@ class Wrapper(object): @property def _ptr(self): - return self.__ptr + try: + return self.__ptr + except AttributeError: + raise AttributeError("_ptr resource has been removed") + + @_ptr.deleter + def _ptr(self): + del self.__ptr def _extract_ptrs(objs): diff --git a/llvm/core.py b/llvm/core.py index 60c05fa..66f7c5f 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -926,7 +926,6 @@ class VectorType(Type): class Value(llvm.Wrapper): _type_ = api.llvm.Value - def __init__(self, builder, ptr): assert builder is _ValueFactory @@ -1596,6 +1595,7 @@ class NamedMetaData(llvm.Wrapper): return mod.get_named_metadata(name) def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() @property @@ -1822,13 +1822,14 @@ class _ValueFactory(object): def build(cls, ptr): # try to look in the cache addr = ptr._capsule.pointer + id = ptr.getValueID() + key = id, addr try: - obj = cls.cache[addr] + obj = cls.cache[key] return obj except KeyError: pass # find class by value id - id = ptr.getValueID() ctorcls = cls.class_for_valueid.get(id) if not ctorcls: if id > VALUE_INSTRUCTION: # "generic" instruction @@ -1837,12 +1838,12 @@ class _ValueFactory(object): ctorcls = Value # cache the obj obj = ctorcls(_ValueFactory, ptr) - cls.cache[addr] = obj + cls.cache[key] = obj return obj @classmethod def delete(cls, ptr): - del cls.cache[ptr._capsule.pointer] + del cls.cache[(ptr.getValueID(), ptr._capsule.pointer)] def _make_value(ptr): return _ValueFactory.build(ptr) @@ -1851,12 +1852,14 @@ def _make_value(ptr): # Builder #===----------------------------------------------------------------------=== -_atomic_orderings = { 'unordered' : api.llvm.AtomicOrdering.Unordered, +_atomic_orderings = { + 'unordered' : api.llvm.AtomicOrdering.Unordered, 'monotonic' : api.llvm.AtomicOrdering.Monotonic, 'acquire' : api.llvm.AtomicOrdering.Acquire, 'release' : api.llvm.AtomicOrdering.Release, 'acq_rel' : api.llvm.AtomicOrdering.AcquireRelease, - 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent} + 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent +} class Builder(llvm.Wrapper): From 26c4380c2b24d4016b0a427c7c1730ebe90b22d5 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 00:14:43 -0600 Subject: [PATCH 098/338] cleanup run_2to3 in setup.py --- setup.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index c24aa66..9bd73b9 100644 --- a/setup.py +++ b/setup.py @@ -158,19 +158,16 @@ kwds = dict( def run_2to3(): import lib2to3.refactor - from distutils.command.build_py import build_py_2to3 as build_py + from distutils.command.build_py import build_py_2to3 + print("Installing 2to3 fixers") - # need to convert sources to Py3 on installation fixes = lib2to3.refactor.get_fixers_from_package("lib2to3.fixes") - #fixes = [fix for fix in fixes - # if fix.split('fix_')[-1] not in ('next',) - #] + kwds["cmdclass"]['build_py'] = build_py_2to3 - kwds["cmdclass"].update(dict(build_py=build_py)) - -if sys.version_info[0] >= 3: +if sys.version_info[0] == 3: run_2to3() + kwds['long_description'] = open('README.rst').read() setup( From 7813bec6e98bfb5d9485e6271e07553521367073 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 01:14:06 -0600 Subject: [PATCH 099/338] add error handling --- setup.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 9bd73b9..cd13654 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ -import sys import os +import sys +from subprocess import Popen, PIPE from distutils.core import setup, Extension import versioneer @@ -19,9 +20,16 @@ else: llvm_config = os.environ.get('LLVM_CONFIG_PATH', default_llvm_config) -def run_llvm_config(args): - cmd = llvm_config + ' ' + ' '.join(args) - return os.popen(cmd).read().rstrip() + +def run_llvm_config(extra_args): + args = llvm_config.split() + args.extend(extra_args) + p = Popen(args, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + if stderr: + raise Exception("%r:\n%s" % (args, stderr.decode())) + return stdout.decode().strip() + if run_llvm_config(['--version']) == '': sys.exit("Cannot invoke llvm-config.\n" @@ -59,7 +67,7 @@ libdir = run_llvm_config(['--libdir']) ldflags = run_llvm_config(['--ldflags']) llvm_version = get_llvm_version() -print('LLVM version = %s' % llvm_version) +print('LLVM version = %r' % llvm_version) auto_intrinsic_gen(incdir) From 079e31c474cbefbf4e5a79de112c374c0047fa1e Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 01:15:37 -0600 Subject: [PATCH 100/338] remove unused code --- setup.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index cd13654..6e7013e 100644 --- a/setup.py +++ b/setup.py @@ -164,16 +164,10 @@ kwds = dict( cmdclass = versioneer.get_cmdclass(), ) -def run_2to3(): - import lib2to3.refactor - from distutils.command.build_py import build_py_2to3 - - print("Installing 2to3 fixers") - fixes = lib2to3.refactor.get_fixers_from_package("lib2to3.fixes") - kwds["cmdclass"]['build_py'] = build_py_2to3 if sys.version_info[0] == 3: - run_2to3() + from distutils.command.build_py import build_py_2to3 + kwds["cmdclass"]['build_py'] = build_py_2to3 kwds['long_description'] = open('README.rst').read() From a7c650a458df47fdcef17f16fd884d340adab333 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 01:24:27 -0600 Subject: [PATCH 101/338] simplified checking for valid llvm-config command --- setup.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index 6e7013e..52e176f 100644 --- a/setup.py +++ b/setup.py @@ -30,9 +30,10 @@ def run_llvm_config(extra_args): raise Exception("%r:\n%s" % (args, stderr.decode())) return stdout.decode().strip() - -if run_llvm_config(['--version']) == '': - sys.exit("Cannot invoke llvm-config.\n" +llvm_version = run_llvm_config(['--version']) +print('LLVM version = %r' % llvm_version) +if not llvm_version: + sys.exit("Error: could invoke llvm-config --version\n" "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config") def get_libs_and_objs(components): @@ -49,10 +50,6 @@ def get_libs_and_objs(components): def get_enabled_components(): return run_llvm_config(['--components']).split() -def get_llvm_version(): - return run_llvm_config(['--version']) - - def auto_intrinsic_gen(incdir): # let's do auto intrinsic generation print("Generate intrinsic IDs") @@ -66,8 +63,7 @@ incdir = run_llvm_config(['--includedir']) libdir = run_llvm_config(['--libdir']) ldflags = run_llvm_config(['--ldflags']) -llvm_version = get_llvm_version() -print('LLVM version = %r' % llvm_version) + auto_intrinsic_gen(incdir) From ffa713e3329199989f2c2e69c000efe2dc7a72e8 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 01:34:51 -0600 Subject: [PATCH 102/338] improve error handling --- setup.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 52e176f..6802391 100644 --- a/setup.py +++ b/setup.py @@ -24,17 +24,18 @@ llvm_config = os.environ.get('LLVM_CONFIG_PATH', default_llvm_config) def run_llvm_config(extra_args): args = llvm_config.split() args.extend(extra_args) - p = Popen(args, stdout=PIPE, stderr=PIPE) + try: + p = Popen(args, stdout=PIPE, stderr=PIPE) + except OSError: + sys.exit("Error: could invoke %r\n" + "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config" % args) stdout, stderr = p.communicate() if stderr: - raise Exception("%r:\n%s" % (args, stderr.decode())) + raise Exception("%r stderr is:\n%s" % (args, stderr.decode())) return stdout.decode().strip() llvm_version = run_llvm_config(['--version']) print('LLVM version = %r' % llvm_version) -if not llvm_version: - sys.exit("Error: could invoke llvm-config --version\n" - "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config") def get_libs_and_objs(components): parts = run_llvm_config(['--libs'] + components).split() From 013c7d2009803f67245815724eb2a17139fccda5 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 10:54:25 -0600 Subject: [PATCH 103/338] add impoved version of llvm-config for Windows --- llvm-config-win.py | 108 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 llvm-config-win.py diff --git a/llvm-config-win.py b/llvm-config-win.py new file mode 100644 index 0000000..25dbc43 --- /dev/null +++ b/llvm-config-win.py @@ -0,0 +1,108 @@ +import re +import sys +from distutils.spawn import find_executable +from os.path import abspath, dirname, isfile, join +from subprocess import Popen, PIPE + + +def find_llvm_tblgen(): + path = find_executable('llvm-tblgen') + if path is None: + sys.exit('Error: could not locate llvm-tblgen') + return path + +def find_llvm_prefix(): + return abspath(dirname(dirname(find_llvm_tblgen()))) + +def get_llvm_version(): + args = [find_llvm_tblgen(), '--version'] + p = Popen(args, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + if stderr: + raise Exception("%r stderr is:\n%s" % (args, stderr.decode())) + out = stdout.decode().strip() + pat = re.compile(r'llvm\s+version\s+(\d+\.\d+\S*)', re.I) + m = pat.search(out) + if m is None: + sys.exit('Error: could not parse version in:' + out) + return m.group(1) + +def main(): + try: + option = sys.argv[1] + except IndexError: + sys.exit('Error: option missing') + + if option == '--version': + print(get_llvm_version()) + + elif option == '--libs': + # NOTE: instead of actually looking at the components requested, + # we just print out a bunch of libs + for lib in """ +LLVMAnalysis +LLVMAsmParser +LLVMAsmPrinter +LLVMBitReader +LLVMBitWriter +LLVMCodeGen +LLVMCore +LLVMExecutionEngine +LLVMInstCombine +LLVMInstrumentation +LLVMInterpreter +LLVMipa +LLVMipo +LLVMJIT +LLVMLinker +LLVMMC +LLVMMCParser +LLVMObject +LLVMRuntimeDyld +LLVMScalarOpts +LLVMSelectionDAG +LLVMSupport +LLVMTarget +LLVMTransformUtils +LLVMVectorize +LLVMX86AsmParser +LLVMX86AsmPrinter +LLVMX86CodeGen +LLVMX86Desc +LLVMX86Info +LLVMX86Utils +Advapi32 +Shell32 +""".split(): + print('-l%s' % lib) + if isfile(join(find_llvm_prefix(), 'lib', 'LLVMPTXCodeGen.lib')): + print('-lLLVMPTXAsmPrinter') + print('-lLLVMPTXCodeGen') + print('-lLLVMPTXDesc') + print('-lLLVMPTXInfo') + elif isfile(join(find_llvm_prefix(), 'lib', 'LLVMNVPTXCodeGen.lib')): + print('-lLLVMNVPTXAsmPrinter') + print('-lLLVMNVPTXCodeGen') + print('-lLLVMNVPTXDesc') + print('-lLLVMNVPTXInfo') + + elif option == '--includedir': + incdir = join(find_llvm_prefix(), 'include') + path = join(incdir, 'llvm' , 'BasicBlock.h') + if not isfile(path): + sys.exit('Error: no file: %r' % path) + print(incdir) + + elif option == '--libdir': + libdir = join(find_llvm_prefix(), 'lib') + path = join(libdir, ' LLVMCore.lib') + if not isfile(path): + sys.exit('Error: no file: %r' % path) + print(libdir) + + else: + sys.exit('Unrecognized llvm-config option %r' % option) + + +if __name__ == '__main__': + main() From 92c9813b3e39cdf02b54565278e22eda9e551b09 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 12:50:22 -0600 Subject: [PATCH 104/338] fix library name --- llvm-config-win.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm-config-win.py b/llvm-config-win.py index 25dbc43..479fa2e 100644 --- a/llvm-config-win.py +++ b/llvm-config-win.py @@ -95,7 +95,7 @@ Shell32 elif option == '--libdir': libdir = join(find_llvm_prefix(), 'lib') - path = join(libdir, ' LLVMCore.lib') + path = join(libdir, 'LLVMCore.lib') if not isfile(path): sys.exit('Error: no file: %r' % path) print(libdir) From 0cc2e516acea4c562701d00efdab093b28d553f8 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 14:29:43 -0600 Subject: [PATCH 105/338] enable new llvm-config on Windows and update changelog --- CHANGELOG | 5 ++ llvm-config-win.py | 108 ------------------------------------------- llvm-config-win32.py | 104 ++++++++++++++++++++++++++--------------- 3 files changed, 73 insertions(+), 144 deletions(-) delete mode 100644 llvm-config-win.py diff --git a/CHANGELOG b/CHANGELOG index 3d19ab8..6c2cd14 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +2013-02-XX 0.11.0: +-------------------- + * fix Python 3 support on Windows + + 2013-02-01 0.10.2: -------------------- * change default to link dynamically to LLVM use: diff --git a/llvm-config-win.py b/llvm-config-win.py deleted file mode 100644 index 479fa2e..0000000 --- a/llvm-config-win.py +++ /dev/null @@ -1,108 +0,0 @@ -import re -import sys -from distutils.spawn import find_executable -from os.path import abspath, dirname, isfile, join -from subprocess import Popen, PIPE - - -def find_llvm_tblgen(): - path = find_executable('llvm-tblgen') - if path is None: - sys.exit('Error: could not locate llvm-tblgen') - return path - -def find_llvm_prefix(): - return abspath(dirname(dirname(find_llvm_tblgen()))) - -def get_llvm_version(): - args = [find_llvm_tblgen(), '--version'] - p = Popen(args, stdout=PIPE, stderr=PIPE) - stdout, stderr = p.communicate() - if stderr: - raise Exception("%r stderr is:\n%s" % (args, stderr.decode())) - out = stdout.decode().strip() - pat = re.compile(r'llvm\s+version\s+(\d+\.\d+\S*)', re.I) - m = pat.search(out) - if m is None: - sys.exit('Error: could not parse version in:' + out) - return m.group(1) - -def main(): - try: - option = sys.argv[1] - except IndexError: - sys.exit('Error: option missing') - - if option == '--version': - print(get_llvm_version()) - - elif option == '--libs': - # NOTE: instead of actually looking at the components requested, - # we just print out a bunch of libs - for lib in """ -LLVMAnalysis -LLVMAsmParser -LLVMAsmPrinter -LLVMBitReader -LLVMBitWriter -LLVMCodeGen -LLVMCore -LLVMExecutionEngine -LLVMInstCombine -LLVMInstrumentation -LLVMInterpreter -LLVMipa -LLVMipo -LLVMJIT -LLVMLinker -LLVMMC -LLVMMCParser -LLVMObject -LLVMRuntimeDyld -LLVMScalarOpts -LLVMSelectionDAG -LLVMSupport -LLVMTarget -LLVMTransformUtils -LLVMVectorize -LLVMX86AsmParser -LLVMX86AsmPrinter -LLVMX86CodeGen -LLVMX86Desc -LLVMX86Info -LLVMX86Utils -Advapi32 -Shell32 -""".split(): - print('-l%s' % lib) - if isfile(join(find_llvm_prefix(), 'lib', 'LLVMPTXCodeGen.lib')): - print('-lLLVMPTXAsmPrinter') - print('-lLLVMPTXCodeGen') - print('-lLLVMPTXDesc') - print('-lLLVMPTXInfo') - elif isfile(join(find_llvm_prefix(), 'lib', 'LLVMNVPTXCodeGen.lib')): - print('-lLLVMNVPTXAsmPrinter') - print('-lLLVMNVPTXCodeGen') - print('-lLLVMNVPTXDesc') - print('-lLLVMNVPTXInfo') - - elif option == '--includedir': - incdir = join(find_llvm_prefix(), 'include') - path = join(incdir, 'llvm' , 'BasicBlock.h') - if not isfile(path): - sys.exit('Error: no file: %r' % path) - print(incdir) - - elif option == '--libdir': - libdir = join(find_llvm_prefix(), 'lib') - path = join(libdir, 'LLVMCore.lib') - if not isfile(path): - sys.exit('Error: no file: %r' % path) - print(libdir) - - else: - sys.exit('Unrecognized llvm-config option %r' % option) - - -if __name__ == '__main__': - main() diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 2fbe662..96cc867 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -1,24 +1,43 @@ +import re import sys -import os +from distutils.spawn import find_executable +from os.path import abspath, dirname, isfile, join +from subprocess import Popen, PIPE -def find_path_of(filename, envvar='PATH'): - """Finds the path from $PATH where the file exists, returns None if not found.""" - pathlist = os.getenv(envvar).split(os.pathsep) - for path in pathlist: - if os.path.exists(os.path.join(path, filename)): - return os.path.abspath(path) - return None +def find_llvm_tblgen(): + path = find_executable('llvm-tblgen') + if path is None: + sys.exit('Error: could not locate llvm-tblgen') + return path -if sys.argv[1] == '--version': - cmd = 'llvm-tblgen --version' - # Hardcoded extraction, only tested on llvm 3.1 - result = os.popen(cmd).read().split('\n')[1].strip().split(' ')[2] - print(result) -elif sys.argv[1] == '--libs': +def find_llvm_prefix(): + return abspath(dirname(dirname(find_llvm_tblgen()))) + + +def ensure_file(path): + if not isfile(path): + sys.exit('Error: no file: %r' % path) + + +def get_llvm_version(): + args = [find_llvm_tblgen(), '--version'] + p = Popen(args, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + if stderr: + raise Exception("%r stderr is:\n%s" % (args, stderr.decode())) + out = stdout.decode().strip() + pat = re.compile(r'llvm\s+version\s+(\d+\.\d+\S*)', re.I) + m = pat.search(out) + if m is None: + sys.exit('Error: could not parse version in:' + out) + return m.group(1) + + +def libs_options(): # NOTE: instead of actually looking at the components requested, - # we just spit out a bunch of libs + # we just print out a bunch of libs for lib in """ LLVMAnalysis LLVMAsmParser @@ -55,32 +74,45 @@ Advapi32 Shell32 """.split(): print('-l%s' % lib) - llvmbin = find_path_of('llvm-tblgen.exe') - if os.path.exists(os.path.join(llvmbin, '../lib/LLVMPTXCodeGen.lib')): + + if isfile(join(find_llvm_prefix(), 'lib', 'LLVMPTXCodeGen.lib')): print('-lLLVMPTXAsmPrinter') print('-lLLVMPTXCodeGen') print('-lLLVMPTXDesc') print('-lLLVMPTXInfo') - elif os.path.exists(os.path.join(llvmbin, '../lib/LLVMNVPTXCodeGen.lib')): + + elif isfile(join(find_llvm_prefix(), 'lib', 'LLVMNVPTXCodeGen.lib')): print('-lLLVMNVPTXAsmPrinter') print('-lLLVMNVPTXCodeGen') print('-lLLVMNVPTXDesc') print('-lLLVMNVPTXInfo') -elif sys.argv[1] == '--includedir': - llvmbin = find_path_of('llvm-tblgen.exe') - if llvmbin is None: - raise RuntimeError('Could not find LLVM') - incdir = os.path.abspath(os.path.join(llvmbin, '../include')) - if not os.path.exists(os.path.join(incdir, 'llvm/BasicBlock.h')): - raise RuntimeError('Could not find LLVM include dir') - print(incdir) -elif sys.argv[1] == '--libdir': - llvmbin = find_path_of('llvm-tblgen.exe') - if llvmbin is None: - raise RuntimeError('Could not find LLVM') - libdir = os.path.abspath(os.path.join(llvmbin, '../lib')) - if not os.path.exists(os.path.join(libdir, 'LLVMCore.lib')): - raise RuntimeError('Could not find LLVM lib dir') - print(libdir) -else: - raise RuntimeError('Unrecognized llvm-config command %s' % sys.argv[1]) + + +def main(): + try: + option = sys.argv[1] + except IndexError: + sys.exit('Error: option missing') + + if option == '--version': + print(get_llvm_version()) + + elif option == '--libs': + libs_options() + + elif option == '--includedir': + incdir = join(find_llvm_prefix(), 'include') + ensure_file(join(incdir, 'llvm' , 'BasicBlock.h')) + print(incdir) + + elif option == '--libdir': + libdir = join(find_llvm_prefix(), 'lib') + ensure_file(join(libdir, 'LLVMCore.lib')) + print(libdir) + + else: + sys.exit('Unrecognized llvm-config option %r' % option) + + +if __name__ == '__main__': + main() From acd6ab685b9ce0cb77d482a3c7e0ff693ed47231 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 16 Feb 2013 19:20:06 -0600 Subject: [PATCH 106/338] enhance setup error messages --- llvm-config-win32.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 96cc867..9d3915a 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -26,7 +26,7 @@ def get_llvm_version(): p = Popen(args, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: - raise Exception("%r stderr is:\n%s" % (args, stderr.decode())) + sys.exit("Error: %r stderr is:\n%s" % (args, stderr.decode())) out = stdout.decode().strip() pat = re.compile(r'llvm\s+version\s+(\d+\.\d+\S*)', re.I) m = pat.search(out) @@ -111,7 +111,7 @@ def main(): print(libdir) else: - sys.exit('Unrecognized llvm-config option %r' % option) + sys.exit('Error: Unrecognized llvm-config option %r' % option) if __name__ == '__main__': From 1647580a4172fdc46b8ea2396acdf90fd20fcaf3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sat, 16 Feb 2013 21:54:12 -0600 Subject: [PATCH 107/338] LinkModules should release ownership of the other module when not preserving --- llvmpy/src/Linker.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/llvmpy/src/Linker.py b/llvmpy/src/Linker.py index 0b846d6..acca503 100644 --- a/llvmpy/src/Linker.py +++ b/llvmpy/src/Linker.py @@ -41,7 +41,7 @@ class Linker: PyObjectPtr, # errmsg ) - LinkModules = CustomStaticMethod('Linker_LinkModules', + _LinkModules = CustomStaticMethod('Linker_LinkModules', PyObjectPtr, # boolean ptr(Module), ptr(Module), @@ -49,3 +49,10 @@ class Linker: PyObjectPtr, # errsg ) + @CustomPythonStaticMethod + def LinkModules(module, other, mode, errmsg): + failed = Linker._LinkModules(module, other, mode, errmsg) + if not failed and mode != Linker.LinkerMode.PreserveSource: + capsule.release_ownership(other._ptr) + return failed + From 20d0bf9f2a8419f27abae471b7de6818be2502e8 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sun, 17 Feb 2013 16:37:57 -0600 Subject: [PATCH 108/338] add missing dummy options --- llvm-config-win32.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 9d3915a..915871e 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -110,6 +110,9 @@ def main(): ensure_file(join(libdir, 'LLVMCore.lib')) print(libdir) + elif option in ('--ldflags', '--components'): + pass + else: sys.exit('Error: Unrecognized llvm-config option %r' % option) From bf484aa2163d5b88b09e1732975bc430d69bcf4d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 19 Feb 2013 08:36:52 +0200 Subject: [PATCH 109/338] Correct if-then-else LLVM asm example. As was present vividly breaks LLVM IR constraints on SSA and basic-blocks: same var being assigned twice, no control transfer at the end of basic block. Compare with the original: http://www.mdevan.org/llvm-py/kaleidoscope/PythonLangImpl5.html --- docs/source/doc/kaleidoscope/PythonLangImpl5.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst index 5a096da..33edba2 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst @@ -217,7 +217,8 @@ Kaleidoscope looks something like this: br i1 %ifcond, label %then, label %else then: ; preds = %entry - %calltmp1 = call double @bar() + %calltmp = call double @foo() + br label %ifcont else: ; preds = %entry %calltmp1 = call double @bar() From 081b41db60609923db192d96b3861e4baf070b77 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Tue, 19 Feb 2013 15:24:54 +0000 Subject: [PATCH 110/338] Allow casting pointers to ints in cbuilder --- llvm_cbuilder/builder.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm_cbuilder/builder.py b/llvm_cbuilder/builder.py index 64083b1..917b37e 100644 --- a/llvm_cbuilder/builder.py +++ b/llvm_cbuilder/builder.py @@ -1153,6 +1153,10 @@ class PointerCasting(OperatorMixin): if _is_pointer(ty): return self._temp(self.parent.builder.bitcast(self.value, ty)) + + if _is_int(ty): + return self._temp(self.parent.builder.ptrtoint(self.value, ty)) + raise CastError(self.type, ty) From 175f558ce06f3b78cdc9e4e6370b16ca703b4c25 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 19 Feb 2013 10:54:31 -0600 Subject: [PATCH 111/338] Add error checking for common mistake in Builder.call --- llvm/core.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/core.py b/llvm/core.py index fa9dc77..fafaa22 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2192,6 +2192,10 @@ class Builder(object): if t != v.type: raise TypeError(err_template % (t, v.type)) arg_ptrs = unpack_values(args) + + if (isinstance(fn, Function) and \ + fn.module is not self.basic_block.function.module): + raise ValueError("Intermodule function call") return _make_value( _core.LLVMBuildCall(self.ptr, fn.ptr, arg_ptrs, name)) From 42f7219c3f571cecf265ff723f0240b5edccad1b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 10:43:11 -0600 Subject: [PATCH 112/338] Allow function.verify to raise exception on error. --- llvm/core.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index 66f7c5f..bc1ff45 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1508,7 +1508,13 @@ class Function(GlobalValue): # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. actions = api.llvm.VerifierFailureAction - return api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) + broken = api.llvm.verifyFunction(self._ptr, + actions.ReturnStatusAction) + if broken: + # If broken, then re-run to print the message + api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) + raise llvm.LLVMException("Function %s failed verification" % + self.name) #===----------------------------------------------------------------------=== # InlineAsm From d270e885cc37b86e66cf08fce2b7045251409c58 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 10:43:34 -0600 Subject: [PATCH 113/338] Add ptrtoint cast in cbuilder --- llvm_cbuilder/builder.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm_cbuilder/builder.py b/llvm_cbuilder/builder.py index 64083b1..917b37e 100644 --- a/llvm_cbuilder/builder.py +++ b/llvm_cbuilder/builder.py @@ -1153,6 +1153,10 @@ class PointerCasting(OperatorMixin): if _is_pointer(ty): return self._temp(self.parent.builder.bitcast(self.value, ty)) + + if _is_int(ty): + return self._temp(self.parent.builder.ptrtoint(self.value, ty)) + raise CastError(self.type, ty) From 435b92b4a49fc9974e3aed40d2cd67e21c7553cd Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 10:50:18 -0600 Subject: [PATCH 114/338] Fix VectorType.element --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index bc1ff45..f38028b 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -917,7 +917,7 @@ class VectorType(Type): @property def element(self): - return self._ptr.getVectorElementType() + return Type(self._ptr.getVectorElementType()) @property def count(self): From 74982d6fefe23c42544ce89591fb8e2cda971a26 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 13:42:05 -0600 Subject: [PATCH 115/338] Adapt to work in python2.6 --- llvmpy/capsule.cpp | 4 +- llvmpy/gen/gen.py | 2 + llvmpy/include/capsulethunk.h | 108 ++++++++++++++++++ llvmpy/include/llvm_binding/capsule_context.h | 20 +++- llvmpy/src/ADT/__init__.py | 12 +- llvmpy/src/Analysis/__init__.py | 12 +- llvmpy/src/Assembly/__init__.py | 12 +- llvmpy/src/Bitcode/__init__.py | 12 +- llvmpy/src/CodeGen/__init__.py | 12 +- llvmpy/src/ExecutionEngine/__init__.py | 12 +- llvmpy/src/Support/__init__.py | 12 +- llvmpy/src/Target/__init__.py | 12 +- llvmpy/src/Transforms/Utils/__init__.py | 17 +-- llvmpy/src/Transforms/__init__.py | 17 +-- llvmpy/src/__init__.py | 9 +- 15 files changed, 154 insertions(+), 119 deletions(-) create mode 100644 llvmpy/include/capsulethunk.h diff --git a/llvmpy/capsule.cpp b/llvmpy/capsule.cpp index e7e4932..b7fa81b 100644 --- a/llvmpy/capsule.cpp +++ b/llvmpy/capsule.cpp @@ -1,4 +1,5 @@ #include +#include #include static @@ -53,12 +54,13 @@ CapsuleContext* getContext(PyObject* self, PyObject* args) { PyErr_SetString(PyExc_TypeError, "PyCapsule has no context."); return NULL; } - return (CapsuleContext*)context; + return static_cast(context); } static PyObject* getClassName(PyObject* self, PyObject* args) { CapsuleContext* context = getContext(self, args); + //Assert(context->_magic == 0xdead); if (!context) { return NULL; } else { diff --git a/llvmpy/gen/gen.py b/llvmpy/gen/gen.py index c5d30de..066ed23 100644 --- a/llvmpy/gen/gen.py +++ b/llvmpy/gen/gen.py @@ -40,6 +40,8 @@ populate_submodules(module, submodule_%(ns)s); def populate_headers(println): includes = [ 'cstring', + 'Python.h', + 'capsulethunk.h', 'llvm_binding/conversion.h', 'llvm_binding/binding.h', 'llvm_binding/capsule_context.h', diff --git a/llvmpy/include/capsulethunk.h b/llvmpy/include/capsulethunk.h new file mode 100644 index 0000000..9061782 --- /dev/null +++ b/llvmpy/include/capsulethunk.h @@ -0,0 +1,108 @@ +/** + + This is a modified version of capsulethunk.h for use in llvmpy + +**/ + +#ifndef __CAPSULETHUNK_H +#define __CAPSULETHUNK_H + +//#define Assert(X) do_assert(!!(X), #X, __FILE__, __LINE__) +#define Assert(X) + +static +void do_assert(int cond, const char * msg, const char *file, unsigned line){ + if (not cond) { + fprintf(stderr, "Assertion failed %s:%d\n%s\n", file, line, msg); + exit(1); + } +} + +#if ( (PY_VERSION_HEX < 0x02070000) \ + || ((PY_VERSION_HEX >= 0x03000000) \ + && (PY_VERSION_HEX < 0x03010000)) ) + +typedef void (*PyCapsule_Destructor)(PyObject *); + +struct FakePyCapsule_Desc { + const char *name; + void *context; + PyCapsule_Destructor dtor; + PyObject *parent; + + FakePyCapsule_Desc() : name(0), context(0), dtor(0) {} +}; + +static +FakePyCapsule_Desc* get_pycobj_desc(PyObject *p){ + void *desc = ((PyCObject*)p)->desc; + Assert(desc && "No desc in PyCObject"); + return static_cast(desc); +} + +static +void pycobject_pycapsule_dtor(void *p, void *desc){ + Assert(desc); + Assert(p); + FakePyCapsule_Desc *fpc_desc = static_cast(desc); + Assert(fpc_desc->parent); + Assert(PyCObject_Check(fpc_desc->parent)); + fpc_desc->dtor(static_cast(fpc_desc->parent)); + delete fpc_desc; +} + +static +PyObject* PyCapsule_New(void* ptr, const char *name, PyCapsule_Destructor dtor) +{ + FakePyCapsule_Desc *desc = new FakePyCapsule_Desc; + desc->name = name; + desc->context = NULL; + desc->dtor = dtor; + PyObject *p = PyCObject_FromVoidPtrAndDesc(ptr, desc, + pycobject_pycapsule_dtor); + desc->parent = p; + return p; +} + +static +int PyCapsule_CheckExact(PyObject *p) +{ + return PyCObject_Check(p); +} + +static +void* PyCapsule_GetPointer(PyObject *p, const char *name) +{ + Assert(PyCapsule_CheckExact(p)); + if (strcmp(get_pycobj_desc(p)->name, name) != 0) { + PyErr_SetString(PyExc_ValueError, "Invalid PyCapsule object"); + } + return PyCObject_AsVoidPtr(p); +} + +static +void* PyCapsule_GetContext(PyObject *p) +{ + Assert(p); + Assert(PyCapsule_CheckExact(p)); + return get_pycobj_desc(p)->context; +} + +static +int PyCapsule_SetContext(PyObject *p, void *context) +{ + Assert(PyCapsule_CheckExact(p)); + get_pycobj_desc(p)->context = context; + return 0; +} + +static +const char * PyCapsule_GetName(PyObject *p) +{ +// Assert(PyCapsule_CheckExact(p)); + return get_pycobj_desc(p)->name; +} + +#endif /* #if PY_VERSION_HEX < 0x02070000 */ + +#endif /* __CAPSULETHUNK_H */ diff --git a/llvmpy/include/llvm_binding/capsule_context.h b/llvmpy/include/llvm_binding/capsule_context.h index 6ed1381..0256088 100644 --- a/llvmpy/include/llvm_binding/capsule_context.h +++ b/llvmpy/include/llvm_binding/capsule_context.h @@ -3,10 +3,10 @@ #include #include - -typedef PyObject* Destructor_Fn; +#include "capsulethunk.h" struct CapsuleContext { + //const unsigned _magic; const char* className; CapsuleContext(const char* cn) @@ -14,6 +14,17 @@ struct CapsuleContext { { } }; +static +void pycapsule_dtor_free_context(PyObject *pycap) +{ + void * context = PyCapsule_GetContext(pycap); + Assert(context); + CapsuleContext* cc = static_cast(context); + //Assert(cc->_magic == 0xdead); + delete cc; +} + + static PyObject* pycapsule_new(void* ptr, @@ -26,15 +37,16 @@ PyObject* pycapsule_new(void* ptr, if (!ptr) { Py_RETURN_NONE; } - PyObject* cap = PyCapsule_New(ptr, basename, NULL); + PyObject* cap = PyCapsule_New(ptr, basename, pycapsule_dtor_free_context); if (!cap) { PyErr_SetString(PyExc_TypeError, "Error creating new PyCapsule"); return NULL; } CapsuleContext* context = new CapsuleContext(classname); - if (PyCapsule_SetContext(cap, context)) { + if (0 != PyCapsule_SetContext(cap, context)) { return NULL; } + //Assert(context->_magic == 0xdead); return cap; } diff --git a/llvmpy/src/ADT/__init__.py b/llvmpy/src/ADT/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/ADT/__init__.py +++ b/llvmpy/src/ADT/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Analysis/__init__.py b/llvmpy/src/Analysis/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Analysis/__init__.py +++ b/llvmpy/src/Analysis/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Assembly/__init__.py b/llvmpy/src/Assembly/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Assembly/__init__.py +++ b/llvmpy/src/Assembly/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Bitcode/__init__.py b/llvmpy/src/Bitcode/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Bitcode/__init__.py +++ b/llvmpy/src/Bitcode/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/CodeGen/__init__.py b/llvmpy/src/CodeGen/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/CodeGen/__init__.py +++ b/llvmpy/src/CodeGen/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/ExecutionEngine/__init__.py b/llvmpy/src/ExecutionEngine/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/ExecutionEngine/__init__.py +++ b/llvmpy/src/ExecutionEngine/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Support/__init__.py b/llvmpy/src/Support/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Support/__init__.py +++ b/llvmpy/src/Support/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Target/__init__.py b/llvmpy/src/Target/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Target/__init__.py +++ b/llvmpy/src/Target/__init__.py @@ -1,10 +1,2 @@ -import os.path, importlib - -def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Transforms/Utils/__init__.py b/llvmpy/src/Transforms/Utils/__init__.py index 98c06fc..944426e 100644 --- a/llvmpy/src/Transforms/Utils/__init__.py +++ b/llvmpy/src/Transforms/Utils/__init__.py @@ -1,15 +1,2 @@ -import os.path, importlib - -def _init(): - base = os.path.dirname(__file__) - for fname in os.listdir(base): - print fname - is_python_script = fname.endswith('.py') or fname.endswith('.pyc') - is_init_script = fname.startswith('__init__') - is_directory = os.path.isdir(os.path.join(base, fname)) - if (is_directory or is_python_script) and not is_init_script : - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() - +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Transforms/__init__.py b/llvmpy/src/Transforms/__init__.py index 98c06fc..944426e 100644 --- a/llvmpy/src/Transforms/__init__.py +++ b/llvmpy/src/Transforms/__init__.py @@ -1,15 +1,2 @@ -import os.path, importlib - -def _init(): - base = os.path.dirname(__file__) - for fname in os.listdir(base): - print fname - is_python_script = fname.endswith('.py') or fname.endswith('.pyc') - is_init_script = fname.startswith('__init__') - is_directory = os.path.isdir(os.path.join(base, fname)) - if (is_directory or is_python_script) and not is_init_script : - modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) - -_init() - +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/__init__.py b/llvmpy/src/__init__.py index 98c06fc..ed34608 100644 --- a/llvmpy/src/__init__.py +++ b/llvmpy/src/__init__.py @@ -1,7 +1,7 @@ -import os.path, importlib +import os.path -def _init(): - base = os.path.dirname(__file__) +def _init(root=__name__, file=__file__): + base = os.path.dirname(file) for fname in os.listdir(base): print fname is_python_script = fname.endswith('.py') or fname.endswith('.pyc') @@ -9,7 +9,8 @@ def _init(): is_directory = os.path.isdir(os.path.join(base, fname)) if (is_directory or is_python_script) and not is_init_script : modname = os.path.basename(fname).rsplit('.', 1)[0] - importlib.import_module('.' + modname, __name__) + #importlib.import_module('.' + modname, __name__) + __import__('.'.join([root, modname])) _init() From a275068193c87c5a27758c17d7699e963a0bdfa8 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 17:58:38 -0600 Subject: [PATCH 116/338] Fix formatted_raw_ostream ownership error with the underlying stream. --- llvmpy/src/Support/FormattedStream.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvmpy/src/Support/FormattedStream.py b/llvmpy/src/Support/FormattedStream.py index 17c259b..26f906d 100644 --- a/llvmpy/src/Support/FormattedStream.py +++ b/llvmpy/src/Support/FormattedStream.py @@ -5,5 +5,11 @@ from raw_ostream import raw_ostream @llvm.Class(raw_ostream) class formatted_raw_ostream: _include_ = 'llvm/Support/FormattedStream.h' - new = Constructor(ref(raw_ostream), cast(bool, Bool)) + _new = Constructor(ref(raw_ostream), cast(bool, Bool)) + + @CustomPythonStaticMethod + def new(stream, destroy=False): + inst = formatted_raw_ostream._new(stream, destroy) + inst.__underlying_stream = stream # to prevent it being freed first + return inst From 45e70333fd70ec2449a0a95a7a7f4f68c47a36d5 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 19:17:56 -0600 Subject: [PATCH 117/338] Adapt to python 3.3 --- llvmpy/capsule.cpp | 1 + llvmpy/capsule.py | 12 ++- llvmpy/extra.py | 2 +- llvmpy/gen/binding.py | 2 +- llvmpy/gen/codegen.py | 2 +- llvmpy/gen/gen.py | 1 + llvmpy/include/llvm_binding/conversion.h | 23 ++++++ llvmpy/include/llvm_binding/extra.h | 8 +- llvmpy/include/python3adapt.h | 32 ++++++++ llvmpy/src/ADT/Triple.py | 2 +- llvmpy/src/Argument.py | 6 +- llvmpy/src/Attributes.py | 4 +- llvmpy/src/BasicBlock.py | 10 +-- llvmpy/src/Bitcode/ReaderWriter.py | 2 +- llvmpy/src/CallingConv.py | 2 +- llvmpy/src/Constant.py | 20 ++--- llvmpy/src/DataLayout.py | 16 ++-- llvmpy/src/DerivedTypes.py | 8 +- llvmpy/src/EngineBuilder.py | 16 ++-- llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 +- llvmpy/src/Function.py | 16 ++-- llvmpy/src/GenericValue.py | 4 +- llvmpy/src/GlobalValue.py | 8 +- llvmpy/src/GlobalVariable.py | 12 +-- llvmpy/src/IRBuilder.py | 28 +++---- llvmpy/src/InlineAsm.py | 8 +- llvmpy/src/Instruction.py | 12 +-- llvmpy/src/Intrinsics.py | 6 +- llvmpy/src/JITMemoryManager.py | 2 +- llvmpy/src/LLVMContext.py | 2 +- llvmpy/src/Linker.py | 8 +- llvmpy/src/Metadata.py | 16 ++-- llvmpy/src/Module.py | 22 +++--- llvmpy/src/Pass.py | 8 +- llvmpy/src/PassManager.py | 8 +- llvmpy/src/PassRegistry.py | 2 +- llvmpy/src/PassSupport.py | 2 +- llvmpy/src/Support/FormattedStream.py | 2 +- llvmpy/src/Type.py | 8 +- llvmpy/src/User.py | 4 +- llvmpy/src/Value.py | 12 +-- llvmpy/src/__init__.py | 5 +- llvmpy/test_binding.py | 73 ++++++++++--------- 43 files changed, 251 insertions(+), 188 deletions(-) create mode 100644 llvmpy/include/python3adapt.h diff --git a/llvmpy/capsule.cpp b/llvmpy/capsule.cpp index b7fa81b..561b28a 100644 --- a/llvmpy/capsule.cpp +++ b/llvmpy/capsule.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 0b1f203..ec6fdde 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -32,7 +32,7 @@ def _capsule_weakref_dtor(item): class Capsule(object): "Wraps PyCapsule so that we can build weakref of it." - from _capsule import check, getClassName, getName, getPointer + from ._capsule import check, getClassName, getName, getPointer def __init__(self, capsule): assert Capsule.valid(capsule) @@ -75,6 +75,9 @@ class Capsule(object): else: return False + def __hash__(self): + return super(Capsule, self).__hash__() + def __ne__(self, other): return not (self == other) @@ -122,7 +125,7 @@ def wrap(cap, owned=False): ''' if not Capsule.valid(cap): if isinstance(cap, list): - return map(wrap, cap) + return list(map(wrap, cap)) return cap # bypass if cap is not a PyCapsule and not a list cap = Capsule(cap) @@ -170,6 +173,9 @@ class Wrapper(object): def _ptr(self): return self._capsule.capsule + def __hash__(self): + return super(Wrapper, self).__hash__() + def __eq__(self, other): return self._capsule == other._capsule @@ -184,7 +190,7 @@ class Wrapper(object): return hasattr(cls, '_delete_') def downcast(obj, cls): - import _api + from . import _api if type(obj) is cls: return obj fromty = obj._llvm_type_ diff --git a/llvmpy/extra.py b/llvmpy/extra.py index a2e744f..99035a7 100644 --- a/llvmpy/extra.py +++ b/llvmpy/extra.py @@ -11,7 +11,7 @@ from llvmpy import _api def _wrapper(func): "Wrap the re-exported functions" def _core(*args): - unwrapped = map(capsule.unwrap, args) + unwrapped = list(map(capsule.unwrap, args)) ret = func(*unwrapped) return capsule.wrap(ret) return _core diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 4454d72..0f5c4fd 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -348,7 +348,7 @@ class Enum(object): def __init__(self, *value_names): self.parent = None if len(value_names) == 1: - value_names = filter(bool, value_names[0].replace(',', ' ').split()) + value_names = list(filter(bool, value_names[0].replace(',', ' ').split())) self.value_names = value_names self.includes = set() diff --git a/llvmpy/gen/codegen.py b/llvmpy/gen/codegen.py index abde437..f9585fd 100644 --- a/llvmpy/gen/codegen.py +++ b/llvmpy/gen/codegen.py @@ -259,7 +259,7 @@ class PyCodeWriter(CodeWriterBase): def unwrap_many(self, args): unwrapped = self.new_symbol('unwrapped') - self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) + self.println('%(unwrapped)s = list(map(capsule.unwrap, %(args)s))' % locals()) return unwrapped def unwrap(self, val): diff --git a/llvmpy/gen/gen.py b/llvmpy/gen/gen.py index 066ed23..263c289 100644 --- a/llvmpy/gen/gen.py +++ b/llvmpy/gen/gen.py @@ -41,6 +41,7 @@ def populate_headers(println): includes = [ 'cstring', 'Python.h', + 'python3adapt.h', 'capsulethunk.h', 'llvm_binding/conversion.h', 'llvm_binding/binding.h', diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 7b8e6df..abc3749 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -4,6 +4,29 @@ // python object unwrapper +static +int py_bytes_to(PyObject *bytesobj, llvm::StringRef &strref){ + // type check + if (!PyBytes_Check(bytesobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get len and buffer + const Py_ssize_t len = PyBytes_Size(bytesobj); + const char * buf = PyBytes_AsString(bytesobj); + if (!buf) { + // raises TypeError + return 0; + } + // set output + strref = llvm::StringRef(buf, len); + // success + return 1; +} + + + static int py_str_to(PyObject *strobj, llvm::StringRef &strref){ // type check diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 76c8a16..3874bb3 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -497,11 +497,9 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) llvm::WriteBitcodeToFile(M, rso); rso.flush(); StringRef ref = rso.str(); - PyObject* buf = PyString_FromStringAndSize(ref.data(), ref.size()); - if (-1 == PyFile_WriteObject(buf, FObj, Py_PRINT_RAW)){ - return NULL; - } - Py_RETURN_NONE; + PyObject* buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); + puts(PyString_AsString(PyObject_Str(PyObject_Type(buf)))); + return PyObject_CallMethod(FObj, "write", "O", buf); } static diff --git a/llvmpy/include/python3adapt.h b/llvmpy/include/python3adapt.h new file mode 100644 index 0000000..5b19ebe --- /dev/null +++ b/llvmpy/include/python3adapt.h @@ -0,0 +1,32 @@ +#ifndef PYTHON3ADAPT_H +#define PYTHON3ADAPT_H + +#if (PY_VERSION_HEX < 0x03000000) + +#define PyBytes_Check PyString_Check +#define PyBytes_Size PyString_Size +#define PyBytes_AsString PyString_AsString +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_FromString PyString_FromString + +#endif + +#if (PY_VERSION_HEX >= 0x03000000) + +#define PyString_Check PyUnicode_Check +#define PyString_Size PyUnicode_GET_SIZE +#define PyString_AsString PyUnicode_AsUTF8 +#define PyString_FromStringAndSize PyUnicode_FromStringAndSize +#define PyString_FromString PyUnicode_FromString + +#define PyInt_Check PyLong_Check +#define PyInt_FromLong PyLong_FromLong +#define PyInt_AsLong PyLong_AsLong +#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask +#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + +#define PyFile_Check(x) (1) + +#endif + +#endif //PYTHON3ADAPT_H \ No newline at end of file diff --git a/llvmpy/src/ADT/Triple.py b/llvmpy/src/ADT/Triple.py index 82de57e..1615c1c 100644 --- a/llvmpy/src/ADT/Triple.py +++ b/llvmpy/src/ADT/Triple.py @@ -1,6 +1,6 @@ from binding import * from ..namespace import llvm -from StringRef import StringRef +from .StringRef import StringRef Triple = llvm.Class() diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index 64db072..4f0b7a4 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -1,7 +1,7 @@ from binding import * -from namespace import llvm -from Value import Argument, Value -from Attributes import Attributes +from .namespace import llvm +from .Value import Argument, Value +from .Attributes import Attributes @Argument class Argument: diff --git a/llvmpy/src/Attributes.py b/llvmpy/src/Attributes.py index c6a8d97..4fe7651 100644 --- a/llvmpy/src/Attributes.py +++ b/llvmpy/src/Attributes.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext +from .namespace import llvm +from .LLVMContext import LLVMContext llvm.includes.add('llvm/Attributes.h') diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 4ed4f66..77eaf01 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -1,9 +1,9 @@ from binding import * -from namespace import llvm -from Value import Function, BasicBlock -from Instruction import Instruction, TerminatorInst -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef +from .namespace import llvm +from .Value import Function, BasicBlock +from .Instruction import Instruction, TerminatorInst +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef @BasicBlock class BasicBlock: diff --git a/llvmpy/src/Bitcode/ReaderWriter.py b/llvmpy/src/Bitcode/ReaderWriter.py index a8e8c43..b950ba4 100644 --- a/llvmpy/src/Bitcode/ReaderWriter.py +++ b/llvmpy/src/Bitcode/ReaderWriter.py @@ -9,7 +9,7 @@ llvm.includes.add('llvm/Bitcode/ReaderWriter.h') ParseBitCodeFile = llvm.CustomFunction('ParseBitCodeFile', 'llvm_ParseBitCodeFile', PyObjectPtr, # returns Module* - cast(str, StringRef), + cast(bytes, StringRef), ref(LLVMContext), PyObjectPtr, # file-like object ).require_only(2) diff --git a/llvmpy/src/CallingConv.py b/llvmpy/src/CallingConv.py index 71b4ad3..efca1fc 100644 --- a/llvmpy/src/CallingConv.py +++ b/llvmpy/src/CallingConv.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm CallingConv = llvm.Namespace('CallingConv') ID = CallingConv.Enum('ID', ''' diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 3cbb40b..70dc3bf 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -1,14 +1,14 @@ from binding import * -from namespace import llvm -from Value import Value -from Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray -from Value import ConstantStruct, ConstantVector, ConstantVector -from Value import ConstantDataSequential, ConstantDataArray, ConstantExpr -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned -from Type import Type, IntegerType, ArrayType, StructType -from Instruction import CmpInst +from .namespace import llvm +from .Value import Value +from .Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray +from .Value import ConstantStruct, ConstantVector, ConstantVector +from .Value import ConstantDataSequential, ConstantDataArray, ConstantExpr +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from .Type import Type, IntegerType, ArrayType, StructType +from .Instruction import CmpInst @Constant class Constant: diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index 9582d53..7085f52 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -1,16 +1,16 @@ from binding import * -from namespace import llvm -from Pass import ImmutablePass +from .namespace import llvm +from .Pass import ImmutablePass DataLayout = llvm.Class(ImmutablePass) StructLayout = llvm.Class() -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from Module import Module -from Type import Type, IntegerType, StructType -from ADT.SmallVector import SmallVector_Value -from GlobalVariable import GlobalVariable +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .Module import Module +from .Type import Type, IntegerType, StructType +from .ADT.SmallVector import SmallVector_Value +from .GlobalVariable import GlobalVariable @DataLayout diff --git a/llvmpy/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py index 40724e0..02eec8c 100644 --- a/llvmpy/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from Type import Type -from ADT.SmallVector import SmallVector_Type +from .namespace import llvm +from .LLVMContext import LLVMContext +from .Type import Type +from .ADT.SmallVector import SmallVector_Type FunctionType = llvm.Class(Type) diff --git a/llvmpy/src/EngineBuilder.py b/llvmpy/src/EngineBuilder.py index c3feafe..4e8ed12 100644 --- a/llvmpy/src/EngineBuilder.py +++ b/llvmpy/src/EngineBuilder.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from Module import Module -from JITMemoryManager import JITMemoryManager -from Support.CodeGen import CodeGenOpt, Reloc, CodeModel -from ADT.StringRef import StringRef -from ExecutionEngine.ExecutionEngine import ExecutionEngine -from Target.TargetMachine import TargetMachine -from ADT.Triple import Triple +from .namespace import llvm +from .Module import Module +from .JITMemoryManager import JITMemoryManager +from .Support.CodeGen import CodeGenOpt, Reloc, CodeModel +from .ADT.StringRef import StringRef +from .ExecutionEngine.ExecutionEngine import ExecutionEngine +from .Target.TargetMachine import TargetMachine +from .ADT.Triple import Triple EngineBuilder = llvm.Class() diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index bcf66fd..038d344 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -98,6 +98,6 @@ class ExecutionEngine: @CustomPythonMethod def runFunction(self, fn, args): from llvmpy import capsule - unwrapped = map(capsule.unwrap, args) + unwrapped = list(map(capsule.unwrap, args)) return self._runFunction(fn, tuple(unwrapped)) diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index 52db622..55a50d9 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from Value import GlobalValue, Constant, Function, Argument, Value -from BasicBlock import BasicBlock -from Attributes import Attributes -from Type import Type -from DerivedTypes import FunctionType -from LLVMContext import LLVMContext -from CallingConv import CallingConv +from .namespace import llvm +from .Value import GlobalValue, Constant, Function, Argument, Value +from .BasicBlock import BasicBlock +from .Attributes import Attributes +from .Type import Type +from .DerivedTypes import FunctionType +from .LLVMContext import LLVMContext +from .CallingConv import CallingConv @Function class Function: diff --git a/llvmpy/src/GenericValue.py b/llvmpy/src/GenericValue.py index 73a3709..e587b5f 100644 --- a/llvmpy/src/GenericValue.py +++ b/llvmpy/src/GenericValue.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from Type import Type +from .namespace import llvm +from .Type import Type GenericValue = llvm.Class() diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index f21d5af..2583c6a 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Value import GlobalValue -from Module import Module -from ADT.StringRef import StringRef +from .namespace import llvm +from .Value import GlobalValue +from .Module import Module +from .ADT.StringRef import StringRef @GlobalValue class GlobalValue: diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index 2280e24..c38df27 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -1,13 +1,13 @@ from binding import * -from namespace import llvm +from .namespace import llvm -from GlobalValue import GlobalValue +from .GlobalValue import GlobalValue GlobalVariable = llvm.Class(GlobalValue) -from Module import Module -from Type import Type -from ADT.StringRef import StringRef -from Value import Constant +from .Module import Module +from .Type import Type +from .ADT.StringRef import StringRef +from .Value import Constant @GlobalVariable class GlobalVariable: diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index efdf453..afd78a0 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -1,18 +1,18 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from BasicBlock import BasicBlock -from Instruction import Instruction -from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst -from Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode -from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst -from Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst -from Instruction import LandingPadInst, VAArgInst -from Instruction import AtomicOrdering, SynchronizationScope -from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned -from ADT.StringRef import StringRef -from Value import Value, MDNode -from Type import Type, IntegerType +from .namespace import llvm +from .LLVMContext import LLVMContext +from .BasicBlock import BasicBlock +from .Instruction import Instruction +from .Instruction import ReturnInst, CallInst, BranchInst, SwitchInst +from .Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode +from .Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst +from .Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst +from .Instruction import LandingPadInst, VAArgInst +from .Instruction import AtomicOrdering, SynchronizationScope +from .ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from .ADT.StringRef import StringRef +from .Value import Value, MDNode +from .Type import Type, IntegerType IRBuilder = llvm.Class() diff --git a/llvmpy/src/InlineAsm.py b/llvmpy/src/InlineAsm.py index a4ce16b..8793343 100644 --- a/llvmpy/src/InlineAsm.py +++ b/llvmpy/src/InlineAsm.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Value import Value -from DerivedTypes import FunctionType -from ADT.StringRef import StringRef +from .namespace import llvm +from .Value import Value +from .DerivedTypes import FunctionType +from .ADT.StringRef import StringRef llvm.includes.add('llvm/InlineAsm.h') diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 4761e16..1974aad 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from Value import Value, MDNode, User, BasicBlock, Function, ConstantInt +from .namespace import llvm +from .Value import Value, MDNode, User, BasicBlock, Function, ConstantInt Instruction = llvm.Class(User) @@ -63,10 +63,10 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', -from ADT.StringRef import StringRef -from CallingConv import CallingConv -from Attributes import Attributes -from Type import Type +from .ADT.StringRef import StringRef +from .CallingConv import CallingConv +from .Attributes import Attributes +from .Type import Type diff --git a/llvmpy/src/Intrinsics.py b/llvmpy/src/Intrinsics.py index 5314112..7e1decd 100644 --- a/llvmpy/src/Intrinsics.py +++ b/llvmpy/src/Intrinsics.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm +from .namespace import llvm -from Module import Module -from Function import Function +from .Module import Module +from .Function import Function Intrinsic = llvm.Namespace('Intrinsic') diff --git a/llvmpy/src/JITMemoryManager.py b/llvmpy/src/JITMemoryManager.py index f134735..e34e678 100644 --- a/llvmpy/src/JITMemoryManager.py +++ b/llvmpy/src/JITMemoryManager.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm @llvm.Class() class JITMemoryManager: diff --git a/llvmpy/src/LLVMContext.py b/llvmpy/src/LLVMContext.py index f2526db..4a6b49a 100644 --- a/llvmpy/src/LLVMContext.py +++ b/llvmpy/src/LLVMContext.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm @llvm.Class() class LLVMContext: diff --git a/llvmpy/src/Linker.py b/llvmpy/src/Linker.py index acca503..960bd90 100644 --- a/llvmpy/src/Linker.py +++ b/llvmpy/src/Linker.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from ADT.StringRef import StringRef -from Module import Module -from LLVMContext import LLVMContext +from .namespace import llvm +from .ADT.StringRef import StringRef +from .Module import Module +from .LLVMContext import LLVMContext llvm.includes.add('llvm/Linker.h') diff --git a/llvmpy/src/Metadata.py b/llvmpy/src/Metadata.py index d5cc4b1..cfeb6ce 100644 --- a/llvmpy/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from Value import Value, MDNode, MDString -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from Module import Module -from Function import Function -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from .namespace import llvm +from .Value import Value, MDNode, MDString +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .Module import Module +from .Function import Function +from .Support.raw_ostream import raw_ostream +from .Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: diff --git a/llvmpy/src/Module.py b/llvmpy/src/Module.py index d68be36..46fad5a 100644 --- a/llvmpy/src/Module.py +++ b/llvmpy/src/Module.py @@ -1,18 +1,18 @@ from binding import * -from namespace import llvm +from .namespace import llvm Module = llvm.Class() -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from Constant import Constant -from GlobalVariable import GlobalVariable -from Function import Function -from DerivedTypes import FunctionType -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter -from Type import Type, StructType -from Metadata import NamedMDNode +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .Constant import Constant +from .GlobalVariable import GlobalVariable +from .Function import Function +from .DerivedTypes import FunctionType +from .Support.raw_ostream import raw_ostream +from .Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from .Type import Type, StructType +from .Metadata import NamedMDNode @Module class Module: diff --git a/llvmpy/src/Pass.py b/llvmpy/src/Pass.py index f36856c..ad03d9a 100644 --- a/llvmpy/src/Pass.py +++ b/llvmpy/src/Pass.py @@ -1,14 +1,14 @@ from binding import * -from namespace import llvm +from .namespace import llvm Pass = llvm.Class() ModulePass = llvm.Class(Pass) FunctionPass = llvm.Class(Pass) ImmutablePass = llvm.Class(ModulePass) -from ADT.StringRef import StringRef -from Module import Module -from Value import Function +from .ADT.StringRef import StringRef +from .Module import Module +from .Value import Function @Pass class Pass: diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index 91a98f4..4d59e9f 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Pass import Pass -from Module import Module -from Value import Function +from .namespace import llvm +from .Pass import Pass +from .Module import Module +from .Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) diff --git a/llvmpy/src/PassRegistry.py b/llvmpy/src/PassRegistry.py index 495de51..ede026c 100644 --- a/llvmpy/src/PassRegistry.py +++ b/llvmpy/src/PassRegistry.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm from src.ADT.StringRef import StringRef PassRegistry = llvm.Class() diff --git a/llvmpy/src/PassSupport.py b/llvmpy/src/PassSupport.py index 8dba872..d239a6d 100644 --- a/llvmpy/src/PassSupport.py +++ b/llvmpy/src/PassSupport.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm PassInfo = llvm.Class() diff --git a/llvmpy/src/Support/FormattedStream.py b/llvmpy/src/Support/FormattedStream.py index 26f906d..3e9159b 100644 --- a/llvmpy/src/Support/FormattedStream.py +++ b/llvmpy/src/Support/FormattedStream.py @@ -1,6 +1,6 @@ from binding import * from ..namespace import llvm -from raw_ostream import raw_ostream +from .raw_ostream import raw_ostream @llvm.Class(raw_ostream) class formatted_raw_ostream: diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index 8e62137..ea1f0e5 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from Support.raw_ostream import raw_ostream -from ADT.StringRef import StringRef +from .namespace import llvm +from .LLVMContext import LLVMContext +from .Support.raw_ostream import raw_ostream +from .ADT.StringRef import StringRef Type = llvm.Class() IntegerType = llvm.Class(Type) diff --git a/llvmpy/src/User.py b/llvmpy/src/User.py index 9a077c1..1d3cc1f 100644 --- a/llvmpy/src/User.py +++ b/llvmpy/src/User.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from Value import Value, User +from .namespace import llvm +from .Value import Value, User @User class User: diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index b10807a..669ed80 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm # forward declarations Value = llvm.Class() @@ -21,11 +21,11 @@ ConstantDataSequential = llvm.Class(Constant) ConstantDataArray = llvm.Class(ConstantDataSequential) ConstantExpr = llvm.Class(Constant) -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter -from Type import Type -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef +from .Support.raw_ostream import raw_ostream +from .Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from .Type import Type +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef @Value diff --git a/llvmpy/src/__init__.py b/llvmpy/src/__init__.py index ed34608..36bc12f 100644 --- a/llvmpy/src/__init__.py +++ b/llvmpy/src/__init__.py @@ -3,11 +3,12 @@ import os.path def _init(root=__name__, file=__file__): base = os.path.dirname(file) for fname in os.listdir(base): - print fname is_python_script = fname.endswith('.py') or fname.endswith('.pyc') is_init_script = fname.startswith('__init__') is_directory = os.path.isdir(os.path.join(base, fname)) - if (is_directory or is_python_script) and not is_init_script : + is_python_module = is_directory and not fname.startswith('__') + if (is_python_module or is_python_script) and not is_init_script: + print(fname) modname = os.path.basename(fname).rsplit('.', 1)[0] #importlib.import_module('.' + modname, __name__) __import__('.'.join([root, modname])) diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index 8eb56f6..c7ceb49 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -1,9 +1,10 @@ -from StringIO import StringIO +from io import BytesIO, StringIO from llvmpy.api import llvm from llvmpy import extra from llvmpy import _capsule import llvmpy.capsule +import collections llvmpy.capsule.set_debug(True) @@ -14,19 +15,19 @@ def test_basic_jit_use(): context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) - print m.getModuleIdentifier() + print(m.getModuleIdentifier()) m.setModuleIdentifier('modname2') - print m.getModuleIdentifier() - print 'endianness', m.getEndianness() + print(m.getModuleIdentifier()) + print('endianness', m.getEndianness()) assert m.getEndianness() == llvm.Module.Endianness.AnyEndianness - print 'pointer-size', m.getPointerSize() + print('pointer-size', m.getPointerSize()) assert m.getPointerSize() == llvm.Module.PointerSize.AnyPointerSize m.dump() os = extra.make_raw_ostream_for_printing() m.print_(os, None) - print os.str() + print(os.str()) int1ty = llvm.Type.getInt1Ty(context) @@ -40,11 +41,11 @@ def test_basic_jit_use(): types = [llvm.Type.getIntNTy(context, 8), llvm.Type.getIntNTy(context, 32)] fnty = llvm.FunctionType.get(llvm.Type.getIntNTy(context, 8), types, False) - print fnty + print(fnty) const = m.getOrInsertFunction("foo", fnty) fn = const._downcast(llvm.Function) - print fn + print(fn) assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') @@ -63,7 +64,7 @@ def test_basic_jit_use(): assert len(fn_uselist) == 0 builder = llvm.IRBuilder.new(context) - print builder + print(builder) bb = llvm.BasicBlock.Create(context, "entry", fn, None) assert bb.empty() @@ -72,19 +73,19 @@ def test_basic_jit_use(): assert bb.getTerminator() is None arg0, arg1 = fn.getArgumentList() - print arg0, arg1 + print(arg0, arg1) extended = builder.CreateZExt(arg0, arg1.getType()) result = builder.CreateAdd(extended, arg1) ret = builder.CreateTrunc(result, fn.getReturnType()) builder.CreateRet(ret) - print arg0.list_use() + print(arg0.list_use()) - print fn + print(fn) errio = StringIO() - print m + print(m) # verifier action = llvm.VerifierFailureAction.ReturnStatusAction @@ -92,7 +93,7 @@ def test_basic_jit_use(): corrupted = llvm.verifyFunction(fn, action) assert not corrupted corrupted = llvm.verifyModule(m, action, errio) - print corrupted + print(corrupted) assert not corrupted, errio.getvalue() # build pass manager @@ -114,13 +115,13 @@ def test_basic_jit_use(): pm.run(m) - print m + print(m) # build engine ee = llvm.ExecutionEngine.createJIT(m, errio) - print ee, errio.getvalue() - print ee.getDataLayout().getStringRepresentation() + print(ee, errio.getvalue()) + print(ee.getDataLayout().getStringRepresentation()) datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' @@ -149,7 +150,7 @@ def test_basic_jit_use(): assert 44 == gvR.toUnsignedInt() # write bitcode - bc_buffer = StringIO() + bc_buffer = BytesIO() llvm.WriteBitcodeToFile(m, bc_buffer) bc = bc_buffer.getvalue() bc_buffer.close() @@ -187,7 +188,7 @@ def test_engine_builder(): builder.SetInsertPoint(bb) builder.CreateRet(fn.getArgumentList()[0]) - print fn + print(fn) eb = llvm.EngineBuilder.new(m) eb2 = eb.setEngineKind(llvm.EngineKind.Kind.JIT) @@ -196,13 +197,13 @@ def test_engine_builder(): tm = eb.selectTarget() - print 'target triple:', tm.getTargetTriple() - print 'target cpu:', tm.getTargetCPU() - print 'target feature string:', tm.getTargetFeatureString() + print('target triple:', tm.getTargetTriple()) + print('target cpu:', tm.getTargetCPU()) + print('target feature string:', tm.getTargetFeatureString()) target = tm.getTarget() - print 'target name:', target.getName() - print 'target short description:', target.getShortDescription() + print('target name:', target.getName()) + print('target short description:', target.getShortDescription()) assert target.hasJIT() assert target.hasTargetMachine() @@ -218,7 +219,7 @@ def test_engine_builder(): triple_32variant = triple.get32BitArchVariant() assert triple_32variant.isArch32Bit() - print tm.getDataLayout() + print(tm.getDataLayout()) pm = llvm.PassManager.new() pm.add(llvm.DataLayout.new(str(tm.getDataLayout()))) @@ -240,7 +241,7 @@ def test_engine_builder(): formatted.flush() raw.flush() asm = raw.str() - print asm + print(asm) assert 'foo' in asm @@ -301,7 +302,7 @@ def test_globalvariable(): gvar2 = m.getNamedGlobal('apple') assert gvar2 is gvar - print m.list_globals() + print(m.list_globals()) def test_sequentialtypes(): @@ -345,9 +346,9 @@ def test_passregistry(): passinfo = passreg.getPassInfo("dce") dcepass = passinfo.createPass() - print dcepass.getPassName() + print(dcepass.getPassName()) - print passreg.enumerate() + print(passreg.enumerate()) def test_targetregistry(): llvm.TargetRegistry.printRegisteredTargetsForVersion() @@ -356,15 +357,15 @@ def test_targetregistry(): target = llvm.TargetRegistry.getClosestTargetForJIT(errmsg) errmsg.close() - print target.getName() - print target.getShortDescription() + print(target.getName()) + print(target.getShortDescription()) assert target.hasJIT() assert target.hasTargetMachine() next = target.getNext() if next: - print next.getName() - print next.getShortDescription() + print(next.getName()) + print(next.getShortDescription()) triple = llvm.sys.getDefaultTargetTriple() cpu = llvm.sys.getHostCPUName() @@ -375,9 +376,9 @@ def test_targetregistry(): tm = target.createTargetMachine(triple, cpu, "", targetoptions) def main(): - for name, value in globals().items(): - if name.startswith('test_') and callable(value): - print name.center(80, '-') + for name, value in list(globals().items()): + if name.startswith('test_') and isinstance(value, collections.Callable): + print(name.center(80, '-')) value() From 6c07747a3b906e649a09aacd3f3b2f90b2ddc10d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 23 Feb 2013 21:52:23 +0200 Subject: [PATCH 118/338] Typo fix - could *not* invoke llvm-config. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6802391..3757770 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def run_llvm_config(extra_args): try: p = Popen(args, stdout=PIPE, stderr=PIPE) except OSError: - sys.exit("Error: could invoke %r\n" + sys.exit("Error: could not invoke %r\n" "Try setting LLVM_CONFIG_PATH=/path/to/llvm-config" % args) stdout, stderr = p.communicate() if stderr: From fccf439117016e605a8b763b3dffcd94a35506ad Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 23 Feb 2013 23:08:30 +0200 Subject: [PATCH 119/338] Add missing titles to few docs to make sure they're rendered in docs. --- docs/source/doc/llvm.core.Constant.rst | 3 +++ docs/source/doc/llvm.core.GlobalVariable.rst | 3 +++ docs/source/doc/llvm.core.Module.rst | 4 +++- docs/source/doc/llvm.core.StructType.rst | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/source/doc/llvm.core.Constant.rst b/docs/source/doc/llvm.core.Constant.rst index 4f2ed08..9b479c2 100644 --- a/docs/source/doc/llvm.core.Constant.rst +++ b/docs/source/doc/llvm.core.Constant.rst @@ -4,6 +4,9 @@ | title: Constant (llvm.core) | +-------------------------------+ +llvm.core.Constant +================== + ``Constant``-s represents constants that appear within the code. The values of such objects are known at creation time. Constants can be created from Python constants. A constant expression is also a constant diff --git a/docs/source/doc/llvm.core.GlobalVariable.rst b/docs/source/doc/llvm.core.GlobalVariable.rst index 392a6a0..48c8255 100644 --- a/docs/source/doc/llvm.core.GlobalVariable.rst +++ b/docs/source/doc/llvm.core.GlobalVariable.rst @@ -4,6 +4,9 @@ | title: GlobalVariable (llvm.core) | +-------------------------------------+ +llvm.core.GlobalVariable +======================== + Global variables (``llvm.core.GlobalVariable``) are subclasses of `llvm.core.GlobalValue `_ and represent module-level variables. These can have optional initializers and can be diff --git a/docs/source/doc/llvm.core.Module.rst b/docs/source/doc/llvm.core.Module.rst index 3dbd5c8..824b6cd 100644 --- a/docs/source/doc/llvm.core.Module.rst +++ b/docs/source/doc/llvm.core.Module.rst @@ -4,11 +4,13 @@ | title: Module (llvm.core) | +-----------------------------+ +llvm.core.Module +================ + Modules are top-level container objects. You need to create a module object first, before you can add global variables, aliases or functions. Modules are created using the static method ``Module.new``: - .. code-block:: python #!/usr/bin/env python diff --git a/docs/source/doc/llvm.core.StructType.rst b/docs/source/doc/llvm.core.StructType.rst index e69de29..0ac3ce6 100644 --- a/docs/source/doc/llvm.core.StructType.rst +++ b/docs/source/doc/llvm.core.StructType.rst @@ -0,0 +1,3 @@ +llvm.core.StructType +==================== + From 650a49dcab6d4b5836fa7daa62be5c3ec4b94770 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 23 Feb 2013 23:13:23 +0200 Subject: [PATCH 120/338] Fix import statements. --- docs/source/doc/llvm.core.Module.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/doc/llvm.core.Module.rst b/docs/source/doc/llvm.core.Module.rst index 824b6cd..4052a4f 100644 --- a/docs/source/doc/llvm.core.Module.rst +++ b/docs/source/doc/llvm.core.Module.rst @@ -15,7 +15,8 @@ Modules are created using the static method ``Module.new``: #!/usr/bin/env python - from llvm import \* from llvm.core import \* + from llvm import * + from llvm.core import * # create a module my_module = Module.new('my_module') From 769376b0556cc7e2daea138723c9dfc3c2e3da1f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 24 Feb 2013 00:03:26 +0200 Subject: [PATCH 121/338] Sublists must have blank lines before and after. --- docs/source/doc/llvm_concepts.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/doc/llvm_concepts.rst b/docs/source/doc/llvm_concepts.rst index c642994..8690e49 100644 --- a/docs/source/doc/llvm_concepts.rst +++ b/docs/source/doc/llvm_concepts.rst @@ -28,6 +28,7 @@ follow these steps: - add a *basic block* to the function - using a helper object called an *instruction builder*, add two instructions into the basic block: + - an instruction to add the two arguments and store the result into a temporary variable - a return From 8086487ab742a743d02bbb9b3b9fd2104162da77 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 24 Feb 2013 00:08:28 +0200 Subject: [PATCH 122/338] Fix "title underline too short" warnings. --- docs/source/doc/examples/JITTutorial2.rst | 2 +- docs/source/doc/kaleidoscope/PythonLangImpl1.rst | 2 +- docs/source/doc/kaleidoscope/PythonLangImpl8.rst | 10 +++++----- docs/source/doc/llvm_cbuilder.rst | 2 +- docs/source/index.rst | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/doc/examples/JITTutorial2.rst b/docs/source/doc/examples/JITTutorial2.rst index a9a9979..6e76150 100644 --- a/docs/source/doc/examples/JITTutorial2.rst +++ b/docs/source/doc/examples/JITTutorial2.rst @@ -1,5 +1,5 @@ A More Complicated Function -==================== +=========================== .. code-block:: python diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl1.rst b/docs/source/doc/kaleidoscope/PythonLangImpl1.rst index 00b16fb..ae4b80d 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl1.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl1.rst @@ -6,7 +6,7 @@ Written by `Chris Lattner `_ and `Max Shawabkeh `_ Introduction -========= +============ Welcome to the "Implementing a language with LLVM" tutorial. This tutorial runs through the implementation of a simple language, showing diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl8.rst b/docs/source/doc/kaleidoscope/PythonLangImpl8.rst index dd4abc1..eb13dd0 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl8.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl8.rst @@ -1,6 +1,6 @@ -************************************************* +*************************************************** Chapter 8: Conclusion and other useful LLVM tidbits -************************************************* +*************************************************** Written by Chris Lattner @@ -106,7 +106,7 @@ generating LLVM IR. These are some of the more subtle things that may not be obv but are very useful if you want to take advantage of LLVM's capabilities. Properties of the LLVM IR -======================== +========================= We have a couple common questions about code in the LLVM IR form - let's just get these out of the way right now, shall we? @@ -164,7 +164,7 @@ This can make sense for specialized domains such as an in-kernel language. -------------- Safety Guarantees ----------------- +----------------- Many of the languages above are also "safe" languages: it is impossible for a program written in Java to corrupt its address space and @@ -236,7 +236,7 @@ you desire in your front-end, on the language-specific AST. -------------- Tips and Tricks -============== +=============== There is a variety of useful tips and tricks that you come to know after working on/with LLVM that aren't obvious at first glance. diff --git a/docs/source/doc/llvm_cbuilder.rst b/docs/source/doc/llvm_cbuilder.rst index 990bfb0..c8623c2 100644 --- a/docs/source/doc/llvm_cbuilder.rst +++ b/docs/source/doc/llvm_cbuilder.rst @@ -1,5 +1,5 @@ llvm_cbuilder -========= +============= llvm_cbuilder is a set of Python-contexts you can use to write C-like constructs in Python which generates llvmpy code directly. diff --git a/docs/source/index.rst b/docs/source/index.rst index 9f86b32..7798b77 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -4,7 +4,7 @@ contain the root `toctree` directive. Documentation for llvmpy -================= +======================== Contents: From d74ff4dc2bebee2a7ceabaafaebc6dd5c5db8538 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 24 Feb 2013 00:22:54 +0200 Subject: [PATCH 123/338] Fill in required explicit argument for code-block. --- docs/source/doc/kaleidoscope/PythonLangImpl7.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst index 629608c..7e86ee4 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst @@ -295,7 +295,7 @@ variables is a useful thing regardless of whether you will be mutating them. Here's a motivating example that shows how we could use these: -.. code-block:: +.. code-block:: none # Define ':' for sequencing: as a low-precedence operator that ignores operands # and just returns the RHS. @@ -352,7 +352,7 @@ function that ensures that the allocas are created in the entry block of the function: -.. code-block:: +.. code-block:: python # Creates an alloca instruction in the entry block of the function. This is used # for mutable variables. @@ -475,7 +475,7 @@ It is interesting to see what the code looks like before and after the mem2reg optimization runs. For example, this is the before/after code for our recursive fib function. Before the optimization: -.. code-block:: +.. code-block:: llvm define double @fib(double %x) { entry: @@ -515,7 +515,7 @@ still just make the PHI. Here is the code after the mem2reg pass runs: -.. code-block:: +.. code-block:: llvm define double @fib(double %x) { entry: @@ -651,7 +651,7 @@ Now that we have an assignment operator, we can mutate loop variables and arguments. For example, we can now run code like this: -.. code-block:: +.. code-block:: none # Function to print a double. extern printd(x) From d36cd1dbc7786b714da54a9cfd781f02045023c0 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 24 Feb 2013 00:40:25 +0200 Subject: [PATCH 124/338] Add docstring documentation to all llvm.core classes. Some classes have docstrings, and lack rST docs (e.g. Module), few others vice versa. It's unclear what is the best way to deal with this. IMHO, docstrings should prevail, i.e. existing docs would rather be moved to docstings. Anyway, for now just make sure that users don't miss documentation, even if it's just list of classmembers. --- docs/source/doc/llvm.core.Argument.rst | 7 +++++++ docs/source/doc/llvm.core.ArrayType.rst | 7 +++++++ docs/source/doc/llvm.core.BasicBlock.rst | 7 +++++++ docs/source/doc/llvm.core.Builder.rst | 7 +++++++ docs/source/doc/llvm.core.Constant.rst | 6 ++++++ docs/source/doc/llvm.core.Function.rst | 7 +++++++ docs/source/doc/llvm.core.FunctionType.rst | 7 +++++++ docs/source/doc/llvm.core.GlobalValue.rst | 6 ++++++ docs/source/doc/llvm.core.GlobalVariable.rst | 7 +++++++ docs/source/doc/llvm.core.Instruction.rst | 7 +++++++ docs/source/doc/llvm.core.IntegerType.rst | 7 +++++++ docs/source/doc/llvm.core.Module.rst | 7 +++++++ docs/source/doc/llvm.core.PointerType.rst | 7 +++++++ docs/source/doc/llvm.core.StructType.rst | 5 +++++ docs/source/doc/llvm.core.Type.rst | 7 +++++++ docs/source/doc/llvm.core.User.rst | 7 +++++++ docs/source/doc/llvm.core.Value.rst | 7 +++++++ docs/source/doc/llvm.core.VectorType.rst | 7 +++++++ 18 files changed, 122 insertions(+) diff --git a/docs/source/doc/llvm.core.Argument.rst b/docs/source/doc/llvm.core.Argument.rst index 2481665..a2ffbfa 100644 --- a/docs/source/doc/llvm.core.Argument.rst +++ b/docs/source/doc/llvm.core.Argument.rst @@ -56,3 +56,10 @@ Add an attribute ``attr`` to the argument, from the set listed above. ~~~~~~~~~~~~~~~~~~~~~~~~~~ Remove the attribute ``attr`` of the argument. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Argument + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.ArrayType.rst b/docs/source/doc/llvm.core.ArrayType.rst index f8b5e0c..3a4e645 100644 --- a/docs/source/doc/llvm.core.ArrayType.rst +++ b/docs/source/doc/llvm.core.ArrayType.rst @@ -28,3 +28,10 @@ A ``Type`` object representing the type of the element of the array. [read-only] The number of elements in the array. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.ArrayType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.BasicBlock.rst b/docs/source/doc/llvm.core.BasicBlock.rst index 74806a6..eb10be3 100644 --- a/docs/source/doc/llvm.core.BasicBlock.rst +++ b/docs/source/doc/llvm.core.BasicBlock.rst @@ -42,3 +42,10 @@ The parent function of this basicblock. ~~~~~~~~~~~~~~~~ A list of instructions in this basicblock. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.BasicBlock + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Builder.rst b/docs/source/doc/llvm.core.Builder.rst index 1e90908..24b9361 100644 --- a/docs/source/doc/llvm.core.Builder.rst +++ b/docs/source/doc/llvm.core.Builder.rst @@ -409,3 +409,10 @@ positioned. ~~~~~~~~~ Deprecated. Same as ``basic_block`` + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Builder + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Constant.rst b/docs/source/doc/llvm.core.Constant.rst index 9b479c2..ae67fa4 100644 --- a/docs/source/doc/llvm.core.Constant.rst +++ b/docs/source/doc/llvm.core.Constant.rst @@ -354,3 +354,9 @@ some examples: assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray) + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Constant + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Function.rst b/docs/source/doc/llvm.core.Function.rst index 1d6070c..cda101e 100644 --- a/docs/source/doc/llvm.core.Function.rst +++ b/docs/source/doc/llvm.core.Function.rst @@ -149,3 +149,10 @@ function bodies. Verifies the function. See `LLVM docs `_. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Function + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.FunctionType.rst b/docs/source/doc/llvm.core.FunctionType.rst index 8d40009..7b728a8 100644 --- a/docs/source/doc/llvm.core.FunctionType.rst +++ b/docs/source/doc/llvm.core.FunctionType.rst @@ -46,3 +46,10 @@ the function. Used like this: Type.int(), Type.int() ] ) for arg in func_type.args: assert arg.kind == TYPE_INTEGER assert arg == Type.int() assert func_type.arg_count == len(func_type.args) + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.FunctionType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.GlobalValue.rst b/docs/source/doc/llvm.core.GlobalValue.rst index 70dee7b..a5c2383 100644 --- a/docs/source/doc/llvm.core.GlobalValue.rst +++ b/docs/source/doc/llvm.core.GlobalValue.rst @@ -95,3 +95,9 @@ A power-of-2 integer indicating the boundary to align to. The module object to which this global belongs to. + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.GlobalValue + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.GlobalVariable.rst b/docs/source/doc/llvm.core.GlobalVariable.rst index 48c8255..1ba69d8 100644 --- a/docs/source/doc/llvm.core.GlobalVariable.rst +++ b/docs/source/doc/llvm.core.GlobalVariable.rst @@ -40,3 +40,10 @@ class, or by using the static method ``GlobalVariable.new``. # list all global variables in a module for gv in module_obj.global_variables: print gv.name, "of type", gv.type + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.GlobalVariable + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Instruction.rst b/docs/source/doc/llvm.core.Instruction.rst index 95aeb81..67c43f0 100644 --- a/docs/source/doc/llvm.core.Instruction.rst +++ b/docs/source/doc/llvm.core.Instruction.rst @@ -240,3 +240,10 @@ Properties The predicate of the compare instruction, one of the ``ICMP_*`` or ``FCMP_*`` constants. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Instruction + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.IntegerType.rst b/docs/source/doc/llvm.core.IntegerType.rst index f62907c..6f1e2b1 100644 --- a/docs/source/doc/llvm.core.IntegerType.rst +++ b/docs/source/doc/llvm.core.IntegerType.rst @@ -21,3 +21,10 @@ Properties [read-only] The width of the integer type, in number of bits. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.IntegerType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Module.rst b/docs/source/doc/llvm.core.Module.rst index 4052a4f..75cc174 100644 --- a/docs/source/doc/llvm.core.Module.rst +++ b/docs/source/doc/llvm.core.Module.rst @@ -20,3 +20,10 @@ Modules are created using the static method ``Module.new``: # create a module my_module = Module.new('my_module') + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Module + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.PointerType.rst b/docs/source/doc/llvm.core.PointerType.rst index a869fba..cc65139 100644 --- a/docs/source/doc/llvm.core.PointerType.rst +++ b/docs/source/doc/llvm.core.PointerType.rst @@ -29,3 +29,10 @@ The address space of the pointer. A `Type `_ object representing the type of the value pointed to. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.PointerType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.StructType.rst b/docs/source/doc/llvm.core.StructType.rst index 0ac3ce6..f3b0786 100644 --- a/docs/source/doc/llvm.core.StructType.rst +++ b/docs/source/doc/llvm.core.StructType.rst @@ -1,3 +1,8 @@ llvm.core.StructType ==================== +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.StructType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Type.rst b/docs/source/doc/llvm.core.Type.rst index 58883d7..b1eb354 100644 --- a/docs/source/doc/llvm.core.Type.rst +++ b/docs/source/doc/llvm.core.Type.rst @@ -126,3 +126,10 @@ Example: assert Type.int().kind == TYPE_INTEGER assert Type.void().kind == TYPE_VOID + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Type + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.User.rst b/docs/source/doc/llvm.core.User.rst index 0762729..12d40c5 100644 --- a/docs/source/doc/llvm.core.User.rst +++ b/docs/source/doc/llvm.core.User.rst @@ -37,3 +37,10 @@ The list of operands (values, of type The number of operands that this value referes to. Same as ``len(uses.operands)`` but faster if you just want the count. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.User + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Value.rst b/docs/source/doc/llvm.core.Value.rst index fdff4cc..081d328 100644 --- a/docs/source/doc/llvm.core.Value.rst +++ b/docs/source/doc/llvm.core.Value.rst @@ -63,3 +63,10 @@ representation. ``Value`` objects can be compared for equality. Internally, this converts both arguments into their LLVM assembly representations and compares the resultant strings. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Value + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.VectorType.rst b/docs/source/doc/llvm.core.VectorType.rst index 19b98e6..a18f6ea 100644 --- a/docs/source/doc/llvm.core.VectorType.rst +++ b/docs/source/doc/llvm.core.VectorType.rst @@ -29,3 +29,10 @@ element of the vector. [read-only] The number of elements in the vector. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.VectorType + :members: + :undoc-members: From 4e87b5170aa027f71301556d5b60b3b12a7d40ed Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 24 Feb 2013 00:43:43 +0200 Subject: [PATCH 125/338] Allow Sphinx build docs with docstrings without installing module. --- docs/source/conf.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 5c5c38d..830f1ad 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,12 +11,22 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys, os, glob # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +#sys.path.insert(0, os.path.abspath('../..')) + +# Support sphinx.ext.autodoc to extract docstrings from modules without installing +# complete package. +# The python modules depend on _core, so we must build entire package first though. +built_lib = glob.glob('../../build/lib.*/') +if not built_lib: + print "WARNING: To build complete documentation you must build package first" +else: + # lib dir has platform suffix + sys.path.insert(0, os.path.abspath(built_lib[0])) # -- General configuration ----------------------------------------------------- From d270f47328820bfa7da6477a142555d4ebb646b9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Feb 2013 13:21:42 -0600 Subject: [PATCH 126/338] Fix writing to file-like obj in python3.3 --- llvmpy/include/llvm_binding/conversion.h | 2 +- llvmpy/include/llvm_binding/extra.h | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index abc3749..1c629b7 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -9,7 +9,7 @@ int py_bytes_to(PyObject *bytesobj, llvm::StringRef &strref){ // type check if (!PyBytes_Check(bytesobj)) { // raises TypeError - PyErr_SetString(PyExc_TypeError, "Expecting a str"); + PyErr_SetString(PyExc_TypeError, "Expecting a bytes"); return 0; } // get len and buffer diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 3874bb3..b33a8a0 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -477,9 +477,13 @@ PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx, if (FObj) { std::string ErrStr; M = ParseBitcodeFile(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 { M = ParseBitcodeFile(MB, Ctx); } @@ -497,9 +501,8 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) llvm::WriteBitcodeToFile(M, rso); rso.flush(); StringRef ref = rso.str(); - PyObject* buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); - puts(PyString_AsString(PyObject_Str(PyObject_Type(buf)))); - return PyObject_CallMethod(FObj, "write", "O", buf); + auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); + return PyObject_CallMethod(FObj, "write", "O", *buf); } static From c1b46e4384958a37493dc9130710f2eecac7624d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 25 Feb 2013 10:02:49 -0600 Subject: [PATCH 127/338] Fix test --- llvmpy/test_binding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index c7ceb49..aee0167 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -156,7 +156,7 @@ def test_basic_jit_use(): bc_buffer.close() # read bitcode - errbuf = StringIO() + errbuf = BytesIO() m2 = llvm.ParseBitCodeFile(bc, context, errbuf) if not m2: raise Exception(errbuf.getvalue()) From 894539681b92314c6255bf6154fb9232cef2d313 Mon Sep 17 00:00:00 2001 From: Jon Riehl Date: Tue, 26 Feb 2013 15:48:00 -0600 Subject: [PATCH 128/338] Modified documentation configuration to search for build specific to Python version. Updated copyright. First attempt at using llvm._version to set documentation version. --- docs/source/conf.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 830f1ad..701ef80 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,9 +21,10 @@ import sys, os, glob # Support sphinx.ext.autodoc to extract docstrings from modules without installing # complete package. # The python modules depend on _core, so we must build entire package first though. -built_lib = glob.glob('../../build/lib.*/') +built_lib = glob.glob('../../build/lib.*-%d.%d/' % sys.version_info[:2]) if not built_lib: - print "WARNING: To build complete documentation you must build package first" + sys.stderr.write("WARNING: To build complete documentation you must build " + "package first\n") else: # lib dir has platform suffix sys.path.insert(0, os.path.abspath(built_lib[0])) @@ -51,16 +52,22 @@ master_doc = 'index' # General information about the project. project = u'llvmpy' -copyright = u'2012, Mahadevan R (2008-2010), Continuum Analytics (2012)' +copyright = u'2013, Mahadevan R (2008-2010), Continuum Analytics (2012-2013)' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. -version = '0.9' -# The full version, including alpha/beta/rc tags. -release = '0.9.0' +try: + import llvm + version_strs = llvm.__version__.split('.') + # The short X.Y version. + version = '.'.join(version_strs[:2]) + # The full version, including alpha/beta/rc tags. + release = '%s.%s' % (version, '-'.join(version_strs[2].split('-')[:2])) +except ImportError: + version = 'unknown-version' + release = 'unknown-release' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From dd9ba65328f18c881318ebeddcee73d2b48217b2 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 26 Feb 2013 18:43:49 -0600 Subject: [PATCH 129/338] Bug fixes --- llvm/core.py | 2 +- llvmpy/include/llvm_binding/conversion.h | 4 ++-- llvmpy/src/Instruction.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index f38028b..268318a 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1729,7 +1729,7 @@ class CallOrInvokeInstruction(Instruction): return _make_value(function) def _set_called_function(self, function): - self._ptr.setCalledFunction(function) + self._ptr.setCalledFunction(function._ptr) called_function = property(_get_called_function, _set_called_function) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 1c629b7..5395a3f 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -124,8 +124,8 @@ int py_int_to(PyObject *intobj, unsigned & val){ static int py_int_to(PyObject *intobj, unsigned long long & val){ if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { - // raise TypeError - PyErr_SetString(PyExc_TypeError, "Expecting an int 2"); + // raise TypeError; + PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; } val = PyInt_AsUnsignedLongLongMask(intobj); diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 1974aad..beb94f1 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -134,7 +134,7 @@ class BinaryOperator: @CallInst class CallInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) @@ -277,7 +277,7 @@ class IndirectBrInst: @InvokeInst class InvokeInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) From c3a08a446fead9268a136aeac4f853097ca4bf78 Mon Sep 17 00:00:00 2001 From: cuda Date: Wed, 27 Feb 2013 11:28:07 -0600 Subject: [PATCH 130/338] Fix import and Makefile on Linux --- llvmpy/Makefile | 3 +-- llvmpy/src/PassManager.py | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvmpy/Makefile b/llvmpy/Makefile index 9de1fb0..e9cc1c3 100644 --- a/llvmpy/Makefile +++ b/llvmpy/Makefile @@ -10,8 +10,7 @@ api.cpp api/__init__.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/bindin clean: cleantemp rm -f _api.so _capsule.so - rm -rf api - py_clean + rm -rf api cleantemp: rm -f api.cpp diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index 4d59e9f..760f080 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -1,13 +1,15 @@ from binding import * from .namespace import llvm -from .Pass import Pass -from .Module import Module -from .Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) FunctionPassManager = llvm.Class(PassManagerBase) +from .Pass import Pass +from .Module import Module +from .Value import Function + + @PassManagerBase class PassManagerBase: _include_ = 'llvm/PassManager.h' From 740d2595eeae16592b0ae7d2dbdd43e0b6d0ef18 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 13:25:19 -0600 Subject: [PATCH 131/338] Replace StringIO with BytesIO --- llvm/core.py | 21 +++++++++------------ llvm/ee.py | 9 +++------ llvm/test_llvmpy.py | 15 +++++---------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 268318a..49b5561 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -28,10 +28,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO +from io import BytesIO import contextlib, weakref import llvm @@ -337,7 +334,7 @@ class Module(llvm.Wrapper): bc = fileobj_or_str else: bc = fileobj_or_str.read() - errbuf = StringIO() + errbuf = BytesIO() context = api.llvm.getGlobalContext() m = api.llvm.ParseBitCodeFile(bc, context, errbuf) if not m: @@ -359,7 +356,7 @@ class Module(llvm.Wrapper): ir = fileobj_or_str else: ir = fileobj_or_str.read() - errbuf = StringIO() + errbuf = BytesIO() context = api.llvm.getGlobalContext() m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDiagnostic.new(), context) @@ -432,7 +429,7 @@ class Module(llvm.Wrapper): enum_mode = api.llvm.Linker.LinkerMode mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource - with contextlib.closing(StringIO()) as errmsg: + with contextlib.closing(BytesIO()) as errmsg: failed = api.llvm.Linker.LinkModules(self._ptr, other._ptr, mode, @@ -512,7 +509,7 @@ class Module(llvm.Wrapper): Checks module for errors. Raises `llvm.LLVMException' on any error.""" action = api.llvm.VerifierFailureAction.ReturnStatusAction - errio = StringIO() + errio = BytesIO() broken = api.llvm.verifyModule(self._ptr, action, errio) if broken: raise llvm.LLVMException(errio.getvalue()) @@ -530,7 +527,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = StringIO + fileobj = BytesIO api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() @@ -571,7 +568,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = StringIO() + fileobj = BytesIO() from llvm.ee import TargetMachine tm = TargetMachine.new() fileobj.write(tm.emit_object(self)) @@ -588,7 +585,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = StringIO() + fileobj = BytesIO() from llvm.ee import TargetMachine tm = TargetMachine.new() fileobj.write(tm.emit_assembly(self)) @@ -2269,7 +2266,7 @@ def load_library_permanently(filename): Load the given shared library (filename argument specifies the full path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" - with contextlib.closing(StringIO()) as errmsg: + with contextlib.closing(BytesIO()) as errmsg: failed = api.llvm.sys.DynamicLibrary.LoadPermanentLibrary(filename, errmsg) if failed: diff --git a/llvm/ee.py b/llvm/ee.py index 8598ad9..030eacb 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -30,10 +30,7 @@ "Execution Engine and related classes." -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO +from io import BytesIO import contextlib import llvm @@ -244,7 +241,7 @@ class TargetMachine(llvm.Wrapper): triple = get_default_triple() if not cpu: cpu = get_host_cpu_name() - with contextlib.closing(StringIO()) as error: + with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(triple, error) if not target: raise llvm.LLVMException(error) @@ -273,7 +270,7 @@ class TargetMachine(llvm.Wrapper): use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` ''' triple = api.llvm.Triple.new() - with contextlib.closing(StringIO()) as error: + with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error) if not target: raise llvm.LLVMException(error) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 5b26e39..8c9b800 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -10,13 +10,8 @@ import subprocess import tempfile import contextlib -is_py3k = bool(sys.version_info[0] == 3) BITS = tuple.__itemsize__ * 8 - -if is_py3k: - from io import StringIO -else: - from cStringIO import StringIO +from io import BytesIO import llvm @@ -123,7 +118,7 @@ class TestAttr(TestCase): ret void } """ - return Module.from_assembly(StringIO(test_module)) + return Module.from_assembly(BytesIO(test_module)) def test_align(self): m = self.make_module() @@ -255,7 +250,7 @@ entry: } """ def test_operands(self): - m = Module.from_assembly(StringIO(self.test_module)) + m = Module.from_assembly(BytesIO(self.test_module)) test_func = m.get_function_named("test_func") prod = m.get_function_named("prod") @@ -317,7 +312,7 @@ entry: } """ def test_passes(self): - m = Module.from_assembly(StringIO(self.asm)) + m = Module.from_assembly(BytesIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') @@ -365,7 +360,7 @@ entry: self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) def test_passes_with_pmb(self): - m = Module.from_assembly(StringIO(self.asm)) + m = Module.from_assembly(BytesIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') From 93cd20e9336e337016e0c73faf1172d017ba3e0b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 13:48:08 -0600 Subject: [PATCH 132/338] Fix for python 3 --- llvm/core.py | 25 +++++++++++++++++-------- llvm/ee.py | 2 +- llvm/passes.py | 1 - llvm/test_llvmpy.py | 33 +++++++++++++++++++-------------- test/inlineasm.py | 2 +- test/malloc.py | 2 +- test/tbaa.py | 2 +- test/test_debuginfo.py | 2 +- 8 files changed, 41 insertions(+), 28 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 49b5561..bed5763 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -29,6 +29,14 @@ # from io import BytesIO +try: + from StringIO import StringIO +except ImportError: + try: + from cStringIO import StringIO + except ImportError: + from io import StringIO + import contextlib, weakref import llvm @@ -468,7 +476,7 @@ class Module(llvm.Wrapper): @property def global_variables(self): - return map(_make_value, self._ptr.list_globals()) + return list(map(_make_value, self._ptr.list_globals())) def add_function(self, ty, name): """Add a function of given type with given name.""" @@ -501,7 +509,7 @@ class Module(llvm.Wrapper): @property def functions(self): """All functions in this module.""" - return map(_make_value, self._ptr.list_functions()) + return list(map(_make_value, self._ptr.list_functions())) def verify(self): """Verify module. @@ -585,10 +593,11 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = BytesIO() + fileobj = StringIO() from llvm.ee import TargetMachine tm = TargetMachine.new() - fileobj.write(tm.emit_assembly(self)) + asm = tm.emit_assembly(self) + fileobj.write(asm) if ret: return fileobj.getvalue() @@ -983,7 +992,7 @@ class Value(llvm.Wrapper): @property def uses(self): - return map(_make_value, self._ptr.list_use()) + return list(map(_make_value, self._ptr.list_use())) class User(Value): _type_ = api.llvm.User @@ -1458,7 +1467,7 @@ class Function(GlobalValue): @property def args(self): args = self._ptr.getArgumentList() - return map(_make_value, args) + return list(map(_make_value, args)) @property def basic_block_count(self): @@ -1480,7 +1489,7 @@ class Function(GlobalValue): @property def basic_blocks(self): - return map(_make_value, self._ptr.getBasicBlockList()) + return list(map(_make_value, self._ptr.getBasicBlockList())) def viewCFG(self): return self._ptr.viewCFG() @@ -1782,7 +1791,7 @@ class BasicBlock(Value): @property def instructions(self): - return map(_make_value, self._ptr.getInstList()) + return list(map(_make_value, self._ptr.getInstList())) #===----------------------------------------------------------------------=== # Value factory method diff --git a/llvm/ee.py b/llvm/ee.py index 030eacb..672a0b6 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -179,7 +179,7 @@ class ExecutionEngine(llvm.Wrapper): self._ptr.DisableLazyCompilation(disabled) def run_function(self, fn, args): - ptr = self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args))) return GenericValue(ptr) def get_pointer_to_function(self, fn): diff --git a/llvm/passes.py b/llvm/passes.py index 36e7d97..9f706d8 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -147,7 +147,6 @@ class PassManager(llvm.Wrapper): if not a_pass: assert pass_name not in PASSES, "Registered but not found?" raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) - print a_pass self._ptr.add(a_pass) def run(self, module): diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 8c9b800..3656621 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -11,7 +11,11 @@ import tempfile import contextlib BITS = tuple.__itemsize__ * 8 -from io import BytesIO + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO import llvm @@ -118,7 +122,8 @@ class TestAttr(TestCase): ret void } """ - return Module.from_assembly(BytesIO(test_module)) + buf = StringIO(test_module) + return Module.from_assembly(buf) def test_align(self): m = self.make_module() @@ -250,7 +255,7 @@ entry: } """ def test_operands(self): - m = Module.from_assembly(BytesIO(self.test_module)) + m = Module.from_assembly(StringIO(self.test_module)) test_func = m.get_function_named("test_func") prod = m.get_function_named("prod") @@ -312,7 +317,7 @@ entry: } """ def test_passes(self): - m = Module.from_assembly(BytesIO(self.asm)) + m = Module.from_assembly(StringIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') @@ -360,7 +365,7 @@ entry: self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) def test_passes_with_pmb(self): - m = Module.from_assembly(BytesIO(self.asm)) + m = Module.from_assembly(StringIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') @@ -626,7 +631,7 @@ class TestTargetMachines(TestCase): self.assertTrue(tm.target_data) self.assertTrue(tm.target_short_description) self.assertTrue(tm.triple) - self.assertIn('foo', tm.emit_assembly(m).decode('utf-8')) + self.assertIn('foo', tm.emit_assembly(m)) self.assertTrue(le.get_host_cpu_name()) def test_ptx(self): @@ -636,13 +641,13 @@ class TestTargetMachines(TestCase): arch = 'nvptx64' else: return # skip this test - print arch + print(arch) m, func = self._build_module() func.calling_convention = lc.CC_PTX_KERNEL # set calling conv ptxtm = le.TargetMachine.lookup(arch=arch, cpu='sm_20') self.assertTrue(ptxtm.triple) self.assertTrue(ptxtm.cpu) - ptxasm = ptxtm.emit_assembly(m).decode('utf-8') + ptxasm = ptxtm.emit_assembly(m) self.assertIn('foo', ptxasm) if lc.HAS_NVPTX: self.assertIn('.address_size 64', ptxasm) @@ -936,31 +941,31 @@ class TestCPUSupport(TestCase): def test_cpu_support2(self): features = 'sse3', 'sse41', 'sse42', 'avx' mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support3(self): features = 'sse41', 'sse42', 'avx' mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support4(self): features = 'sse42', 'avx' mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support5(self): features = 'avx', mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support6(self): features = [] mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) tests.append(TestCPUSupport) @@ -1235,4 +1240,4 @@ def run(verbosity=1): if __name__ == '__main__': - run() + unittest.main() diff --git a/test/inlineasm.py b/test/inlineasm.py index df91d71..64a4cbe 100644 --- a/test/inlineasm.py +++ b/test/inlineasm.py @@ -20,7 +20,7 @@ class TestInlineAsm(TestCase): inlineasm = InlineAsm.get(iaty, "bswap $0", "=r,r") self.assertIn('asm "bswap $0", "=r,r"', str(inlineasm)) builder.ret(builder.call(inlineasm, [fn.args[0]])) - print fn + print(fn) if __name__ == '__main__': unittest.main() diff --git a/test/malloc.py b/test/malloc.py index 1613a36..be37dcd 100644 --- a/test/malloc.py +++ b/test/malloc.py @@ -10,7 +10,7 @@ def test(): alloc = b.malloc_array(Type.int(), Constant.int(Type.int(), 10), 'hee') inst = b.free(alloc) b.ret_void() - print m + print(m) if __name__ == '__main__': test() diff --git a/test/tbaa.py b/test/tbaa.py index 242ed19..ad11081 100644 --- a/test/tbaa.py +++ b/test/tbaa.py @@ -29,7 +29,7 @@ class TestTBAABuilder(TestCase): bldr.ret_void() - print mod + print(mod) if __name__ == '__main__': unittest.main() diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index 33dbbdb..b6a5d6f 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -122,7 +122,7 @@ def debug_in_gdb(lfunc): # Now let's compile and run! retval = ee.run_function(lfunc, [arg1]) - print retval.as_real(float_type) + print(retval.as_real(float_type)) if __name__ == '__main__': From 5d83d626f6ff22fc3c74d18e45fad392ad5fd75f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 14:20:45 -0600 Subject: [PATCH 133/338] Update setup script --- llvmpy/build.py | 8 ++++++++ setup.py | 33 +++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 llvmpy/build.py diff --git a/llvmpy/build.py b/llvmpy/build.py new file mode 100644 index 0000000..1021927 --- /dev/null +++ b/llvmpy/build.py @@ -0,0 +1,8 @@ +from os import chdir +from os.path import dirname +import sys, subprocess + +scriptdir = dirname(__file__) +chdir(scriptdir) + +subprocess.check_call([sys.executable, 'gen/gen.py', 'api', 'src']) diff --git a/setup.py b/setup.py index 3757770..9bcd9f0 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import os import sys -from subprocess import Popen, PIPE +from subprocess import Popen, PIPE, check_call from distutils.core import setup, Extension import versioneer @@ -141,22 +141,30 @@ if sys.platform == 'win32': else: macros.append(('_GNU_SOURCE', None)) +# auto generate bindings +check_call([sys.executable, 'llvmpy/build.py']) + extra_link_args = ldflags.split() kwds = dict( ext_modules = [ Extension( - name='llvm._core', - sources=['llvm/_core.cpp', 'llvm/wrap.cpp', 'llvm/extra.cpp'], + name='llvmpy._api', + sources=['llvmpy/api.cpp'], define_macros = macros, - include_dirs = ['/usr/include', incdir], + include_dirs = [incdir, 'llvmpy/include'], library_dirs = [libdir], libraries = libs_core, extra_objects = objs_core, extra_link_args = extra_link_args), - Extension(name='llvm._dwarf', - sources=['llvm/_dwarf.cpp'], - include_dirs=[incdir]) + Extension( + name='llvmpy._capsule', + sources=['llvmpy/capsule.cpp'], + include_dirs=['llvmpy/include'], + ) +# Extension(name='llvm._dwarf', +# sources=['llvm/_dwarf.cpp'], +# include_dirs=[incdir]) ], cmdclass = versioneer.get_cmdclass(), ) @@ -173,12 +181,17 @@ setup( name = 'llvmpy', version=versioneer.get_version(), description = 'Python bindings for LLVM', - author = 'R Mahadevan', + author = 'R Mahadevan, Siu Kwan Lam', maintainer = 'Continuum Analytics, Inc.', maintainer_email = 'llvmpy@continuum.io', url = 'http://www.llvmpy.org/', - packages = ['llvm', 'llvm_cbuilder', 'llpython'], - py_modules = ['llvm.core'], + packages = ['llvm', 'llvm_cbuilder', 'llpython', + 'llvmpy.api', 'llvmpy.api.llvm'], + py_modules = ['llvmpy', + 'llvmpy._capsule', + 'llvmpy._api', + 'llvmpy.capsule', + 'llvmpy.extra'], license = "BSD", classifiers = [ "Intended Audience :: Developers", From ae6dab8e509d54fc35f73b3a5924e182038aed91 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 14:53:49 -0600 Subject: [PATCH 134/338] Pass llvm version and ptx support to wrapper generator through environ --- llvmpy/gen/binding.py | 14 ++++++++++++++ llvmpy/src/Support/TargetSelect.py | 18 ++++++++++-------- setup.py | 12 ++++++++---- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 0f5c4fd..ab8e7aa 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -838,3 +838,17 @@ class Attr(object): writer.println() +# +# Pick-up environ var +# +PTX_SUPPORT = os.environ['LLVMPY_PTX_SUPPORT'] + +def _parse_llvm_version(ver): + import re + m = re.compile(r'(\d+)\.(\d+)').match(ver) + assert m + major, minor = m.groups() + return int(major), int(minor) + +LLVM_VERSION = _parse_llvm_version(os.environ['LLVMPY_LLVM_VERSION']) + diff --git a/llvmpy/src/Support/TargetSelect.py b/llvmpy/src/Support/TargetSelect.py index ca97c24..85e1d74 100644 --- a/llvmpy/src/Support/TargetSelect.py +++ b/llvmpy/src/Support/TargetSelect.py @@ -17,12 +17,14 @@ InitializeNativeTargetDisassembler = llvm.Function( #InitializeAllTargetMCs = llvm.Function('InitializeAllTargetMCs') #InitializeAllAsmPrinters = llvm.Function('InitializeAllAsmPrinters') -#LLVMInitializePTXTarget = default.Function('LLVMInitializePTXTarget') -#LLVMInitializePTXTargetInfo = default.Function('LLVMInitializePTXTargetInfo') -#LLVMInitializePTXTargetMC = default.Function('LLVMInitializePTXTargetMC') -#LLVMInitializePTXAsmPrinter = default.Function('LLVMInitializePTXAsmPrinter') +if PTX_SUPPORT == 'PTX': + LLVMInitializePTXTarget = default.Function('LLVMInitializePTXTarget') + LLVMInitializePTXTargetInfo = default.Function('LLVMInitializePTXTargetInfo') + LLVMInitializePTXTargetMC = default.Function('LLVMInitializePTXTargetMC') + LLVMInitializePTXAsmPrinter = default.Function('LLVMInitializePTXAsmPrinter') -LLVMInitializeNVPTXTarget = default.Function('LLVMInitializeNVPTXTarget') -LLVMInitializeNVPTXTargetInfo = default.Function('LLVMInitializeNVPTXTargetInfo') -LLVMInitializeNVPTXTargetMC = default.Function('LLVMInitializeNVPTXTargetMC') -LLVMInitializeNVPTXAsmPrinter = default.Function('LLVMInitializeNVPTXAsmPrinter') +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 9bcd9f0..6fa6653 100644 --- a/setup.py +++ b/setup.py @@ -97,7 +97,7 @@ def determine_to_use_dynlink(libdir, llvm_version): dynlink = determine_to_use_dynlink(libdir, llvm_version) - +ptx_support = '' if dynlink: print('Using dynamic linking') @@ -120,12 +120,13 @@ else: 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") - macros.append(('LLVM_DISABLE_PTX', None)) libs_core, objs_core = get_libs_and_objs( ['core', 'analysis', 'scalaropts', 'executionengine', @@ -136,14 +137,17 @@ else: if sys.platform == 'win32': # If no PTX lib got added, disable PTX in the build - if 'LLVMPTXCodeGen' not in libs_core: - macros.append(('LLVM_DISABLE_PTX', None)) + if 'LLVMPTXCodeGen' in libs_core: + ptx_support = 'ptx' else: macros.append(('_GNU_SOURCE', None)) # auto generate bindings +os.environ['LLVMPY_PTX_SUPPORT'] = ptx_support +os.environ['LLVMPY_LLVM_VERSION'] = llvm_version check_call([sys.executable, 'llvmpy/build.py']) +# generate shared objects extra_link_args = ldflags.split() kwds = dict( ext_modules = [ From d485c22b0870f75d429eea6a546d8479e4946b2d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 16:32:00 -0600 Subject: [PATCH 135/338] Add llvm.workaround package --- llvm/workaround/__init__.py | 0 llvm/workaround/avx_support.py | 60 ++++++++++++++++++++++++++++++++++ setup.py | 4 ++- 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 llvm/workaround/__init__.py create mode 100644 llvm/workaround/avx_support.py diff --git a/llvm/workaround/__init__.py b/llvm/workaround/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llvm/workaround/avx_support.py b/llvm/workaround/avx_support.py new file mode 100644 index 0000000..81cb936 --- /dev/null +++ b/llvm/workaround/avx_support.py @@ -0,0 +1,60 @@ +""" +Auto-detect avx and xsave + +According to Intel manual [0], both AVX and XSAVE features must be present to +use AVX instructions. + +References: + +[0] Intel Architecture Instruction Set Extensions Programming Reference + +http://software.intel.com/sites/default/files/m/a/b/3/4/d/41604-319433-012a.pdf + +""" + +import sys, os, subprocess + +def detect_avx_support(option='detect'): + '''Detect AVX support''' + option = os.environ.get('LLVMPY_AVX_SUPPORT', option).lower() + if option in ('disable', '0', 'false'): + return False + elif option in ('enable', '1', 'true'): + return True + else: # do detection + plat = sys.platform + if plat.startswith('darwin'): + return detect_osx_like() + elif plat.startswith('win32'): + return False # don't know how to detect in windows + else: + return detect_unix_like() + +def detect_unix_like(): + try: + info = open('/proc/cpuinfo') + except IOError: + return False + + for line in info: + if line.lstrip().startswith('flags'): + features = line.split() + if 'avx' in features and 'xsave' in features: + # enable AVX if flags contain AVX + return True + return False + +def detect_osx_like(): + try: + info = subprocess.Popen(['sysctl', '-n', 'machdep.cpu.features'], + stdout=subprocess.PIPE) + except OSError: + return False + + features = info.stdout.read() + features = features.split() + return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features + + +if __name__ == '__main__': + print("AVX support: %s" % detect_avx_support()) diff --git a/setup.py b/setup.py index 6fa6653..ea7edb6 100644 --- a/setup.py +++ b/setup.py @@ -189,7 +189,9 @@ setup( maintainer = 'Continuum Analytics, Inc.', maintainer_email = 'llvmpy@continuum.io', url = 'http://www.llvmpy.org/', - packages = ['llvm', 'llvm_cbuilder', 'llpython', + packages = ['llvm', 'llvm.workaround', + 'llvm_cbuilder', + 'llpython', 'llvmpy.api', 'llvmpy.api.llvm'], py_modules = ['llvmpy', 'llvmpy._capsule', From f3e7b39bc926a17ff4537fafb02e416492657a47 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 16:36:21 -0600 Subject: [PATCH 136/338] Update changelog --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 6c2cd14..d2e2263 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ 2013-02-XX 0.11.0: -------------------- * fix Python 3 support on Windows + * New llvm binding 2013-02-01 0.10.2: From 8073b67c96defdbee148b329a8f9bb2447487cfe Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 18:28:15 -0600 Subject: [PATCH 137/338] Fix test related to AVX instructions. --- llvm/test_llvmpy.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 3656621..509629c 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -964,9 +964,13 @@ class TestCPUSupport(TestCase): def test_cpu_support6(self): features = [] - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print('disable mattrs', mattrs) - self._template(mattrs) + from llvm.workaround.avx_support import detect_avx_support + if not detect_avx_support(): + print 'Skipping: no AVX' + else: + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print('disable mattrs', mattrs) + self._template(mattrs) tests.append(TestCPUSupport) From 9f9d5a6081c790e26ef6065d95ea1a6fb2496a8a Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 18:31:54 -0600 Subject: [PATCH 138/338] More fixes to disable AVX in tests --- llvm/test_llvmpy.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 509629c..27fd59c 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -923,7 +923,6 @@ class TestCPUSupport(TestCase): def _template(self, mattrs): mod, func = self._build_test_module() ee = self._build_engine(mod, mattrs=mattrs) - arg = le.GenericValue.real(Type.double(), 1.234) retval = ee.run_function(func, [arg]) @@ -987,7 +986,12 @@ class TestIntrinsicBasic(TestCase): def _template(self, mod, func, pyfunc): float = func.type.pointee.return_type - ee = le.ExecutionEngine.new(mod) + + from llvm.workaround.avx_support import detect_avx_support + if not detect_avx_support(): + ee = le.EngineBuilder.new(mod).mattrs("-avx").create() + else: + ee = le.EngineBuilder.new(mod).create() arg = le.GenericValue.real(float, 1.234) retval = ee.run_function(func, [arg]) golden = pyfunc(1.234) From cd8d622fc9005cca8be10a633834ccbfac64bb2f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 18:34:00 -0600 Subject: [PATCH 139/338] Fix mysin test for AVX support --- llvm/test_llvmpy.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 27fd59c..04170b4 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1152,7 +1152,13 @@ class TestIntrinsic(TestCase): # declare float @llvm.cos.f32(float) nounwind readnone # let's run the function - ee = le.ExecutionEngine.new(mod) + + from llvm.workaround.avx_support import detect_avx_support + if not detect_avx_support(): + ee = le.EngineBuilder.new(mod).mattrs("-avx").create() + else: + ee = le.EngineBuilder.new(mod).create() + arg = le.GenericValue.real(Type.float(), 1.234) retval = ee.run_function(mysin, [arg]) From 9df508f7c0e3bba40e64431ff030df64a8e6f107 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 18:43:57 -0600 Subject: [PATCH 140/338] Fix test with unicode problem in py3k --- llvm/test_llvmpy.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 04170b4..02bb386 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -10,6 +10,7 @@ import subprocess import tempfile import contextlib +is_py3k = sys.version_info[0] >= 3 BITS = tuple.__itemsize__ * 8 try: @@ -711,7 +712,10 @@ class TestNative(TestCase): src = os.path.join(self.tmpdir, 'llvmasm.s') with open(src, 'wb') as fout: - fout.write(output) + if is_py3k: + fout.write(output.encode('utf-8')) + else: + fout.write(output) self._compile(src) @@ -725,7 +729,11 @@ class TestNative(TestCase): src = os.path.join(self.tmpdir, 'llvmobj.o') with open(src, 'wb') as fout: - fout.write(output) + if is_py3k: + fout.write(output.encode('utf-8')) + else: + fout.write(output) + self._compile(src) @@ -965,7 +973,7 @@ class TestCPUSupport(TestCase): features = [] from llvm.workaround.avx_support import detect_avx_support if not detect_avx_support(): - print 'Skipping: no AVX' + print('Skipping: no AVX') else: mattrs = ','.join(map(lambda s: '-%s' % s, features)) print('disable mattrs', mattrs) From 0cccb3dec9e1a70107a09a43398caea87a2f01de Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 19:03:44 -0600 Subject: [PATCH 141/338] Attempt to fix object code printing problem due to unicode --- llvm/ee.py | 8 +++++++- llvm/test_llvmpy.py | 6 +----- llvmpy/include/llvm_binding/conversion.h | 6 ++++++ llvmpy/src/Support/raw_ostream.py | 2 ++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/llvm/ee.py b/llvm/ee.py index 672a0b6..18cef78 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -291,7 +291,13 @@ class TargetMachine(llvm.Wrapper): pm.add(api.llvm.DataLayout.new(str(self.target_data))) failed = self._ptr.addPassesToEmitFile(pm, os, cgft) pm.run(module) - return os.str() + + + CGFT = api.llvm.TargetMachine.CodeGenFileType + if cgft == CGFT.CGFT_ObjectFile: + return os.bytes() + else: + return os.str() def emit_assembly(self, module): '''returns byte string of the module as assembly code of the target machine diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 02bb386..c96f471 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -729,11 +729,7 @@ class TestNative(TestCase): src = os.path.join(self.tmpdir, 'llvmobj.o') with open(src, 'wb') as fout: - if is_py3k: - fout.write(output.encode('utf-8')) - else: - fout.write(output) - + fout.write(output) self._compile(src) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 5395a3f..cdc0350 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -209,6 +209,12 @@ static PyObject* py_str_from(const std::string &str){ return PyString_FromStringAndSize(str.c_str(), str.size()); } + + +static +PyObject* py_bytes_from(const std::string &str){ + return PyBytes_FromStringAndSize(str.c_str(), str.size()); +} // //static //PyObject* py_str_from(const llvm::StringRef *str){ diff --git a/llvmpy/src/Support/raw_ostream.py b/llvmpy/src/Support/raw_ostream.py index dcce73f..02765aa 100644 --- a/llvmpy/src/Support/raw_ostream.py +++ b/llvmpy/src/Support/raw_ostream.py @@ -15,4 +15,6 @@ class raw_svector_ostream: _base_ = raw_ostream str = Method(cast(str, StringRef)) + bytes = Method(cast(bytes, StringRef)) + bytes.realname = 'str' From 268dc2466a9f34c55c19fca7e95bef5a08a81700 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 19:12:23 -0600 Subject: [PATCH 142/338] Fix build on win32 due to missing environ variable --- llvmpy/gen/binding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index ab8e7aa..1b9c799 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -841,7 +841,7 @@ class Attr(object): # # Pick-up environ var # -PTX_SUPPORT = os.environ['LLVMPY_PTX_SUPPORT'] +PTX_SUPPORT = os.environ.get('LLVMPY_PTX_SUPPORT', '') def _parse_llvm_version(ver): import re From 4bf0fa65ef3099b8bac9286873019606a837da04 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 19:22:32 -0600 Subject: [PATCH 143/338] Attempt to fix build on 32-bit linux --- llvmpy/include/llvm_binding/conversion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index cdc0350..8c9e3fc 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -135,10 +135,10 @@ int py_int_to(PyObject *intobj, unsigned long long & val){ } static -int py_int_to(PyObject *intobj, size_t & val){ +int py_int_to(PyObject *intobj, unsigned long & val){ unsigned long long ull; if (py_int_to(intobj, ull)) { - val = (size_t)ull; + val = (unsigned long)ull; return 1; } else { return 0; From 1a34e412a5c706cf097c783e3150f079b5397fed Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 19:27:34 -0600 Subject: [PATCH 144/338] Fix: "not" is not available on some compiler. --- llvmpy/include/capsulethunk.h | 2 +- llvmpy/include/llvm_binding/extra.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/llvmpy/include/capsulethunk.h b/llvmpy/include/capsulethunk.h index 9061782..6b1aba7 100644 --- a/llvmpy/include/capsulethunk.h +++ b/llvmpy/include/capsulethunk.h @@ -12,7 +12,7 @@ static void do_assert(int cond, const char * msg, const char *file, unsigned line){ - if (not cond) { + if (!cond) { fprintf(stderr, "Assertion failed %s:%d\n%s\n", file, line, msg); exit(1); } diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index b33a8a0..5838ae1 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -586,7 +586,7 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker, { std::string errmsg; bool failed = Linker->LinkInModule(Mod, &errmsg); - if (not failed) { + if (! failed) { Py_RETURN_FALSE; } else { if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { @@ -604,7 +604,7 @@ PyObject* Linker_LinkModules(llvm::Module* Dest, { std::string errmsg; bool failed = llvm::Linker::LinkModules(Dest, Src, Mode, &errmsg); - if (not failed) { + if (! failed) { Py_RETURN_FALSE; } else { if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { @@ -686,7 +686,7 @@ PyObject* ConstantArray_get(llvm::ArrayType* Ty, PyObject* Consts) std::vector vec_consts; bool ok = extract::from_py_sequence(vec_consts, Consts, "llvm::Value"); - if (not ok) return NULL; + if (! ok) return NULL; Constant* ary = ConstantArray::get(Ty, vec_consts); return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); } @@ -699,7 +699,7 @@ PyObject* ConstantStruct_get(llvm::StructType* Ty, PyObject* Elems) std::vector vec_consts; bool ok = extract::from_py_sequence(vec_consts, Elems, "llvm::Value"); - if (not ok) return NULL; + if (! ok) return NULL; Constant* ary = ConstantStruct::get(Ty, vec_consts); return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); } @@ -713,7 +713,7 @@ PyObject* ConstantStruct_getAnon(PyObject* Elems, std::vector vec_consts; bool ok = extract::from_py_sequence(vec_consts, Elems, "llvm::Value"); - if (not ok) return NULL; + if (! ok) return NULL; Constant* ary = ConstantStruct::getAnon(vec_consts, isPacked); return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); } @@ -726,7 +726,7 @@ PyObject* ConstantVector_get(PyObject* Elems) std::vector vec_consts; bool ok = extract::from_py_sequence(vec_consts, Elems, "llvm::Value"); - if (not ok) return NULL; + if (! ok) return NULL; Constant* ary = ConstantVector::get(vec_consts); return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); } @@ -756,7 +756,7 @@ PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) bool accept_null = true; bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value", accept_null); - if (not ok) return NULL; + if (! ok) return NULL; llvm::MDNode* md = llvm::MDNode::get(Cxt, vals); return pycapsule_new(md, "llvm::Value", "llvm::MDNode"); } @@ -778,7 +778,7 @@ PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, using namespace llvm; std::vector vec_values; bool ok = extract::from_py_sequence(vec_values, Vals, "llvm::Value"); - if (not ok) return NULL; + if (! ok) return NULL; Value** ptr_values = &vec_values[0]; ReturnInst* inst = builder->CreateAggregateRet(ptr_values, N); return pycapsule_new(inst, "llvm::Value", "llvm::ReturnInst"); From d9c2ec696dde230a2a6fd562c048f9f63cf1122c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 19:31:26 -0600 Subject: [PATCH 145/338] Fix: "and" is not available in all compilers. --- llvmpy/include/llvm_binding/conversion.h | 8 ++++---- llvmpy/include/llvm_binding/extra.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 8c9e3fc..0d65fa9 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -90,7 +90,7 @@ int py_str_to(PyObject *strobj, const char* &strref){ static int py_int_to(PyObject *intobj, int64_t & val){ - if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { + if (!PyInt_Check(intobj) && !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -111,7 +111,7 @@ int py_int_to(PyObject *intobj, int64_t & val){ static int py_int_to(PyObject *intobj, unsigned & val){ - if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { + if (!PyInt_Check(intobj) && !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -123,7 +123,7 @@ int py_int_to(PyObject *intobj, unsigned & val){ static int py_int_to(PyObject *intobj, unsigned long long & val){ - if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { + if (!PyInt_Check(intobj) && !PyLong_Check(intobj)) { // raise TypeError; PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -148,7 +148,7 @@ int py_int_to(PyObject *intobj, unsigned long & val){ static int py_int_to(PyObject *intobj, void* & val){ - if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { + if (!PyInt_Check(intobj) && !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 5838ae1..0e2d0a0 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -201,7 +201,7 @@ struct extract { if (!item) { return false; } - if (accept_null and Py_None == *item) { + if (accept_null && Py_None == *item) { vec.push_back(NULL); } else { auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); From 61d8105e2cffbdd415ff485d3e029a2f8abfcd9d Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Wed, 27 Feb 2013 19:26:25 -0600 Subject: [PATCH 146/338] add missing static library (Windows) --- llvm-config-win32.py | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 915871e..05fc94f 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -68,6 +68,7 @@ LLVMX86AsmParser LLVMX86AsmPrinter LLVMX86CodeGen LLVMX86Desc +LLVMX86Disassembler LLVMX86Info LLVMX86Utils Advapi32 From 75b7d11fb1aad8506418468e1906e2867b250d79 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 20:00:40 -0600 Subject: [PATCH 147/338] Add prints to help debug. --- llvmpy/include/llvm_binding/conversion.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 0d65fa9..da90de6 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -207,6 +207,7 @@ int py_bool_to(PyObject *boolobj, bool & val){ static PyObject* py_str_from(const std::string &str){ + puts(str.c_str()); return PyString_FromStringAndSize(str.c_str(), str.size()); } From 91d2740fbf29163bdcf27f6c8fea96cce2be1c93 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Wed, 27 Feb 2013 20:00:42 -0600 Subject: [PATCH 148/338] disable lib2to3 conversion --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index ea7edb6..4ed5c56 100644 --- a/setup.py +++ b/setup.py @@ -174,9 +174,9 @@ kwds = dict( ) -if sys.version_info[0] == 3: - from distutils.command.build_py import build_py_2to3 - kwds["cmdclass"]['build_py'] = build_py_2to3 +#if sys.version_info[0] == 3: +# from distutils.command.build_py import build_py_2to3 +# kwds["cmdclass"]['build_py'] = build_py_2to3 kwds['long_description'] = open('README.rst').read() From f172e82f1032f365a80ac8ccb4d7673702945c63 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 20:28:30 -0600 Subject: [PATCH 149/338] Use .data() instead of .c_str() --- llvmpy/include/llvm_binding/conversion.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index da90de6..a9f073c 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -207,14 +207,13 @@ int py_bool_to(PyObject *boolobj, bool & val){ static PyObject* py_str_from(const std::string &str){ - puts(str.c_str()); - return PyString_FromStringAndSize(str.c_str(), str.size()); + return PyString_FromStringAndSize(str.data(), str.size()); } static PyObject* py_bytes_from(const std::string &str){ - return PyBytes_FromStringAndSize(str.c_str(), str.size()); + return PyBytes_FromStringAndSize(str.data(), str.size()); } // //static From e89c19ee60fed56ed43d243a69e540e3b9ff7f79 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 28 Feb 2013 00:00:25 -0600 Subject: [PATCH 150/338] Ensure order of imported modules --- llvmpy/src/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/src/__init__.py b/llvmpy/src/__init__.py index 36bc12f..69b6609 100644 --- a/llvmpy/src/__init__.py +++ b/llvmpy/src/__init__.py @@ -2,7 +2,7 @@ import os.path def _init(root=__name__, file=__file__): base = os.path.dirname(file) - for fname in os.listdir(base): + for fname in sorted(os.listdir(base)): is_python_script = fname.endswith('.py') or fname.endswith('.pyc') is_init_script = fname.startswith('__init__') is_directory = os.path.isdir(os.path.join(base, fname)) From 51ff879a070553b3628b49099f12995ec1c35263 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 28 Feb 2013 00:01:03 -0600 Subject: [PATCH 151/338] Fix incorrect use of StringRef in return value --- llvmpy/src/DataLayout.py | 2 +- llvmpy/src/Pass.py | 2 +- llvmpy/src/Support/TargetRegistry.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index 7085f52..812a83d 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -30,7 +30,7 @@ class DataLayout: isLittleEndian = Method(cast(Bool, bool)) isBigEndian = Method(cast(Bool, bool)) - getStringRepresentation = Method(cast(StringRef, str)) + getStringRepresentation = Method(cast(StdString, str)) @CustomPythonMethod def __str__(self): diff --git a/llvmpy/src/Pass.py b/llvmpy/src/Pass.py index ad03d9a..52173cd 100644 --- a/llvmpy/src/Pass.py +++ b/llvmpy/src/Pass.py @@ -15,7 +15,7 @@ class Pass: _include_ = 'llvm/Pass.h' delete = Destructor() - getPassName = Method(cast(StringRef, str)) + getPassName = Method(cast(StdString, str)) dump = Method() @ModulePass diff --git a/llvmpy/src/Support/TargetRegistry.py b/llvmpy/src/Support/TargetRegistry.py index 640364b..2a445e7 100644 --- a/llvmpy/src/Support/TargetRegistry.py +++ b/llvmpy/src/Support/TargetRegistry.py @@ -16,8 +16,8 @@ from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt class Target: getNext = Method(const(ptr(Target))) - getName = Method(cast(StringRef, str)) - getShortDescription = Method(cast(StringRef, str)) + getName = Method(cast(StdString, str)) + getShortDescription = Method(cast(StdString, str)) def _has(): return Method(cast(Bool, bool)) From fde153aab6a4f123a759501c91fcbfbaa2e44a52 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 28 Feb 2013 18:05:30 -0600 Subject: [PATCH 152/338] Add relocation model enums and allow TargetMachine to handle these enums --- llvm/ee.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/llvm/ee.py b/llvm/ee.py index 18cef78..36c0bbf 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -52,6 +52,12 @@ CM_KERNEL = api.llvm.CodeModel.Model.Kernel CM_MEDIUM = api.llvm.CodeModel.Model.Medium CM_LARGE = api.llvm.CodeModel.Model.Large +# Reloc +RELOC_DEFAULT = api.llvm.Reloc.Model.Default +RELOC_STATIC = api.llvm.Reloc.Model.Static +RELOC_PIC = api.llvm.Reloc.Model.PIC_ +RELOC_DYNAMIC_NO_PIC = api.llvm.Reloc.Model.DynamicNoPIC + #===----------------------------------------------------------------------=== # Generic value #===----------------------------------------------------------------------=== @@ -236,7 +242,8 @@ def get_default_triple(): class TargetMachine(llvm.Wrapper): @staticmethod - def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT): + def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT, + reloc=RELOC_DEFAULT): if not triple: triple = get_default_triple() if not cpu: @@ -250,14 +257,14 @@ class TargetMachine(llvm.Wrapper): target_options = api.llvm.TargetOptions.new() tm = target.createTargetMachine(triple, cpu, features, target_options, - api.llvm.Reloc.Model.Default, - cm, opt) + reloc, cm, opt) if not tm: raise llvm.LLVMException("Cannot create target machine") return TargetMachine(tm) @staticmethod - def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): + def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT, + reloc=RELOC_DEFAULT): '''create a targetmachine given an architecture name For a list of architectures, @@ -279,8 +286,7 @@ class TargetMachine(llvm.Wrapper): target_options = api.llvm.TargetOptions.new() tm = target.createTargetMachine(str(triple), cpu, features, target_options, - api.llvm.Reloc.Model.Default, - cm, opt) + reloc, cm, opt) if not tm: raise llvm.LLVMException("Cannot create target machine") return TargetMachine(tm) From bb43f4097a30077c6d19b68fb8d9f18b68b0f70d Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Fri, 1 Mar 2013 19:45:13 -0300 Subject: [PATCH 153/338] Implemented Python 3 compatible division in IntegerValue and RealValue --- llvm_cbuilder/builder.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm_cbuilder/builder.py b/llvm_cbuilder/builder.py index 917b37e..9b970f4 100644 --- a/llvm_cbuilder/builder.py +++ b/llvm_cbuilder/builder.py @@ -988,6 +988,9 @@ class IntegerValue(OperatorMixin): else: return self._temp(self.parent.builder.sdiv(self.value, rhs.value)) + __truediv__ = __div__ + __floordiv__ = __div__ + def __mod__(self, rhs): if self.unsigned: return self._temp(self.parent.builder.urem(self.value, rhs.value)) @@ -1082,6 +1085,8 @@ class RealValue(OperatorMixin): def __div__(self, rhs): return self._temp(self.parent.builder.fdiv(self.value, rhs.value)) + __truediv__ = __div__ + def __mod__(self, rhs): return self._temp(self.parent.builder.frem(self.value, rhs.value)) From ba759b59d08418de7373fbbe93294303d309d27f Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 2 Mar 2013 12:53:31 -0600 Subject: [PATCH 154/338] update supported dependencies in readme --- README.rst | 10 +++++----- setup.py | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 973dfdb..b16249a 100644 --- a/README.rst +++ b/README.rst @@ -10,15 +10,15 @@ http://www.llvmpy.org Versions -------- -This package has been tested with LLVM 3.1 and 3.2, Python 2.7 and Python 3.2. -Other Python versions should work. +This package has been tested with LLVM 3.2, Python 2.6, 2.7 and 3.3. +Other Python versions may work. Quickstart ---------- -1. Get 3.1 or 3.2 version of LLVM, build it. Make sure ``--enable-pic`` is - passed to LLVM's ``configure``. - +1. Get 3.2 version of LLVM, build it. Make sure ``--enable-pic`` is + passed to LLVM's ``configure``. + For LLVM 3.2, make sure that environment variable ``REQUIRES_RTTI=1`` is defined when running ``make``. Otherwise, you may see "undefined symbol: _ZTIN4llvm24PassRegistrationListenerE". Please refer to diff --git a/setup.py b/setup.py index 4ed5c56..8202c5f 100644 --- a/setup.py +++ b/setup.py @@ -207,7 +207,6 @@ setup( "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", ], **kwds From f8deae06ddcaa8a2e062194d01c1736bf6809763 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Sat, 2 Mar 2013 12:56:00 -0600 Subject: [PATCH 155/338] remove excess whitespace --- llvm/core.py | 34 +++++++++---------- llvm/ee.py | 4 +-- llvm/passes.py | 4 +-- llvmpy/capsule.py | 2 +- llvmpy/gen/binding.py | 8 ++--- llvmpy/gen/gen.py | 2 +- llvmpy/src/Argument.py | 2 +- llvmpy/src/BasicBlock.py | 2 +- llvmpy/src/Constant.py | 14 ++++---- llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 +- llvmpy/src/GenericValue.py | 2 +- llvmpy/src/GlobalValue.py | 12 +++---- llvmpy/src/GlobalVariable.py | 3 +- llvmpy/src/IRBuilder.py | 2 +- llvmpy/src/Instruction.py | 6 ++-- llvmpy/src/Metadata.py | 2 +- llvmpy/src/PassRegistry.py | 2 +- llvmpy/src/Target/TargetLibraryInfo.py | 22 ++++++------ llvmpy/src/Transforms/PassManagerBuilder.py | 2 +- llvmpy/src/Type.py | 2 +- llvmpy/src/Value.py | 8 ++--- llvmpy/test_binding.py | 2 +- 22 files changed, 69 insertions(+), 70 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index bed5763..bbe5d01 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -388,7 +388,7 @@ class Module(llvm.Wrapper): return str(self) == str(rhs) else: return False - + def __ne__(self, rhs): return not (self == rhs) @@ -429,7 +429,7 @@ class Module(llvm.Wrapper): The `other' module is no longer valid after this method is invoked, all refs to it should be dropped. - + In the future, this API might be replaced with a full-fledged Linker class. """ @@ -560,7 +560,7 @@ class Module(llvm.Wrapper): pm = PassManager.new()._ptr formatted failed = tm.addPassesToEmitFile(pm, fileobj, cgft, False) - + if failed: raise llvm.LLVMException("Failed to write native object file") if ret: @@ -664,7 +664,7 @@ class Type(llvm.Wrapper): context = api.llvm.getGlobalContext() ptr = api.llvm.Type.getFP128Ty(context) return Type(ptr) - + @staticmethod def ppc_fp128(): """Create a 128-bit floating point type (two 64-bits).""" @@ -920,7 +920,7 @@ class PointerType(Type): class VectorType(Type): _type_ = api.llvm.VectorType - + @property def element(self): return Type(self._ptr.getVectorElementType()) @@ -989,7 +989,7 @@ class Value(llvm.Wrapper): @property def use_count(self): return self._ptr.getNumUses() - + @property def uses(self): return list(map(_make_value, self._ptr.list_use())) @@ -1263,7 +1263,7 @@ class GlobalValue(Constant): def _set_linkage(self, value): self._ptr.setLinkage(value) - + linkage = property(_get_linkage, _set_linkage) def _get_section(self): @@ -1287,7 +1287,7 @@ class GlobalValue(Constant): def _set_alignment(self, value): return self._ptr.setAlignment(value) - + alignment = property(_get_alignment, _set_alignment) @property @@ -1490,7 +1490,7 @@ class Function(GlobalValue): @property def basic_blocks(self): return list(map(_make_value, self._ptr.getBasicBlockList())) - + def viewCFG(self): return self._ptr.viewCFG() @@ -1510,7 +1510,7 @@ class Function(GlobalValue): def verify(self): # Although we're just asking LLVM to return the success or # failure, it appears to print result to stderr and abort. - + # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. actions = api.llvm.VerifierFailureAction @@ -1528,7 +1528,7 @@ class Function(GlobalValue): class InlineAsm(Value): _type_ = api.llvm.InlineAsm - + @staticmethod def get(functype, asm, constrains, side_effect=False, align_stack=False, dialect=api.llvm.InlineAsm.AsmDialect.AD_ATT): @@ -1609,7 +1609,7 @@ class NamedMetaData(llvm.Wrapper): def delete(self): _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() - + @property def name(self): return self._ptr.getName() @@ -1639,7 +1639,7 @@ class Instruction(User): @property def is_binary_op(self): return self._ptr.isBinaryOp() - + @property def is_shift(self): return self._ptr.isShift() @@ -1663,7 +1663,7 @@ class Instruction(User): @property def is_commutative(self): return self._ptr.isCommutative() - + @property def is_volatile(self): """True if this is a volatile load or store.""" @@ -1925,7 +1925,7 @@ class Builder(llvm.Wrapper): def ret_void(self): self._guard_terminators() return _make_value(self._ptr.CreateRetVoid()) - + def ret(self, value): self._guard_terminators() return _make_value(self._ptr.CreateRet(value._ptr)) @@ -2039,7 +2039,7 @@ class Builder(llvm.Wrapper): "") inst = self._ptr.Insert(malloc, name) return _make_value(inst) - + def malloc_array(self, ty, size, name=""): context = api.llvm.getGlobalContext() allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) @@ -2242,7 +2242,7 @@ class Builder(llvm.Wrapper): def atomic_umin(self, *args, **kwargs): return self.atomic_rmw('umin', *args, **kwargs) - + def atomic_load(self, ptr, ordering, align=1, crossthread=True, volatile=False, name=""): inst = self.load(ptr, align=align, volatile=volatile, name=name) diff --git a/llvm/ee.py b/llvm/ee.py index 36c0bbf..9531427 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -156,7 +156,7 @@ class EngineBuilder(llvm.Wrapper): def select_target(self, *args): '''get the corresponding target machine - + Accept no arguments or (triple, march, mcpu, mattrs) ''' if args: @@ -338,7 +338,7 @@ class TargetMachine(llvm.Wrapper): @property def cpu(self): return self._ptr.getTargetCPU() - + @property def feature_string(self): return self._ptr.getTargetFeatureString() diff --git a/llvm/passes.py b/llvm/passes.py index 9f706d8..6216724 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -77,7 +77,7 @@ class PassManagerBuilder(llvm.Wrapper): @vectorize.setter def vectorize(self, enable): self._ptr.Vectorize = enable - + @property def loop_vectorize(self): @@ -200,7 +200,7 @@ class Pass(llvm.Wrapper): try: return self.__name except AttributeError: - return + return @property def description(self): diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index ec6fdde..e3b9537 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -33,7 +33,7 @@ class Capsule(object): "Wraps PyCapsule so that we can build weakref of it." from ._capsule import check, getClassName, getName, getPointer - + def __init__(self, capsule): assert Capsule.valid(capsule) self.capsule = capsule diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 1b9c799..eeccab1 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -344,7 +344,7 @@ class Class(SubModule, _Type): class Enum(object): format = 'O' - + def __init__(self, *value_names): self.parent = None if len(value_names) == 1: @@ -507,7 +507,7 @@ class Method(object): def is_return_ownedptr(self): retty = self.signatures[0][0] return isinstance(retty, ownedptr) - + def process_ownedptr_args(self, writer, unwrapped): argtys = self.signatures[0][1:] for i, ty in enumerate(argtys): @@ -525,7 +525,7 @@ class CustomMethod(Method): ret = writer.call(self.methodname, retty.fullname, *args) writer.return_value(retty.wrap(writer, ret)) - + class StaticMethod(Method): def compile_cpp_body(self, writer, retty, argtys): @@ -544,7 +544,7 @@ class StaticMethod(Method): with decl as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) diff --git a/llvmpy/gen/gen.py b/llvmpy/gen/gen.py index 263c289..cd63b68 100644 --- a/llvmpy/gen/gen.py +++ b/llvmpy/gen/gen.py @@ -80,7 +80,7 @@ static } ''' println(fmt % locals()) - + fn.generate_cpp(println) println('static') diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index 4f0b7a4..babbd1c 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -12,4 +12,4 @@ class Argument: addAttr = Method(Void, ref(Attributes)) removeAttr = Method(Void, ref(Attributes)) getParamAlignment = Method(cast(Unsigned, int)) - + diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 77eaf01..868b3c9 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -14,7 +14,7 @@ class BasicBlock: getParent = Method(ptr(Function)) getTerminator = Method(ptr(TerminatorInst)) - + empty = Method(cast(Bool, bool)) dropAllReferences = Method() isLandingPad = Method(cast(Bool, bool)) diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 70dc3bf..8a091b5 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -73,7 +73,7 @@ class UndefValue: @ConstantInt class ConstantInt: _downcast_ = Constant, Value - + get = StaticMethod(ptr(ConstantInt), ptr(IntegerType), cast(int, Uint64), @@ -89,7 +89,7 @@ class ConstantInt: @ConstantFP class ConstantFP: _downcast_ = Constant, Value - + get = StaticMethod(ptr(Constant), ptr(Type), cast(float, Double)) getNegativeZero = StaticMethod(ptr(ConstantFP), ptr(Type)) getInfinity = StaticMethod(ptr(ConstantFP), ptr(Type), cast(bool, Bool)) @@ -103,7 +103,7 @@ class ConstantFP: @ConstantArray class ConstantArray: _downcast_ = Constant, Value - + get = CustomStaticMethod('ConstantArray_get', PyObjectPtr, # ptr(Constant), ptr(ArrayType), @@ -114,7 +114,7 @@ class ConstantArray: @ConstantStruct class ConstantStruct: _downcast_ = Constant, Value - + get = CustomStaticMethod('ConstantStruct_get', PyObjectPtr, # ptr(Constant) ptr(StructType), @@ -130,7 +130,7 @@ class ConstantStruct: @ConstantVector class ConstantVector: _downcast_ = Constant, Value - + get = CustomStaticMethod('ConstantVector_get', PyObjectPtr, # ptr(Constant) PyObjectPtr, # constants @@ -145,7 +145,7 @@ class ConstantDataSequential: @ConstantDataArray class ConstantDataArray: _downcast_ = Constant, Value - + getString = StaticMethod(ptr(Constant), ref(LLVMContext), cast(str, StringRef), @@ -178,7 +178,7 @@ def _factory_const_type(): @ConstantExpr class ConstantExpr: _downcast_ = Constant, Value - + getAlignOf = _factory(ptr(Type)) getSizeOf = _factory(ptr(Type)) getOffsetOf = _factory(ptr(Type), ptr(Constant)) diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 038d344..3208269 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -18,7 +18,7 @@ class ExecutionEngine: 'llvm/ExecutionEngine/JIT.h') # force linking of jit delete = Destructor() - + create = CustomStaticMethod('ExecutionEngine_create', ptr(ExecutionEngine), ownedptr(Module), cast(bool, Bool), diff --git a/llvmpy/src/GenericValue.py b/llvmpy/src/GenericValue.py index e587b5f..4dc50d8 100644 --- a/llvmpy/src/GenericValue.py +++ b/llvmpy/src/GenericValue.py @@ -31,4 +31,4 @@ class GenericValue: toFloat = _accessor('ToFloat', cast(Double, float), ptr(Type)) - toPointer = _accessor('ToPointer', cast(VoidPtr, int)) \ No newline at end of file + toPointer = _accessor('ToPointer', cast(VoidPtr, int)) diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index 2583c6a..ff499f7 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -9,15 +9,15 @@ class GlobalValue: _include_ = 'llvm/GlobalValue.h' LinkageTypes = Enum(''' - ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage, - LinkOnceODRLinkage, LinkOnceODRAutoHideLinkage, WeakAnyLinkage, - WeakODRLinkage, AppendingLinkage, InternalLinkage, PrivateLinkage, - LinkerPrivateLinkage, LinkerPrivateWeakLinkage, DLLImportLinkage, + ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage, + LinkOnceODRLinkage, LinkOnceODRAutoHideLinkage, WeakAnyLinkage, + WeakODRLinkage, AppendingLinkage, InternalLinkage, PrivateLinkage, + LinkerPrivateLinkage, LinkerPrivateWeakLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage, CommonLinkage ''') - VisibilityTypes = Enum('''DefaultVisibility, - HiddenVisibility, + VisibilityTypes = Enum('''DefaultVisibility, + HiddenVisibility, ProtectedVisibility''') setLinkage = Method(Void, LinkageTypes) diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index c38df27..8b196c0 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -11,7 +11,7 @@ from .Value import Constant @GlobalVariable class GlobalVariable: - ThreadLocalMode = Enum('''NotThreadLocal, GeneralDynamicTLSModel, + ThreadLocalMode = Enum('''NotThreadLocal, GeneralDynamicTLSModel, LocalDynamicTLSModel, InitialExecTLSModel, LocalExecTLSModel ''') @@ -46,4 +46,3 @@ class GlobalVariable: # setExternallyinitialized = Method(Void, cast(bool, Bool)) - \ No newline at end of file diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index afd78a0..c0766e9 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -94,7 +94,7 @@ class IRBuilder: cast(bool, Bool)] op = Method(*sig).require_only(2) return op - + CreateUDiv = _binop_is_exact() CreateSDiv = _binop_is_exact() CreateLShr = _binop_is_exact() diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index beb94f1..16f57c2 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -85,7 +85,7 @@ class Instruction: insertBefore = Method(Void, ptr(Instruction)) insertAfter = Method(Void, ptr(Instruction)) moveBefore = Method(Void, ptr(Instruction)) - + isTerminator = Method(cast(Bool, bool)) isBinaryOp = Method(cast(Bool, bool)) isShift = Method(cast(Bool, bool)) @@ -135,7 +135,7 @@ class BinaryOperator: @CallInst class CallInst: _downcast_ = Value, User, Instruction - + getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) @@ -298,7 +298,7 @@ class ReturnInst: @SwitchInst class SwitchInst: _downcast_ = Value, Instruction - + getCondition = Method(ptr(Value)) setCondition = Method(Void, ptr(Value)) getDefaultDest = Method(ptr(BasicBlock)) diff --git a/llvmpy/src/Metadata.py b/llvmpy/src/Metadata.py index cfeb6ce..65aac03 100644 --- a/llvmpy/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -51,4 +51,4 @@ class NamedMDNode: from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) - return os.str() \ No newline at end of file + return os.str() diff --git a/llvmpy/src/PassRegistry.py b/llvmpy/src/PassRegistry.py index ede026c..f48e7f0 100644 --- a/llvmpy/src/PassRegistry.py +++ b/llvmpy/src/PassRegistry.py @@ -18,4 +18,4 @@ class PassRegistry: # This is a custom method that wraps enumerateWith # Returns list of tuples of (pass-arg, pass-name) - enumerate = CustomMethod('PassRegistry_enumerate', PyObjectPtr) \ No newline at end of file + enumerate = CustomMethod('PassRegistry_enumerate', PyObjectPtr) diff --git a/llvmpy/src/Target/TargetLibraryInfo.py b/llvmpy/src/Target/TargetLibraryInfo.py index 9c47814..3562fa7 100644 --- a/llvmpy/src/Target/TargetLibraryInfo.py +++ b/llvmpy/src/Target/TargetLibraryInfo.py @@ -10,7 +10,7 @@ LibFunc.Enum('Func', ''' ZdaPv, ZdlPv, Znaj, ZnajRKSt9nothrow_t, Znam, ZnamRKSt9nothrow_t, Znwj, ZnwjRKSt9nothrow_t, Znwm, ZnwmRKSt9nothrow_t, cxa_atexit, cxa_guard_abort, - cxa_guard_acquire, cxa_guard_release, memcpy_chk, + cxa_guard_acquire, cxa_guard_release, memcpy_chk, acos, acosf, acosh, acoshf, acoshl, acosl, asin, asinf, asinh, asinhf, asinhl, asinl, @@ -38,17 +38,17 @@ LibFunc.Enum('Func', ''' powl, putchar, puts, realloc, reallocf, rint, rintf, rintl, round, roundf, roundl, - sin, sinf, sinh, sinhf, - sinhl, sinl, siprintf, - sqrt, sqrtf, sqrtl, stpcpy, - strcat, strchr, strcmp, strcpy, - strcspn, strdup, strlen, strncat, - strncmp, strncpy, strndup, strnlen, - strpbrk, strrchr, strspn, strstr, - strtod, strtof, strtol, strtold, + sin, sinf, sinh, sinhf, + sinhl, sinl, siprintf, + sqrt, sqrtf, sqrtl, stpcpy, + strcat, strchr, strcmp, strcpy, + strcspn, strdup, strlen, strncat, + strncmp, strncpy, strndup, strnlen, + strpbrk, strrchr, strspn, strstr, + strtod, strtof, strtol, strtold, strtoll, strtoul, strtoull, tan, - tanf, tanh, tanhf, tanhl, - tanl, trunc, truncf, + tanf, tanh, tanhf, tanhl, + tanl, trunc, truncf, truncl, valloc, NumLibFuncs''') # not in llvm-3.2 abs, ffs, ffsl, ffsll, fprintf, isascii, # isdigit, labs, llabs, printf, sprintf, toascii diff --git a/llvmpy/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py index c940062..86be4fb 100644 --- a/llvmpy/src/Transforms/PassManagerBuilder.py +++ b/llvmpy/src/Transforms/PassManagerBuilder.py @@ -10,7 +10,7 @@ from src.Pass import Pass @PassManagerBuilder class PassManagerBuilder: _include_ = 'llvm/Transforms/IPO/PassManagerBuilder.h' - + new = Constructor() delete = Destructor() diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index ea1f0e5..874201e 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -201,7 +201,7 @@ class StructType: ).require_only(1) getNumElements = Method(cast(Unsigned, int)) getElementType = Method(ptr(Type), cast(int, Unsigned)) - + create = StaticMethod(ptr(StructType), ref(LLVMContext), cast(str, StringRef), diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index 669ed80..f9fddae 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -34,10 +34,10 @@ class Value: ValueTy = Enum(''' ArgumentVal, BasicBlockVal, FunctionVal, GlobalAliasVal, GlobalVariableVal, UndefValueVal, BlockAddressVal, ConstantExprVal, - ConstantAggregateZeroVal, ConstantDataArrayVal, ConstantDataVectorVal, - ConstantIntVal, ConstantFPVal, ConstantArrayVal, ConstantStructVal, - ConstantVectorVal, ConstantPointerNullVal, MDNodeVal, MDStringVal, - InlineAsmVal, PseudoSourceValueVal, FixedStackPseudoSourceValueVal, + ConstantAggregateZeroVal, ConstantDataArrayVal, ConstantDataVectorVal, + ConstantIntVal, ConstantFPVal, ConstantArrayVal, ConstantStructVal, + ConstantVectorVal, ConstantPointerNullVal, MDNodeVal, MDStringVal, + InlineAsmVal, PseudoSourceValueVal, FixedStackPseudoSourceValueVal, InstructionVal, ConstantFirstVal, ConstantLastVal ''') diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index aee0167..0e833e3 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -112,7 +112,7 @@ def test_basic_jit_use(): fpm.doInitialization() fpm.run(fn) fpm.doFinalization() - + pm.run(m) print(m) From a5078d6cd71090aa9139aa729e377b9714b7afed Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Sun, 3 Mar 2013 17:27:01 -0300 Subject: [PATCH 156/338] Added testing infrastructure with travis --- .travis.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..95f434a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: python + +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + +branches: + only: + - master + +install: + - wget "http://repo.continuum.io/pkgs/free/linux-64/llvm-3.2-0.tar.bz2" + - tar -xjf llvm-3.2-0.tar.bz2 + - PATH+=":`pwd`/bin" + - export LD_LIBRARY_PATH="`pwd`/lib" + - export LLVM_CONFIG_PATH="`pwd`/bin/llvm-config" + - $LLVM_CONFIG_PATH --cflags # test llvm-config + - export LLVMPY_DYNLINK=1 + - python setup.py install -q + +script: python -c "import llvm; llvm.test()" + From 372d6018759744dee6dac70fc6814c452864b7c0 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Mon, 4 Mar 2013 23:28:10 -0300 Subject: [PATCH 157/338] Changed test command for travis --- .travis.yml | 2 +- llvm/__init__.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 95f434a..f4474f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,5 +20,5 @@ install: - export LLVMPY_DYNLINK=1 - python setup.py install -q -script: python -c "import llvm; llvm.test()" +script: cd ~; python -c "import sys;import llvm;sys.exit(0 if llvm.test() == 0 else 1)" diff --git a/llvm/__init__.py b/llvm/__init__.py index e3e785f..8f71446 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -34,9 +34,11 @@ class LLVMException(Exception): def test(verbosity=1): """test(verbosity=1) -> TextTestResult - Run self-test, and return unittest.runner.TextTestResult object. + Run self-test, and return the number of failures + errors """ from llvm.test_llvmpy import run - return run(verbosity=verbosity) + result = run(verbosity=verbosity) + + return len(result.failures) + len(result.errors) From e4996f02d7573cec9033acb65176196a370710c8 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Mon, 4 Mar 2013 23:47:54 -0300 Subject: [PATCH 158/338] Fix for Python 3.2 --- llvmpy/include/python3adapt.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/llvmpy/include/python3adapt.h b/llvmpy/include/python3adapt.h index 5b19ebe..a60153f 100644 --- a/llvmpy/include/python3adapt.h +++ b/llvmpy/include/python3adapt.h @@ -9,13 +9,10 @@ #define PyBytes_FromStringAndSize PyString_FromStringAndSize #define PyBytes_FromString PyString_FromString -#endif - -#if (PY_VERSION_HEX >= 0x03000000) +#else #define PyString_Check PyUnicode_Check #define PyString_Size PyUnicode_GET_SIZE -#define PyString_AsString PyUnicode_AsUTF8 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize #define PyString_FromString PyUnicode_FromString @@ -27,6 +24,12 @@ #define PyFile_Check(x) (1) +#if (PY_VERSION_HEX < 0x03030000) +#define PyString_AsString(x) PyBytes_AsString(PyUnicode_AsUTF8String(x)) +#else +#define PyString_AsString PyUnicode_AsUTF8 #endif -#endif //PYTHON3ADAPT_H \ No newline at end of file +#endif // (PY_VERSION_HEX < 0x03000000) + +#endif //PYTHON3ADAPT_H From 931352d4bfab72897dc8012c78d9f64739656226 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Tue, 5 Mar 2013 14:31:21 -0300 Subject: [PATCH 159/338] Fix memory leak in Python 3.2 --- llvmpy/include/python3adapt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/include/python3adapt.h b/llvmpy/include/python3adapt.h index a60153f..db7f28d 100644 --- a/llvmpy/include/python3adapt.h +++ b/llvmpy/include/python3adapt.h @@ -25,7 +25,7 @@ #define PyFile_Check(x) (1) #if (PY_VERSION_HEX < 0x03030000) -#define PyString_AsString(x) PyBytes_AsString(PyUnicode_AsUTF8String(x)) +#define PyString_AsString _PyUnicode_AsString #else #define PyString_AsString PyUnicode_AsUTF8 #endif From b8da3c7a7335e5b2f4a9cee14fe4ae5783fa000f Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Tue, 5 Mar 2013 18:01:57 -0300 Subject: [PATCH 160/338] Changed imports in llpython --- llpython/byte_control.py | 8 ++++---- llpython/byte_flow.py | 6 +++--- llpython/byte_translator.py | 14 +++++++------- llpython/bytecode_visitor.py | 4 ++-- llpython/gen_bytecode_visitor.py | 4 ++-- llpython/nobitey.py | 7 +++---- llpython/phi_injector.py | 2 +- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/llpython/byte_control.py b/llpython/byte_control.py index 9df6d5c..acd5a41 100644 --- a/llpython/byte_control.py +++ b/llpython/byte_control.py @@ -1,12 +1,12 @@ #! /usr/bin/env python # ______________________________________________________________________ - +from __future__ import absolute_import import opcode -import opcode_util +from . import opcode_util import pprint -from bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin -from control_flow import ControlFlowGraph +from .bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin +from .control_flow import ControlFlowGraph # ______________________________________________________________________ diff --git a/llpython/byte_flow.py b/llpython/byte_flow.py index 4a878b2..2201791 100644 --- a/llpython/byte_flow.py +++ b/llpython/byte_flow.py @@ -1,11 +1,11 @@ #! /usr/bin/env python # ______________________________________________________________________ - +from __future__ import absolute_import import dis import opcode -from bytecode_visitor import BasicBlockVisitor -import opcode_util +from .bytecode_visitor import BasicBlockVisitor +from . import opcode_util # ______________________________________________________________________ diff --git a/llpython/byte_translator.py b/llpython/byte_translator.py index 3922099..9b6d2de 100644 --- a/llpython/byte_translator.py +++ b/llpython/byte_translator.py @@ -4,19 +4,19 @@ ''' # ______________________________________________________________________ # Module imports - +from __future__ import absolute_import import opcode import types import logging import llvm.core as lc -import opcode_util -import bytetype -from bytecode_visitor import BytecodeFlowVisitor -from byte_flow import BytecodeFlowBuilder -from byte_control import ControlFlowBuilder -from phi_injector import PhiInjector, synthetic_opname +from . import opcode_util +from . import bytetype +from .bytecode_visitor import BytecodeFlowVisitor +from .byte_flow import BytecodeFlowBuilder +from .byte_control import ControlFlowBuilder +from .phi_injector import PhiInjector, synthetic_opname # ______________________________________________________________________ # Module data diff --git a/llpython/bytecode_visitor.py b/llpython/bytecode_visitor.py index dcc3a0c..009d1a0 100644 --- a/llpython/bytecode_visitor.py +++ b/llpython/bytecode_visitor.py @@ -1,10 +1,10 @@ #! /usr/bin/env python # ______________________________________________________________________ - +from __future__ import absolute_import import itertools import opcode -from opcode_util import itercode +from .opcode_util import itercode # ______________________________________________________________________ diff --git a/llpython/gen_bytecode_visitor.py b/llpython/gen_bytecode_visitor.py index 7f922e2..b29bc56 100644 --- a/llpython/gen_bytecode_visitor.py +++ b/llpython/gen_bytecode_visitor.py @@ -1,7 +1,7 @@ #! /usr/bin/env python # ______________________________________________________________________ - -import opcode_util +from __future__ import absolute_import +from . import opcode_util # ______________________________________________________________________ diff --git a/llpython/nobitey.py b/llpython/nobitey.py index 014216b..68bde5f 100644 --- a/llpython/nobitey.py +++ b/llpython/nobitey.py @@ -1,6 +1,6 @@ #! /usr/bin/env python # ______________________________________________________________________ - +from __future__ import absolute_import import sys import os.path import imp @@ -10,9 +10,8 @@ import types import llvm.core as lc import llvm.ee as le -import bytetype -import byte_translator -from pyaddfunc import pyaddfunc +from . import bytetype, byte_translator +from .pyaddfunc import pyaddfunc LLVM_TO_INT_PARSE_STR_MAP = { 8 : 'b', diff --git a/llpython/phi_injector.py b/llpython/phi_injector.py index 6cccb66..ee28ab5 100644 --- a/llpython/phi_injector.py +++ b/llpython/phi_injector.py @@ -1,7 +1,7 @@ #! /usr/bin/env python # ______________________________________________________________________ -from bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin +from .bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin # ______________________________________________________________________ From 3c4769c58d9e470ce720211063779086c836752b Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 5 Mar 2013 16:47:31 -0600 Subject: [PATCH 161/338] test bug: only attempt to compile when cc is available --- llvm/test_llvmpy.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index c96f471..8df32b8 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -9,6 +9,7 @@ import unittest import subprocess import tempfile import contextlib +from distutils.spawn import find_executable is_py3k = sys.version_info[0] >= 3 BITS = tuple.__itemsize__ * 8 @@ -31,7 +32,6 @@ import llvmpy tests = [] - # --------------------------------------------------------------------------- if sys.version_info[:2] <= (2, 6): @@ -674,6 +674,7 @@ tests.append(TestTargetMachines) # --------------------------------------------------------------------------- class TestNative(TestCase): + def setUp(self): self.tmpdir = tempfile.mkdtemp() @@ -694,8 +695,12 @@ class TestNative(TestCase): return m def _compile(self, src): + cc = find_executable('cc') + if not cc: + return + dst = os.path.join(self.tmpdir, 'llvmobj.out') - s = subprocess.call(['cc', '-o', dst, src]) + s = subprocess.call([cc, '-o', dst, src]) if s != 0: raise Exception("Cannot compile") From 67f4acf91f09cd12c64d6238e5d17f9ffa1a5979 Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 5 Mar 2013 16:49:40 -0600 Subject: [PATCH 162/338] update changelog --- CHANGELOG | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d2e2263..46b7a92 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,9 @@ -2013-02-XX 0.11.0: +2013-03-05 0.11.1: +-------------------- + * fix test when cc is not available + + +2013-03-01 0.11.0: -------------------- * fix Python 3 support on Windows * New llvm binding From e63bdd6da24b7198311a08433bc38e287e6c3439 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Mar 2013 17:17:21 -0600 Subject: [PATCH 163/338] Update changelog --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 46b7a92..c36288a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ 2013-03-05 0.11.1: -------------------- * fix test when cc is not available - + * fix Python 3 division (Hernan Grecco) (Issue #59) + * add relocation enums and add reloc argument for TargetMachine 2013-03-01 0.11.0: -------------------- From 6f524130d0e43109543182b753701435a7c36c2b Mon Sep 17 00:00:00 2001 From: Ilan Schnell Date: Tue, 5 Mar 2013 17:21:28 -0600 Subject: [PATCH 164/338] formatting --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index c36288a..5af6169 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ * fix Python 3 division (Hernan Grecco) (Issue #59) * add relocation enums and add reloc argument for TargetMachine + 2013-03-01 0.11.0: -------------------- * fix Python 3 support on Windows From bd129baa0a4413f5872baf8981a92c78ecd27a01 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Mon, 11 Mar 2013 15:51:03 -0300 Subject: [PATCH 165/338] Reimplemented FunctionAlreadyExists and usage (Exceptions are not iterable in Python 3) --- llvm_cbuilder/builder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm_cbuilder/builder.py b/llvm_cbuilder/builder.py index 9b970f4..648f384 100644 --- a/llvm_cbuilder/builder.py +++ b/llvm_cbuilder/builder.py @@ -14,7 +14,9 @@ from . import shortnames as types ### class FunctionAlreadyExists(NameError): - pass + + def __init__(self, func): + self.func = func def _is_int(ty): return isinstance(ty, lc.IntegerType) @@ -830,7 +832,7 @@ class CDefinition(object): try: func = self.define(module) except FunctionAlreadyExists as e: - (func,) = e + func = e.func return func def __getattr__(self, attr): From ec0dda4621855e845b276b3b48f743a1eb377ad7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 12 Mar 2013 21:35:51 -0500 Subject: [PATCH 166/338] Fix ownership bug --- llvm/passes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/passes.py b/llvm/passes.py index 6216724..068a7a3 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -336,7 +336,7 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False, pmb.populate(pm) if fpm: - fpm.add(tm.target_data) + fpm.add(tm.target_data.clone()) fpm.add(TargetLibraryInfo.new(tm.triple)) if llvm.version >= (3, 2): fpm.add(TargetTransformInfo.new(tm)) From b913b2840e9ec758b0b387f7afef0ff36af33b03 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Thu, 14 Mar 2013 15:21:14 +0000 Subject: [PATCH 167/338] Support non-inplace versions of bitwise left and right shift, and, or and xor --- llvm_cbuilder/builder.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm_cbuilder/builder.py b/llvm_cbuilder/builder.py index 648f384..eaabd67 100644 --- a/llvm_cbuilder/builder.py +++ b/llvm_cbuilder/builder.py @@ -999,22 +999,22 @@ class IntegerValue(OperatorMixin): else: return self._temp(self.parent.builder.srem(self.value, rhs.value)) - def __ilshift__(self, rhs): + def __lshift__(self, rhs): return self._temp(self.parent.builder.shl(self.value, rhs.value)) - def __irshift__(self, rhs): + def __rshift__(self, rhs): if self.unsigned: return self._temp(self.self.parent.builder.lshr(self.value, rhs.value)) else: return self._temp(self.parent.builder.ashr(self.value, rhs.value)) - def __iand__(self, rhs): + def __and__(self, rhs): return self._temp(self.parent.builder.and_(self.value, rhs.value)) - def __ior__(self, rhs): + def __or__(self, rhs): return self._temp(self.parent.builder.or_(self.value, rhs.value)) - def __ixor__(self, rhs): + def __xor__(self, rhs): return self._temp(self.parent.builder.xor(self.value, rhs.value)) def __lt__(self, rhs): From d06a5f3eb401768e89b06d856ff918ceda668af8 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Mar 2013 14:56:26 -0500 Subject: [PATCH 168/338] Fix setOptLevel in EngineBuilder --- llvm/ee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/ee.py b/llvm/ee.py index 9531427..1ef16ae 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -132,7 +132,7 @@ class EngineBuilder(llvm.Wrapper): level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] ''' assert 0 <= level <= 3 - self._ptr.setOptLevel = level + self._ptr.setOptLevel(level) return self def mattrs(self, string): From a8c78a6e2efa707d823769c6c62740afb47b1576 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Mar 2013 14:57:04 -0500 Subject: [PATCH 169/338] Temporily remove setErrorStr. Current implementation does not work. --- llvmpy/include/llvm_binding/extra.h | 32 +++++++++++++---------------- llvmpy/src/EngineBuilder.py | 6 +++--- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 0e2d0a0..6626ede 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -401,24 +401,20 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, return pycapsule_new(new GenericValue(ret), GVN); } -static -PyObject* EngineBuilder_setErrorStr(llvm::EngineBuilder* eb, PyObject* fileobj) -{ - - if (!PyFile_Check(fileobj)) { - PyErr_SetString(PyExc_TypeError, "Expecting a file object."); - return NULL; - } - - std::string buffer; - eb->setErrorStr(&buffer); - - if (-1 == PyFile_WriteString(buffer.c_str(), fileobj)) { - return NULL; - } - - return pycapsule_new(eb, "llvm::EngineBuilder"); -} +// FIXME +//static +//PyObject* EngineBuilder_setErrorStr(llvm::EngineBuilder* eb, PyObject* fileobj) +//{ +// +// std::string buffer; +// eb->setErrorStr(&buffer); +// +// if (-1 == PyFile_WriteString(buffer.c_str(), fileobj)) { +// return NULL; +// } +// +// return pycapsule_new(eb, "llvm::EngineBuilder"); +//} static PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, diff --git a/llvmpy/src/EngineBuilder.py b/llvmpy/src/EngineBuilder.py index 4e8ed12..ef3277f 100644 --- a/llvmpy/src/EngineBuilder.py +++ b/llvmpy/src/EngineBuilder.py @@ -23,9 +23,9 @@ class EngineBuilder: setEngineKind = _setter(Kind) setJITMemoryManager = _setter(ptr(JITMemoryManager)) - - setErrorStr = CustomMethod('EngineBuilder_setErrorStr', - PyObjectPtr, PyObjectPtr) +# FIXME +# setErrorStr = CustomMethod('EngineBuilder_setErrorStr', +# PyObjectPtr, PyObjectPtr) setOptLevel = _setter(CodeGenOpt.Level) #setTargetOptions = From 1b2a9dec9a999076ec2637bf64444c4ab991599b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Mar 2013 14:57:23 -0500 Subject: [PATCH 170/338] Add splitBasicBlock --- llvmpy/src/BasicBlock.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 868b3c9..6efe704 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -24,3 +24,7 @@ class BasicBlock: getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) eraseFromParent = Method() + + splitBasicBlock = Method(ptr(BasicBlock), ptr(Instruction), + cast(str, StringRef)).require_only(1) + From 8800ebac6660e5536355bc05546db7867072f1f7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Mar 2013 14:57:36 -0500 Subject: [PATCH 171/338] Add downcast mapping --- llvmpy/src/Constant.py | 20 ++++---- llvmpy/src/GlobalVariable.py | 3 +- llvmpy/src/Instruction.py | 92 ++++++++++++++++++++---------------- 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 8a091b5..77bd835 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -1,6 +1,6 @@ from binding import * from .namespace import llvm -from .Value import Value +from .Value import Value, User from .Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray from .Value import ConstantStruct, ConstantVector, ConstantVector from .Value import ConstantDataSequential, ConstantDataArray, ConstantExpr @@ -12,7 +12,7 @@ from .Instruction import CmpInst @Constant class Constant: - _downcast_ = Value + _downcast_ = Value, User isNullValue = Method(cast(bool, Bool)) isAllOnesValue = Method(cast(bool, Bool)) @@ -72,7 +72,7 @@ class UndefValue: @ConstantInt class ConstantInt: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value get = StaticMethod(ptr(ConstantInt), ptr(IntegerType), @@ -88,7 +88,7 @@ class ConstantInt: @ConstantFP class ConstantFP: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value get = StaticMethod(ptr(Constant), ptr(Type), cast(float, Double)) getNegativeZero = StaticMethod(ptr(ConstantFP), ptr(Type)) @@ -102,7 +102,7 @@ class ConstantFP: @ConstantArray class ConstantArray: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value get = CustomStaticMethod('ConstantArray_get', PyObjectPtr, # ptr(Constant), @@ -113,7 +113,7 @@ class ConstantArray: @ConstantStruct class ConstantStruct: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value get = CustomStaticMethod('ConstantStruct_get', PyObjectPtr, # ptr(Constant) @@ -129,7 +129,7 @@ class ConstantStruct: @ConstantVector class ConstantVector: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value get = CustomStaticMethod('ConstantVector_get', PyObjectPtr, # ptr(Constant) @@ -139,12 +139,12 @@ class ConstantVector: @ConstantDataSequential class ConstantDataSequential: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value @ConstantDataArray class ConstantDataArray: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value getString = StaticMethod(ptr(Constant), ref(LLVMContext), @@ -177,7 +177,7 @@ def _factory_const_type(): @ConstantExpr class ConstantExpr: - _downcast_ = Constant, Value + _downcast_ = Constant, User, Value getAlignOf = _factory(ptr(Type)) getSizeOf = _factory(ptr(Type)) diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index 8b196c0..e319e52 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -7,10 +7,11 @@ GlobalVariable = llvm.Class(GlobalValue) from .Module import Module from .Type import Type from .ADT.StringRef import StringRef -from .Value import Constant +from .Value import Value, User, Constant @GlobalVariable class GlobalVariable: + _downcast_ = Value, User ThreadLocalMode = Enum('''NotThreadLocal, GeneralDynamicTLSModel, LocalDynamicTLSModel, InitialExecTLSModel, LocalExecTLSModel diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 16f57c2..edde8bc 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -110,6 +110,9 @@ class Instruction: clone = Method(ptr(Instruction)) + getNextNode = Method(ptr(Instruction)) + getPrevNode = Method(ptr(Instruction)) + # LLVM 3.3 # hasUnsafeAlgebra = Method(cast(Bool, bool)) # hasNoNans = Method(cast(Bool, bool)) @@ -120,17 +123,17 @@ class Instruction: @AtomicCmpXchgInst class AtomicCmpXchgInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @AtomicRMWInst class AtomicRMWInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min', 'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP') @BinaryOperator class BinaryOperator: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @CallInst class CallInst: @@ -160,7 +163,7 @@ class CallInst: @CmpInst class CmpInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', 'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO', 'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE', @@ -177,31 +180,31 @@ class CmpInst: @ExtractElementInst class ExtractElementInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @FenceInst class FenceInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @GetElementPtrInst class GetElementPtrInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @InsertElementInst class InsertElementInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @InsertValueInst class InsertValueInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @LandingPadInst class LandingPadInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @PHINode class PHINode: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getNumIncomingValues = Method(cast(Unsigned, int)) getIncomingValue = Method(ptr(Value), cast(int, Unsigned)) setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value)) @@ -213,15 +216,15 @@ class PHINode: @SelectInst class SelectInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @ShuffleVectorInst class ShuffleVectorInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @StoreInst class StoreInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction isVolatile = Method(cast(Bool, bool)) isSimple = Method(cast(Bool, bool)) isUnordered = Method(cast(Bool, bool)) @@ -240,40 +243,40 @@ class StoreInst: @TerminatorInst class TerminatorInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getNumSuccessors = Method(cast(Unsigned, int)) getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned)) setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) @UnaryInstruction class UnaryInstruction: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction #call @IntrinsicInst class IntrinsicInst: _include_ = 'llvm/IntrinsicInst.h' - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction #compare @FCmpInst class FCmpInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @ICmpInst class ICmpInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction # terminator @BranchInst class BranchInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @IndirectBrInst class IndirectBrInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @InvokeInst class InvokeInst: @@ -289,15 +292,17 @@ class InvokeInst: @ResumeInst class ResumeInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @ReturnInst class ReturnInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction, TerminatorInst + getReturnValue = Method(ptr(Value)) + getNumSuccessors = Method(cast(Unsigned, int)) @SwitchInst class SwitchInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getCondition = Method(ptr(Value)) setCondition = Method(Void, ptr(Value)) @@ -309,24 +314,29 @@ class SwitchInst: @UnreachableInst class UnreachableInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction # unary @AllocaInst class AllocaInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction + isArrayAllocation = Method(cast(Bool, bool)) + isStaticAlloca = Method(cast(Bool, bool)) + getArraySize = Method(ptr(Value)) + getAllocatedType = Method(ptr(Type)) + @CastInst class CastInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @ExtractValueInst class ExtractValueInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @LoadInst class LoadInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction isVolatile = Method(cast(Bool, bool)) isSimple = Method(cast(Bool, bool)) isUnordered = Method(cast(Bool, bool)) @@ -341,50 +351,52 @@ class LoadInst: AtomicOrdering, SynchronizationScope).require_only(1) + getPointerOperand = Method(ptr(Value)) + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @VAArgInst class VAArgInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction # intrinsic @DbgInfoIntrinsic class DbgInfoIntrinsic: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @MemIntrinsic class MemIntrinsic: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @VACopyInst class VACopyInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @VAEndInst class VAEndInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @VAStartInst class VAStartInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @BitCastInst class BitCastInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @FPExtInst class FPExtInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @FPToSIInst class FPToSIInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @FPToUIInst class FPToUIInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction @FPTruncInst class FPTruncInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction From b6c1e7a961ca32178023593ad03bd1ab735553b2 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Mar 2013 14:57:58 -0500 Subject: [PATCH 172/338] Add some utils in BasicBlockUtils.h --- llvmpy/src/Transforms/Utils/BasicBlockUtils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 llvmpy/src/Transforms/Utils/BasicBlockUtils.py diff --git a/llvmpy/src/Transforms/Utils/BasicBlockUtils.py b/llvmpy/src/Transforms/Utils/BasicBlockUtils.py new file mode 100644 index 0000000..8a571c2 --- /dev/null +++ b/llvmpy/src/Transforms/Utils/BasicBlockUtils.py @@ -0,0 +1,16 @@ +from binding import * +from src.namespace import llvm +from src.Value import MDNode +from src.Instruction import Instruction, TerminatorInst +llvm.includes.add('llvm/Transforms/Utils/BasicBlockUtils.h') + +SplitBlockAndInsertIfThen = llvm.Function('SplitBlockAndInsertIfThen', + ptr(TerminatorInst), + ptr(Instruction), # cmp + cast(bool, Bool), # unreachable + ptr(MDNode)) # branchweights + +ReplaceInstWithInst = llvm.Function('ReplaceInstWithInst', + Void, + ptr(Instruction), # from + ptr(Instruction)) # to \ No newline at end of file From 6c2ed9a3ed6fa204dba3290fc0a1f992437eafa3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 25 Mar 2013 11:23:16 -0500 Subject: [PATCH 173/338] Add some more to CallInst and StoreInst --- llvmpy/src/Instruction.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index edde8bc..e17e8a1 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -161,6 +161,10 @@ class CallInst: CreateFree = StaticMethod(ptr(Instruction), ptr(Value), ptr(BasicBlock)) + getNumArgOperands = Method(cast(Unsigned, int)) + getArgOperand = Method(ptr(Value), cast(int, Unsigned)) + setArgOperand = Method(Void, cast(int, Unsigned), ptr(Value)) + @CmpInst class CmpInst: _downcast_ = Value, User, Instruction @@ -239,6 +243,10 @@ class StoreInst: AtomicOrdering, SynchronizationScope).require_only(1) + getValueOperand = Method(ptr(Value)) + getPointerOperand = Method(ptr(Value)) + getPointerAddressSpace = Method(cast(Unsigned, int)) + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @TerminatorInst From b14161c1847569c5667a54a9dd3260b06cf1d817 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 25 Mar 2013 17:23:41 -0500 Subject: [PATCH 174/338] Add Constant to GlobalVariable cast --- llvmpy/src/GlobalVariable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index e319e52..bffa9ee 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -11,7 +11,7 @@ from .Value import Value, User, Constant @GlobalVariable class GlobalVariable: - _downcast_ = Value, User + _downcast_ = Value, User, Constant ThreadLocalMode = Enum('''NotThreadLocal, GeneralDynamicTLSModel, LocalDynamicTLSModel, InitialExecTLSModel, LocalExecTLSModel From b13aee066849f21e0d0acd3106283ce1d4014fdd Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 28 Mar 2013 22:05:12 -0500 Subject: [PATCH 175/338] Two llvm wrapped instances are the same if they point to the same thing --- llvmpy/capsule.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index e3b9537..9c1e86a 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -76,7 +76,7 @@ class Capsule(object): return False def __hash__(self): - return super(Capsule, self).__hash__() + return hash((self.pointer, self.name)) def __ne__(self, other): return not (self == other) @@ -174,13 +174,13 @@ class Wrapper(object): return self._capsule.capsule def __hash__(self): - return super(Wrapper, self).__hash__() + return hash(self._capsule) def __eq__(self, other): return self._capsule == other._capsule def __ne__(self, other): - return self._capsule != other._capsule + return not(self == other) def _downcast(self, newcls): return downcast(self, newcls) From 22b5d4695cbec0382831b2091666580cc372765c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 1 Apr 2013 11:24:09 -0500 Subject: [PATCH 176/338] Add mutateType --- llvmpy/src/Value.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index f9fddae..fb9c3cc 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -71,3 +71,5 @@ class Value: return os.str() getValueID = Method(cast(Unsigned, int)) + + mutateType = Method(Void, ptr(Type)) From 0b1abe7b26d35f11e826111c9fa026d087dd49d5 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 1 Apr 2013 11:24:19 -0500 Subject: [PATCH 177/338] Add isLayoutIdentical --- llvm/core.py | 4 ++++ llvm/test_llvmpy.py | 12 ++++++++++++ llvmpy/src/Type.py | 2 ++ 3 files changed, 18 insertions(+) diff --git a/llvm/core.py b/llvm/core.py index bbe5d01..719c8a4 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -895,6 +895,10 @@ class StructType(Type): def is_opaque(self): return self._ptr.isOpaque() + 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 8df32b8..945ac41 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -1245,6 +1245,18 @@ class TestNamedMetaData(TestCase): tests.append(TestNamedMetaData) + +# --------------------------------------------------------------------------- + +class TestStruct(TestCase): + def test_struct_identical(self): + m = Module.new('test_struct_identical') + ta = Type.struct([Type.int(32), Type.float()], name='ta') + tb = Type.struct([Type.int(32), Type.float()]) + self.assertTrue(ta.is_layout_identical(tb)) + +tests.append(TestStruct) + # --------------------------------------------------------------------------- def run(verbosity=1): diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index 874201e..afc148c 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -214,6 +214,8 @@ class StructType: cast(bool, Bool), # is packed ).require_only(2) + isLayoutIdentical = Method(cast(Bool, bool), # identical? + ptr(StructType)) # other isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) From fab52057ba6b44a334e8eb004a1549f2ffe96b6a Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 8 Apr 2013 11:14:11 -0500 Subject: [PATCH 178/338] Improve docs on LLVM build instruction --- README.rst | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index b16249a..a9817ac 100644 --- a/README.rst +++ b/README.rst @@ -16,13 +16,18 @@ Other Python versions may work. Quickstart ---------- -1. Get 3.2 version of LLVM, build it. Make sure ``--enable-pic`` is - passed to LLVM's ``configure``. +1. Get and extract LLVM 3.2 source tarball. - For LLVM 3.2, make sure that environment variable ``REQUIRES_RTTI=1`` is - defined when running ``make``. Otherwise, you may see "undefined symbol: - _ZTIN4llvm24PassRegistrationListenerE". Please refer to - http://llvm.org/docs/Packaging.html#c-features for details. +2. Run ``./configure --enable-optimized`` in the extracted directory. + + **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. + +3. Run ``REQUIRES_RTTI=1 make`` to build. + + **Note**: With LLVM 3.2, the default build configuration has C++ RTTI + disabled. However, llvmpy requires RTTI. 2. Get llvm-py and install it:: @@ -36,6 +41,14 @@ Quickstart 3. See documentation at 'http://www.llvmpy.org' and examples under 'test'. + +Common Build Problems +--------------------- + +1. If llvmpy cannot be imported due to "undefined symbol: + _ZTIN4llvm24PassRegistrationListenerE", it is because RTTI is not enabled + when building LLVM. "_ZTIN4llvm24PassRegistrationListenerE" is the typeinfo + of PassRegistrationListener class. LICENSE ------- From ca8fa2593a651b74327817700193c5a3ad766fac Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 8 Apr 2013 11:17:51 -0500 Subject: [PATCH 179/338] Add LLVM source link --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index a9817ac..aea8f64 100644 --- a/README.rst +++ b/README.rst @@ -16,7 +16,7 @@ Other Python versions may work. Quickstart ---------- -1. Get and extract LLVM 3.2 source tarball. +1. Get and extract LLVM 3.2 source tarball from `llvm.org `_. 2. Run ``./configure --enable-optimized`` in the extracted directory. From 003768cdea0632e0fb64b81fe6aa9b980ae0e94e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 8 Apr 2013 11:20:21 -0500 Subject: [PATCH 180/338] Prettify docs. (Does this trigger a NOTE section?) --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index aea8f64..10f945b 100644 --- a/README.rst +++ b/README.rst @@ -20,9 +20,9 @@ Quickstart 2. Run ``./configure --enable-optimized`` in the extracted directory. - **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**: 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. 3. Run ``REQUIRES_RTTI=1 make`` to build. From 2479c2dc22f1df98fcc45bf4d72368f481e98893 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 8 Apr 2013 11:28:42 -0500 Subject: [PATCH 181/338] More detail --- README.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 10f945b..0fbcd24 100644 --- a/README.rst +++ b/README.rst @@ -16,30 +16,36 @@ Other Python versions may work. Quickstart ---------- -1. Get and extract LLVM 3.2 source tarball from `llvm.org `_. +1. Get and extract LLVM 3.2 source tarball from + `llvm.org `_. Then, ``cd`` into + the extracted directory. -2. Run ``./configure --enable-optimized`` in the extracted directory. +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. 3. Run ``REQUIRES_RTTI=1 make`` to build. **Note**: With LLVM 3.2, the default build configuration has C++ RTTI disabled. However, llvmpy requires RTTI. -2. Get llvm-py and install it:: +4. Get llvm-py and install it:: $ git clone git@github.com:llvmpy/llvmpy.git $ cd llvmpy - $ python setup.py install + $ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install Run the tests:: $ python -c "import llvm; llvm.test()" -3. See documentation at 'http://www.llvmpy.org' and examples +5. See documentation at 'http://www.llvmpy.org' and examples under 'test'. Common Build Problems From 125e65e2613a1bbaf3a319a96d9939c09238be4f Mon Sep 17 00:00:00 2001 From: David H Post Date: Wed, 10 Apr 2013 15:15:19 -0500 Subject: [PATCH 182/338] Fix corrupted text and example in 7.3 Memory in LLVM --- docs/source/doc/kaleidoscope/PythonLangImpl7.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst index 7e86ee4..dee1c31 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst @@ -121,8 +121,8 @@ to talk about how LLVM represents stack variables. In LLVM, all memory accesses are explicit with load/store instructions, and it is carefully designed not to have (or need) an "address-of" operator. Notice how the type of the @G/@H global variables is actually -"i32\ *" even though the variable is defined as "i32". What this means -is that @G defines* space* for an i32 in the global data area, but its +"i32\*" even though the variable is defined as "i32". What this means +is that @G defines *space* for an i32 in the global data area, but its *name* actually refers to the address for that space. Stack variables work the same way, except that instead of being declared with global variable definitions, they are declared with the `LLVM alloca @@ -133,11 +133,11 @@ instruction `_: define i32 @example() { entry: - %X = alloca i32 ; type of %X is i32 *. + %X = alloca i32 ; type of %X is i32* ... - %tmp = load i32* %X ; load the stack value %X from the stack. - %tmp2 = add i32 %tmp, 1 ; increment it store i32 %tmp2, - i32* %X ; store it back + %tmp = load i32* %X ; load the stack value %X from the stack + %tmp2 = add i32 %tmp, 1 ; increment it + store i32 %tmp2, i32* %X ; store it back ... From 66346ee507d600da121713c039ecbfa501d27b90 Mon Sep 17 00:00:00 2001 From: David H Post Date: Thu, 11 Apr 2013 02:36:00 -0500 Subject: [PATCH 183/338] Corruption fixed in doc/llvm.core.Constant.rst (bottom of page needs work) --- docs/source/doc/llvm.core.Constant.rst | 657 +++++++++++++------------ 1 file changed, 329 insertions(+), 328 deletions(-) diff --git a/docs/source/doc/llvm.core.Constant.rst b/docs/source/doc/llvm.core.Constant.rst index ae67fa4..3822046 100644 --- a/docs/source/doc/llvm.core.Constant.rst +++ b/docs/source/doc/llvm.core.Constant.rst @@ -26,334 +26,335 @@ some examples: tr = Type.float() - r1 = Constant.real(tr, "3.141592") # create from a string r2 = - Constant.real(tr, 1.61803399) # create from a Python float {% - endhighlight %} - - # llvm.core.Constant - - This will become a table of contents (this text will be scraped). - {:toc} - - Static factory methods - ---------------------- - - ``null(ty)`` - ~~~~~~~~~~~~ - - A null value (all zeros) of type ``ty`` - - ``all_ones(ty)`` - ~~~~~~~~~~~~~~~~ - - All 1's value of type ``ty`` - - ``undef(ty)`` - ~~~~~~~~~~~~~ - - An undefined value of type ``ty`` - - ``int(ty, value)`` - ~~~~~~~~~~~~~~~~~~ - - Integer of type ``ty``, with value ``value`` (a Python int or long) - - ``int_signextend(ty, value)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Integer of signed type ``ty`` (use for signed types) - - ``real(ty, value)`` - ~~~~~~~~~~~~~~~~~~~ - - Floating point value of type ``ty``, with value ``value`` (a Python - float) - - ``stringz(value)`` - ~~~~~~~~~~~~~~~~~~ - - A null-terminated string. ``value`` is a Python string - - ``string(value)`` - ~~~~~~~~~~~~~~~~~ - - As ``string(ty)``, but not null terminated - - ``array(ty, consts)`` - ~~~~~~~~~~~~~~~~~~~~~ - - Array of type ``ty``, initialized with ``consts`` (an iterable yielding - ``Constant`` objects of the appropriate type) - - ``struct(ty, consts)`` - ~~~~~~~~~~~~~~~~~~~~~~ - - Struct (unpacked) of type ``ty``, initialized with ``consts`` (an - iterable yielding ``Constant`` objects of the appropriate type) - - ``packed_struct(ty, consts)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - As ``struct(ty, consts)`` but packed - - ``vector(consts)`` - ~~~~~~~~~~~~~~~~~~ - - Vector, initialized with ``consts`` (an iterable yielding ``Constant`` - objects of the appropriate type) - - ``sizeof(ty)`` - ~~~~~~~~~~~~~~ - - Constant value representing the sizeof the type ``ty`` - - Methods - ------- - - The following operations on constants are supported. For more details on - any operation, consult the `Constant - Expressions `_ - section of the LLVM Language Reference. - - ``k.neg()`` - ~~~~~~~~~~~ - - negation, same as ``0 - k`` - - ``k.not_()`` - ~~~~~~~~~~~~ - - 1's complement of ``k``. Note trailing underscore. - - ``k.add(k2)`` - ~~~~~~~~~~~~~ - - ``k + k2``, where ``k`` and ``k2`` are integers. - - ``k.fadd(k2)`` - ~~~~~~~~~~~~~~ - - ``k + k2``, where ``k`` and ``k2`` are floating-point. - - ``k.sub(k2)`` - ~~~~~~~~~~~~~ - - ``k - k2``, where ``k`` and ``k2`` are integers. - - ``k.fsub(k2)`` - ~~~~~~~~~~~~~~ - - ``k - k2``, where ``k`` and ``k2`` are floating-point. - - ``k.mul(k2)`` - ~~~~~~~~~~~~~ - - ``k * k2``, where ``k`` and ``k2`` are integers. - - ``k.fmul(k2)`` - ~~~~~~~~~~~~~~ - - ``k * k2``, where ``k`` and ``k2`` are floating-point. - - ``k.udiv(k2)`` - ~~~~~~~~~~~~~~ - - Quotient of unsigned division of ``k`` with ``k2`` - - ``k.sdiv(k2)`` - ~~~~~~~~~~~~~~ - - Quotient of signed division of ``k`` with ``k2`` - - ``k.fdiv(k2)`` - ~~~~~~~~~~~~~~ - - Quotient of floating point division of ``k`` with ``k2`` - - ``k.urem(k2)`` - ~~~~~~~~~~~~~~ - - Reminder of unsigned division of ``k`` with ``k2`` - - ``k.srem(k2)`` - ~~~~~~~~~~~~~~ - - Reminder of signed division of ``k`` with ``k2`` - - ``k.frem(k2)`` - ~~~~~~~~~~~~~~ - - Reminder of floating point division of ``k`` with ``k2`` - - ``k.and_(k2)`` - ~~~~~~~~~~~~~~ - - Bitwise and of ``k`` and ``k2``. Note trailing underscore. - - ``k.or_(k2)`` - ~~~~~~~~~~~~~ - - Bitwise or of ``k`` and ``k2``. Note trailing underscore. - - ``k.xor(k2)`` - ~~~~~~~~~~~~~ - - Bitwise exclusive-or of ``k`` and ``k2``. - - ``k.icmp(icmp, k2)`` - ~~~~~~~~~~~~~~~~~~~~ - - Compare ``k`` with ``k2`` using the predicate ``icmp``. See - `here `_ for list of predicates for integer - operands. - - ``k.fcmp(fcmp, k2)`` - ~~~~~~~~~~~~~~~~~~~~ - - Compare ``k`` with ``k2`` using the predicate ``fcmp``. See - `here `_ for list of predicates for real - operands. - - ``k.shl(k2)`` - ~~~~~~~~~~~~~ - - Shift ``k`` left by ``k2`` bits. - - ``k.lshr(k2)`` - ~~~~~~~~~~~~~~ - - Shift ``k`` logically right by ``k2`` bits (new bits are 0s). - - ``k.ashr(k2)`` - ~~~~~~~~~~~~~~ - - Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as - previous sign bit). - - ``k.gep(indices)`` - ~~~~~~~~~~~~~~~~~~ - - GEP, see `LLVM docs `_. - - ``k.trunc(ty)`` - ~~~~~~~~~~~~~~~ - - Truncate ``k`` to a type ``ty`` of lower bitwidth. - - ``k.sext(ty)`` - ~~~~~~~~~~~~~~ - - Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending - the sign bit. - - ``k.zext(ty)`` - ~~~~~~~~~~~~~~ - - Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are - 0s. - - ``k.fptrunc(ty)`` - ~~~~~~~~~~~~~~~~~ - - Truncate floating point constant ``k`` to floating point type ``ty`` of - lower size than k's. - - ``k.fpext(ty)`` - ~~~~~~~~~~~~~~~ - - Extend floating point constant ``k`` to floating point type ``ty`` of - higher size than k's. - - ``k.uitofp(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert an unsigned integer constant ``k`` to floating point constant of - type ``ty``. - - ``k.sitofp(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert a signed integer constant ``k`` to floating point constant of - type ``ty``. - - ``k.fptoui(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert a floating point constant ``k`` to an unsigned integer constant - of type ``ty``. - - ``k.fptosi(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert a floating point constant ``k`` to a signed integer constant of - type ``ty``. - - ``k.ptrtoint(ty)`` - ~~~~~~~~~~~~~~~~~~ - - Convert a pointer constant ``k`` to an integer constant of type ``ty``. - - ``k.inttoptr(ty)`` - ~~~~~~~~~~~~~~~~~~ - - Convert an integer constant ``k`` to a pointer constant of type ``ty``. - - ``k.bitcast(ty)`` - ~~~~~~~~~~~~~~~~~ - - Convert ``k`` to a (equal-width) constant of type ``ty``. - - ``k.select(cond,k2,k3)`` - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1, - else with ``k3``. - - ``k.extract_element(idx)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Extract value at ``idx`` (integer constant) from a vector constant - ``k``. - - ``k.insert_element(k2,idx)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Insert value ``k2`` (scalar constant) at index ``idx`` (integer - constant) of vector constant ``k``. - - ``k.shuffle_vector(k2,mask)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Shuffle vector constant ``k`` based on vector constants ``k2`` and - ``mask``. - - -------------- - - # Other Constant Classes - The following subclasses of ``Constant`` do not provide additional - methods, **they serve only to provide richer type information.** - - Subclass \| LLVM C++ Class \| Remarks \| - ---------\|----------------\|---------\| ``ConstantExpr`` \| - ``llvmConstantExpr`` \| A constant expression \| - ``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero - constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer - constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point - constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array - constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A - structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \| - A vector constant \| ``ConstantPointerNull``\ \| - ``llvmConstantPointerNull``\ \| All-zero pointer constant \| - ``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of - LLVM IR \| - - These types are helpful in ``isinstance`` checks, like so: - - {% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) # - int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = { - k1, k1 }; - - assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray) - + r1 = Constant.real(tr, "3.141592") # create from a string + r2 = Constant.real(tr, 1.61803399) # create from a Python float + + +# llvm.core.Constant +- This will become a table of contents (this text will be scraped). +{:toc} + + +Static factory methods +---------------------- + +``null(ty)`` +~~~~~~~~~~~~ + +A null value (all zeros) of type ``ty`` + +``all_ones(ty)`` +~~~~~~~~~~~~~~~~ + +All 1's value of type ``ty`` + +``undef(ty)`` +~~~~~~~~~~~~~ + +An undefined value of type ``ty`` + +``int(ty, value)`` +~~~~~~~~~~~~~~~~~~ + +Integer of type ``ty``, with value ``value`` (a Python int or long) + +``int_signextend(ty, value)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Integer of signed type ``ty`` (use for signed types) + +``real(ty, value)`` +~~~~~~~~~~~~~~~~~~~ + +Floating point value of type ``ty``, with value ``value`` (a Python +float) + +``stringz(value)`` +~~~~~~~~~~~~~~~~~~ + +A null-terminated string. ``value`` is a Python string + +``string(value)`` +~~~~~~~~~~~~~~~~~ + +As ``string(ty)``, but not null terminated + +``array(ty, consts)`` +~~~~~~~~~~~~~~~~~~~~~ + +Array of type ``ty``, initialized with ``consts`` (an iterable yielding +``Constant`` objects of the appropriate type) + +``struct(ty, consts)`` +~~~~~~~~~~~~~~~~~~~~~~ + +Struct (unpacked) of type ``ty``, initialized with ``consts`` (an +iterable yielding ``Constant`` objects of the appropriate type) + +``packed_struct(ty, consts)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As ``struct(ty, consts)`` but packed + +``vector(consts)`` +~~~~~~~~~~~~~~~~~~ + +Vector, initialized with ``consts`` (an iterable yielding ``Constant`` +objects of the appropriate type) + +``sizeof(ty)`` +~~~~~~~~~~~~~~ + +Constant value representing the sizeof the type ``ty`` + +Methods +------- + +The following operations on constants are supported. For more details on +any operation, consult the `Constant +Expressions `_ +section of the LLVM Language Reference. + +``k.neg()`` +~~~~~~~~~~~ + +negation, same as ``0 - k`` + +``k.not_()`` +~~~~~~~~~~~~ + +1's complement of ``k``. Note trailing underscore. + +``k.add(k2)`` +~~~~~~~~~~~~~ + +``k + k2``, where ``k`` and ``k2`` are integers. + +``k.fadd(k2)`` +~~~~~~~~~~~~~~ + +``k + k2``, where ``k`` and ``k2`` are floating-point. + +``k.sub(k2)`` +~~~~~~~~~~~~~ + +``k - k2``, where ``k`` and ``k2`` are integers. + +``k.fsub(k2)`` +~~~~~~~~~~~~~~ + +``k - k2``, where ``k`` and ``k2`` are floating-point. + +``k.mul(k2)`` +~~~~~~~~~~~~~ + +``k * k2``, where ``k`` and ``k2`` are integers. + +``k.fmul(k2)`` +~~~~~~~~~~~~~~ + +``k * k2``, where ``k`` and ``k2`` are floating-point. + +``k.udiv(k2)`` +~~~~~~~~~~~~~~ + +Quotient of unsigned division of ``k`` with ``k2`` + +``k.sdiv(k2)`` +~~~~~~~~~~~~~~ + +Quotient of signed division of ``k`` with ``k2`` + +``k.fdiv(k2)`` +~~~~~~~~~~~~~~ + +Quotient of floating point division of ``k`` with ``k2`` + +``k.urem(k2)`` +~~~~~~~~~~~~~~ + +Reminder of unsigned division of ``k`` with ``k2`` + +``k.srem(k2)`` +~~~~~~~~~~~~~~ + +Reminder of signed division of ``k`` with ``k2`` + +``k.frem(k2)`` +~~~~~~~~~~~~~~ + +Reminder of floating point division of ``k`` with ``k2`` + +``k.and_(k2)`` +~~~~~~~~~~~~~~ + +Bitwise and of ``k`` and ``k2``. Note trailing underscore. + +``k.or_(k2)`` +~~~~~~~~~~~~~ + +Bitwise or of ``k`` and ``k2``. Note trailing underscore. + +``k.xor(k2)`` +~~~~~~~~~~~~~ + +Bitwise exclusive-or of ``k`` and ``k2``. + +``k.icmp(icmp, k2)`` +~~~~~~~~~~~~~~~~~~~~ + +Compare ``k`` with ``k2`` using the predicate ``icmp``. See +`here `_ for list of predicates for integer +operands. + +``k.fcmp(fcmp, k2)`` +~~~~~~~~~~~~~~~~~~~~ + +Compare ``k`` with ``k2`` using the predicate ``fcmp``. See +`here `_ for list of predicates for real +operands. + +``k.shl(k2)`` +~~~~~~~~~~~~~ + +Shift ``k`` left by ``k2`` bits. + +``k.lshr(k2)`` +~~~~~~~~~~~~~~ + +Shift ``k`` logically right by ``k2`` bits (new bits are 0s). + +``k.ashr(k2)`` +~~~~~~~~~~~~~~ + +Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as +previous sign bit). + +``k.gep(indices)`` +~~~~~~~~~~~~~~~~~~ + +GEP, see `LLVM docs `_. + +``k.trunc(ty)`` +~~~~~~~~~~~~~~~ + +Truncate ``k`` to a type ``ty`` of lower bitwidth. + +``k.sext(ty)`` +~~~~~~~~~~~~~~ + +Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending +the sign bit. + +``k.zext(ty)`` +~~~~~~~~~~~~~~ + +Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are +0s. + +``k.fptrunc(ty)`` +~~~~~~~~~~~~~~~~~ + +Truncate floating point constant ``k`` to floating point type ``ty`` of +lower size than k's. + +``k.fpext(ty)`` +~~~~~~~~~~~~~~~ + +Extend floating point constant ``k`` to floating point type ``ty`` of +higher size than k's. + +``k.uitofp(ty)`` +~~~~~~~~~~~~~~~~ + +Convert an unsigned integer constant ``k`` to floating point constant of +type ``ty``. + +``k.sitofp(ty)`` +~~~~~~~~~~~~~~~~ + +Convert a signed integer constant ``k`` to floating point constant of +type ``ty``. + +``k.fptoui(ty)`` +~~~~~~~~~~~~~~~~ + +Convert a floating point constant ``k`` to an unsigned integer constant +of type ``ty``. + +``k.fptosi(ty)`` +~~~~~~~~~~~~~~~~ + +Convert a floating point constant ``k`` to a signed integer constant of +type ``ty``. + +``k.ptrtoint(ty)`` +~~~~~~~~~~~~~~~~~~ + +Convert a pointer constant ``k`` to an integer constant of type ``ty``. + +``k.inttoptr(ty)`` +~~~~~~~~~~~~~~~~~~ + +Convert an integer constant ``k`` to a pointer constant of type ``ty``. + +``k.bitcast(ty)`` +~~~~~~~~~~~~~~~~~ + +Convert ``k`` to a (equal-width) constant of type ``ty``. + +``k.select(cond,k2,k3)`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1, +else with ``k3``. + +``k.extract_element(idx)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Extract value at ``idx`` (integer constant) from a vector constant +``k``. + +``k.insert_element(k2,idx)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Insert value ``k2`` (scalar constant) at index ``idx`` (integer +constant) of vector constant ``k``. + +``k.shuffle_vector(k2,mask)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Shuffle vector constant ``k`` based on vector constants ``k2`` and +``mask``. + +-------------- + +# Other Constant Classes +The following subclasses of ``Constant`` do not provide additional +methods, **they serve only to provide richer type information.** + +Subclass \| LLVM C++ Class \| Remarks \| +---------\|----------------\|---------\| ``ConstantExpr`` \| +``llvmConstantExpr`` \| A constant expression \| +``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero +constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer +constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point +constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array +constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A +structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \| +A vector constant \| ``ConstantPointerNull``\ \| +``llvmConstantPointerNull``\ \| All-zero pointer constant \| +``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of +LLVM IR \| + +These types are helpful in ``isinstance`` checks, like so: + +{% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) # +int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = { +k1, k1 }; + +assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray) + Automatically Generated Documentation ------------------------------------- From 020032b57881968ba477be80dc365e8eba2b2a48 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 25 Apr 2013 14:10:57 -0500 Subject: [PATCH 184/338] 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 185/338] 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 186/338] 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 187/338] 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 188/338] 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 189/338] 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 190/338] 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 191/338] 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 192/338] 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 193/338] 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 194/338] 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 195/338] 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 196/338] 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 197/338] 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 198/338] 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 199/338] 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 200/338] 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 201/338] 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 202/338] 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 203/338] 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 204/338] 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 205/338] 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 206/338] 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 207/338] 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 208/338] 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 209/338] 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 210/338] 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 211/338] 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 212/338] 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 213/338] 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 214/338] 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 215/338] 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 216/338] 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 217/338] 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 218/338] 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 219/338] 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 220/338] 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 221/338] 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 222/338] 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 223/338] 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 224/338] 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 225/338] 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 226/338] 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 227/338] 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 228/338] 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 229/338] 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 230/338] 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 231/338] 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 232/338] 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 233/338] 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 234/338] 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 235/338] 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 236/338] 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 + +;