Compare commits

..

107 commits

Author SHA1 Message Date
Siu Kwan Lam
34900d2748 Update README.rst 2014-04-29 13:25:43 -05:00
Siu Kwan Lam
749b518b90 Update changelog 2014-04-28 11:06:48 -05:00
Siu Kwan Lam
c07fce0477 Update MANIFEST.in (#99) 2014-04-28 11:03:13 -05:00
Siu Kwan Lam
7f8476dd33 Fixing leaks (#92); thanks to ksshelt and eltjpm. 2014-04-04 15:14:47 -05:00
Siu Kwan Lam
57afefb069 Update change log 2014-03-20 15:00:11 -05:00
Siu Kwan Lam
0629ccb226 Allow BasicBlock downcast to Value 2014-03-19 11:33:01 -05:00
Siu Kwan Lam
6e4620edc6 Disable check_intrinsic 2014-03-13 13:47:09 -05:00
Siu Kwan Lam
2410267c8e Disable isolated test in conda build 2014-03-13 13:20:08 -05:00
Siu Kwan Lam
bc12aae8c1 Hashable Module and fix Module __eq__ 2014-03-11 15:17:06 -05:00
Siu Kwan Lam
6578412437 Add binding for dynamic library loading 2014-03-06 11:58:40 -06:00
Siu Kwan Lam
ce696c9b4e Update changelog 2014-02-18 14:30:39 -06:00
Siu Kwan Lam
3befa1be59 Merge pull request #94 from cgohlke/patch-1
Fix ImportError for C extensions on Python 3.4b2
2014-02-18 14:27:32 -06:00
Siu Kwan Lam
a9174f09c5 Merge pull request #88 from cantora/tests-import-TestCase
Fix broken tests from test refactor
2014-02-18 14:20:39 -06:00
Siu Kwan Lam
b86cc097d9 Fix deprecated function use 2014-02-18 14:13:40 -06:00
Jay Bourque
0e9f434ad8 Fix release date year in CHANGELOG 2014-02-10 10:54:08 -06:00
cgohlke
e868b825bb Fix ImportError of C extensions on Python 3.4b2 2014-02-04 15:52:41 -08:00
Ilan Schnell
dd2a569d76 fix release date 2014-02-04 14:22:53 -06:00
Siu Kwan Lam
059192f1ae Update change log 2014-01-31 17:33:32 -06:00
Siu Kwan Lam
3db6d8352a Fix isolated test runner 2014-01-16 18:34:19 -06:00
Siu Kwan Lam
00db78d89e Edit conda buildscript 2014-01-16 17:45:15 -06:00
Siu Kwan Lam
d9eb3ec175 Update setup.py 2014-01-16 17:11:21 -06:00
Siu Kwan Lam
4ed8f80774 Fix avx_support; only run check_intrinsics for conda build test 2014-01-16 17:03:40 -06:00
Siu Kwan Lam
43095609c3 Add intrinsic check 2014-01-16 16:49:23 -06:00
Siu Kwan Lam
b9cccbf9ae Close everything properly 2014-01-16 11:22:52 -06:00
Siu Kwan Lam
8689d62f02 Fix for PY3 2014-01-15 17:41:15 -06:00
Siu Kwan Lam
17d3cef4bd Fix build_pass_manager fpm handling 2013-12-31 16:57:45 -06:00
Siu Kwan Lam
ecac668bef Fix inline threshold and add size level 2013-12-27 22:21:33 -06:00
Siu Kwan Lam
078f1fe5c1 Move capsule code into C++ 2013-12-23 17:17:12 -06:00
Siu Kwan Lam
b9752e1e98 Add deprecated module and deprecate alloca_array 2013-12-20 12:26:35 -06:00
Siu Kwan Lam
f8c1c78df1 Leaner 2013-12-18 15:25:14 -06:00
Siu Kwan Lam
b8e0338da8 Add AllocaInstruction 2013-12-18 10:43:11 -06:00
Siu Kwan Lam
091a393d1d insert_value, extract_value can be multiple dimensional 2013-12-16 14:05:19 -06:00
anthony cantor
d7590fb029 change module name from llvm.test_llvmpy to llvm.tests.support
this seems to have been forgotten when test stuff was refactored.
2013-12-03 02:37:47 -07:00
Troy Powell
c199881b67 fixing index.rst 2013-11-18 15:59:01 -06:00
Ilan Schnell
fb3b6a3674 update changelog 2013-11-11 15:22:39 -06:00
Siu Kwan Lam
4e814b7d53 skip test for building executable from native object and assembly on OSX 2013-11-11 12:20:43 -06:00
Siu Kwan Lam
8a6dd7af7f fix loop-vectorize for llvm-3.3 2013-11-05 16:58:20 -06:00
Siu Kwan Lam
d08095299e add example for using vector instructions 2013-11-01 16:58:49 -05:00
Siu Kwan Lam
bf5859be7e fix bad version checking which disables auto-vectorization for llvm 3.3 2013-11-01 16:50:53 -05:00
Siu Kwan Lam
18d3b4809f Fix py2.6--use Popen instead of check_output 2013-10-05 13:55:26 +08:00
Siu Kwan Lam
a82e876f93 Add test skipping to disable arch specific tests conditionally 2013-10-05 13:37:04 +08:00
Siu Kwan Lam
1f7b9e3922 Fix setup.py 2013-10-04 15:35:22 +08:00
Siu Kwan Lam
fac1bc782d Reorganize and cleanup tests 2013-10-04 15:24:30 +08:00
Siu Kwan Lam
ea452bd33c Fix test 2013-09-30 17:18:30 -05:00
Siu Kwan Lam
ddf2007553 Adjust test for win32 x86 ABI 2013-09-30 17:13:06 -05:00
Siu Kwan Lam
e7a7896710 Adjust test for win32 amd64 ABI 2013-09-30 16:59:46 -05:00
Siu Kwan Lam
69a78d0a54 Test ABI for structures and reorganize tests a bit. 2013-09-30 16:24:26 -05:00
Siu Kwan Lam
cc4e4631bd fix windows build: include all LLVM static library 2013-09-19 17:38:46 -05:00
Siu Kwan Lam
8034854ad4 make visual studio happy 2013-09-19 17:11:54 -05:00
Siu Kwan Lam
733fd7d18e fix missing re-export for old llvm.ee symbols 2013-09-19 15:05:29 -05:00
Siu Kwan Lam
6e55bfc406 fix spaces redundant trailing spaces and missing line break at EOF 2013-09-18 11:58:05 -05:00
anthony cantor
72192c7e6a fixed documentation typo 2013-09-18 11:52:22 -05:00
anthony cantor
b303fd532a fixes to make this branch compatible with llvm versions before 3.4 2013-09-18 11:52:22 -05:00
anthony cantor
aa264cee2d added align parameter to llvm.mc.Disassembler.decode
i cant find any method in llvm to automatically get the
correct instruction alignment for disassembling. i thought
it would be MCAsmInfo.getMinInstAlignment, but that value is
1 for the ARM target machine. since that is clearly the wrong
instruction alignment for disassembling arm, the user should
be able to configure the alignment to whatever is needed.
2013-09-18 11:52:22 -05:00
anthony cantor
3743146121 only convert input bytes if they are a string and we are in python 3
in python 2 'str' and 'bytes' are the same. if input bytes are not
a string or bytes, then raise a TypeError.
2013-09-18 11:52:22 -05:00
anthony cantor
8de5c3faff added some methods to llvm.mc.Operand
methods that describe what type of operand it is
2013-09-18 11:52:22 -05:00
anthony cantor
083586464b add bindings for instruction description methods to MCInstrDesc
use these new bindings instead of MCInstrAnalysis bindings in
llvm.mc.Instr because MCInstrAnalaysis is just a thin layer
encapsulating MCInstrInfo that seems largely pointless.
2013-09-18 11:52:22 -05:00
anthony cantor
0f3d5a8127 decode yields a tuple of integers instead of a bytearray
a tuple of integers is immutable and more similar to python 3
bytes than bytearray
2013-09-18 11:52:22 -05:00
anthony cantor
3e77a55de3 added methods to Instr which describe possible branch/terminator properties 2013-09-18 11:52:22 -05:00
anthony cantor
65c4558cac added opcode property to llvm.mc.Instr 2013-09-18 11:52:22 -05:00
anthony cantor
43f7330fda llvm.mc.Disassembler.decode now yields the byte sequence which generated the instruction
added custom method to extra.h to return a PyBytes object
from the bytes read from MemoryObject.readBytes.

also moved the generic methods from StringRefMemoryObject
up to MemoryObject
2013-09-18 11:52:22 -05:00
anthony cantor
1d735e49d2 fix python2/3 incompatibility
bytes built-in is different in python2
2013-09-18 11:52:22 -05:00
anthony cantor
fea82991c3 convert str input to bytes
StringRefMemoryObject constructor binding specifies bytes as
its input parameter, so we have to convert it.
2013-09-18 11:52:22 -05:00
anthony cantor
b3bf7f86cd MCExpr pointer is owned by the MCOperand object 2013-09-18 11:52:22 -05:00
anthony cantor
3c06f0d590 add flags, ts_flags properties for Instr class 2013-09-18 11:52:22 -05:00
anthony cantor
cadc53f174 no need for get method in TargetInstrInfo
MCInstrInfo parent already has a binding
2013-09-18 11:52:22 -05:00
anthony cantor
0ed471d336 added example-instruction-info.py
demonstrates getting flag information for an opcode
2013-09-18 11:52:22 -05:00
anthony cantor
7234b0d200 use getRegInfo instead of creating a register info object
also raise exception if a property is accessed which is not
available on that particular TargetMachine.
2013-09-18 11:52:22 -05:00
anthony cantor
fa3aec8353 added some bindings to TargetMachine methods
these methods return pointers to MC objects relevant
to the arch the TargetMachine represents.
2013-09-18 11:52:21 -05:00
anthony cantor
bd9d71c713 added some bindings for MC classes 2013-09-18 11:52:21 -05:00
anthony cantor
8dbfc377ad added functionality to llvm.mc.Instr to print itself
uses binding of printInst on MCInstPrinter for printing
instruction.

also fixed a bug in llvm.mc.Disassembler.decode: idx should
start at zero, and we should pass code.getBase() + idx to
getInstruction. idx must start at zero because the while loop
compares it against code.getExtent() which returns only the
length of bs.
2013-09-18 11:52:21 -05:00
anthony cantor
82d9c787f3 added llvm.mc.Operand class
Operand encapsulates information that llvm provides about an MCOperand
in an instruction.
2013-09-18 11:52:21 -05:00
anthony cantor
87d444c9e9 added tests to testall for llvm.target and llvm.mc
tests dont check for correctness, just exercise the API
2013-09-18 11:52:21 -05:00
anthony cantor
fa26aa1651 fix typo 2013-09-18 11:52:21 -05:00
anthony cantor
cbf4a61a17 moved the MC data type access to TargetMachine
Disassembler now simply needs a TargetMachine object
and it will be able to access all the descriptor objects
it needs for disassembly through the target machine.
2013-09-18 11:52:21 -05:00
anthony cantor
0e265a2cc5 TargetTransformInfo stuff doesnt work in llvm >= 3.3 2013-09-18 11:52:21 -05:00
anthony cantor
e65f6174a7 some fixes so that test/testall.py will run
some easy changes to core.py which were just conditionals on llvm
version. for the broken tests which i didnt know how to fix i
simply disabled them.
2013-09-18 11:52:21 -05:00
anthony cantor
83299a20a6 refactor TargetMachine into a new target module
TargetMachine is generally useful outside of the execution engine
context so i think it makes sense to move it into its own module.
2013-09-18 11:52:21 -05:00
anthony cantor
97c0e15e72 add some MCAsmInfo bindings 2013-09-18 11:52:21 -05:00
anthony cantor
4eab936224 added new MC classes for richer disassembling functionality 2013-09-18 11:52:21 -05:00
anthony cantor
78be6a7f5f conditionals for compatibility with llvm < 3.4
i only intend to support MC bindings (and anything reliant on MC)
for llvm 3.4 and greater.
2013-09-18 11:52:21 -05:00
anthony cantor
bc02b3d90a use (llvm 3.4) built in StringRefMemoryObject instead of BytesMemoryObject 2013-09-18 11:52:21 -05:00
anthony cantor
aa0ee9b6a6 changes to make llvmpy compatible with development branch of llvm
mostly just removing stuff and changing function prototypes.
with these changes, llvmpy compiles and llvm.test() passes.
2013-09-18 11:52:21 -05:00
anthony cantor
0610a27535 add MCAsmInfo 2013-09-18 11:52:21 -05:00
anthony cantor
f4bbb18e47 fixed arm test: arm code needs to be reverse b.c. its little endian 2013-09-18 11:52:20 -05:00
anthony cantor
25e6651055 added MCOperand methods 2013-09-18 11:52:20 -05:00
anthony cantor
38a00c6e55 fixed typo in new_from_triple and added args to new_from_name
new_from_triple: need to pass subtarget info to new_from_target

new_from_name: allow caller to pass cpu and feature info
2013-09-18 11:52:20 -05:00
anthony cantor
818c9289fc implemented binding for MCDisassembler.getInstruction
also added new llvm.mc module to act as higher level
python access to the MC section of LLVM (added Instr
and Disassembler classes).
2013-09-18 11:52:20 -05:00
anthony cantor
ba03b226c8 added Target.createMCSubtargetInfo and createMCDisassembler
also added bindings to classes required by the target methods. also
added a convenience function to initialize all target components to
the llvm module
2013-09-18 11:52:20 -05:00
anthony cantor
8f2c27ba41 added TargetRegistry_targets_list
this allows all targets to be enumerated. this is generally useful,
but i specifically wanted to be able to see which targets report
having a disassembler. it is necessary to init the various
target components in order for them to report that they have one,
thus i added InitializeAllDisassemblers and InitializeAllAsmParsers
to TargetSelect.py
2013-09-18 11:52:20 -05:00
anthony cantor
ef59848d18 modify build process to support all targets
my goal is to facillitate a wide range of disassembly capability through
llvm disassemblers, so supporting as many machine targets as possible is ideal.
2013-09-18 11:52:20 -05:00
anthony cantor
4905743e0a add BytesMemoryObject to extra.h and a binding for it in llvmpy/src 2013-09-18 11:52:20 -05:00
Jon Riehl
09d9dbba1e Merge pull request #83 from sergiopasra/noshebang
Remove shebangs from library code
2013-09-09 14:12:40 -07:00
Sergio Pascual
aae25f5e55 Remove shebangs from library code 2013-09-09 13:00:01 +02:00
Siu Kwan Lam
af2c1d6d01 update change log 2013-08-28 17:11:03 -05:00
Siu Kwan Lam
4e993570cd disable logging to avoid a exception ignored message 2013-08-28 14:18:35 -05:00
Siu Kwan Lam
6bbf53241d revive a casting code in the binding 2013-08-28 13:55:38 -05:00
Siu Kwan Lam
0801df41dc fix upcasting problem (#77 thanks to cantora) 2013-08-26 12:23:28 -05:00
Siu Kwan Lam
24f1b33737 Fix a ownership bug (thanks to cantora) 2013-08-23 10:59:47 -05:00
Siu Kwan Lam
536bc37c94 Disable MCJIT test on windows 64-bit (#79) 2013-08-22 14:13:17 -05:00
Jay Bourque
351bd39814 Python3 fix: Implement __hash__ method for Value class 2013-08-20 17:20:57 -05:00
majidaldo
33ca795e0c remove chrpath 2013-08-16 11:50:38 -05:00
Siu Kwan Lam
d57c4d88c6 fix x86 arch type for LLRT 2013-08-14 18:25:32 -05:00
Siu Kwan Lam
328f88bbd5 llvm3.3 has a different TargetTransformInfo 2013-08-14 18:18:05 -05:00
Siu Kwan Lam
ea5b430297 add IR files in setup.py 2013-08-14 18:09:17 -05:00
Siu Kwan Lam
5f01343bba Merge branch 'llrt' 2013-08-14 17:45:58 -05:00
majidaldo
7d1c4c18a0 high version number 2013-08-14 14:39:10 -05:00
109 changed files with 5706 additions and 2695 deletions

View file

@ -1,3 +1,40 @@
2014-04-28 0.12.5:
---------------------
* Fixes memory leaks (#92)
* Fixes tarball (#99)
2014-03-20 0.12.4:
---------------------
* Add dylib_import_library and friends
* Fix BasicBlock downcast
* Module hashing
* Fix test script
2014-02-18 0.12.3:
---------------------
* Fix deprecation message for py2.6
* Fix llvm_cbuilder for using deprecated_alloca
* Merged PR #88 by cantora
* Merged PR #94 by cgohlke
2014-02-04 0.12.2:
---------------------
* enhance wrapper efficiency by moving some capsule code into C++
* fix unclosed file handler in avx_support
* multiple-dimension insert_value, extract_value
* various minor fixes
2013-11-11 0.12.1:
---------------------
* various bug fixes
2013-08-28 0.12.0:
---------------------
* update to LLVM 3.3 and maintain compatibility with LLVM 3.2
* add LLRT for minimal support for 64-bit divmod on 32-bit platform
* start to adopt MCJIT (not quite usable on win32)
* various bug fixes
2013-03-05 0.11.1:
--------------------
* fix test when cc is not available

View file

@ -1,5 +1,6 @@
include CHANGELOG LICENSE README setup.py MANIFEST.in
include CHANGELOG LICENSE README.rst setup.py MANIFEST.in versioneer.py
recursive-include llvm *
recursive-include llvmpy *
recursive-include www *
recursive-include test *
recursive-include tools *

View file

@ -30,10 +30,13 @@ Quickstart
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.
3. Run ``REQUIRES_RTTI=1 make install`` to build and install.
**Note**: With LLVM 3.2, the default build configuration has C++ RTTI
disabled. However, llvmpy requires RTTI.
**Note**: Use ``make -j2 install`` to enable concurrent build.
Replace ``2`` with the actual number of processor you have.
4. Get llvm-py and install it::

View file

@ -1,6 +1,6 @@
package:
name: llvmpy
version: master
version: 99.9.9
source:
git_url: git@github.com:llvmpy/llvmpy.git
@ -10,7 +10,7 @@ requirements:
build:
- llvm
- python
- chrpath [linux]
#- chrpath [linux]
run:
- llvm [unix]
- python

View file

@ -4,6 +4,8 @@ import llvm
from llvm.core import Module
from llvm.ee import EngineBuilder
from llvm.utils import check_intrinsics
m = Module.new('fjoidajfa')
eb = EngineBuilder.new(m)
target = eb.select_target()
@ -13,7 +15,8 @@ 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
assert llvm.test(verbosity=2, run_isolated=False) == 0
#check_intrinsics.main()
print('llvm.__version__: %s' % llvm.__version__)
#assert llvm.__version__ == '0.12.0'

View file

@ -3,8 +3,8 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Documentation for llvmpy
========================
llvmpy
======
Contents:
@ -22,7 +22,7 @@ Contents:
Indices and tables
==================
------------------
* :ref:`genindex`
* :ref:`modindex`

152
example/vector_instr.py Normal file
View file

@ -0,0 +1,152 @@
'''
This example shows:
1) how to use vector instructions
2) how to take advantage of LLVM loop vectorization to transform scalar
operations to vector operations
'''
from __future__ import print_function
import llvm.core as lc
import llvm.ee as le
import llvm.passes as lp
from ctypes import CFUNCTYPE, POINTER, c_int, c_float
def build_manual_vector():
mod = lc.Module.new('manual.vector')
intty = lc.Type.int(32)
vecty = lc.Type.vector(lc.Type.float(), 4)
aryty = lc.Type.pointer(lc.Type.float())
fnty = lc.Type.function(lc.Type.void(), [aryty, aryty, aryty, intty])
fn = mod.add_function(fnty, name='vector_add')
bbentry = fn.append_basic_block('entry')
bbloopcond = fn.append_basic_block('loop.cond')
bbloopbody = fn.append_basic_block('loop.body')
bbexit = fn.append_basic_block('exit')
builder = lc.Builder.new(bbentry)
# populate function body
in1, in2, out, size = fn.args
ZERO = lc.Constant.null(intty)
loopi_ptr = builder.alloca(intty)
builder.store(ZERO, loopi_ptr)
builder.branch(bbloopcond)
builder.position_at_end(bbloopcond)
loopi = builder.load(loopi_ptr)
loopcond = builder.icmp(lc.ICMP_ULT, loopi, size)
builder.cbranch(loopcond, bbloopbody, bbexit)
builder.position_at_end(bbloopbody)
vecaryty = lc.Type.pointer(vecty)
in1asvec = builder.bitcast(builder.gep(in1, [loopi]), vecaryty)
in2asvec = builder.bitcast(builder.gep(in2, [loopi]), vecaryty)
outasvec = builder.bitcast(builder.gep(out, [loopi]), vecaryty)
vec1 = builder.load(in1asvec)
vec2 = builder.load(in2asvec)
vecout = builder.fadd(vec1, vec2)
builder.store(vecout, outasvec)
next = builder.add(loopi, lc.Constant.int(intty, 4))
builder.store(next, loopi_ptr)
builder.branch(bbloopcond)
builder.position_at_end(bbexit)
builder.ret_void()
return mod, fn
def build_auto_vector():
mod = lc.Module.new('auto.vector')
# Loop vectorize is sensitive to the size of the index size(!?)
intty = lc.Type.int(tuple.__itemsize__ * 8)
aryty = lc.Type.pointer(lc.Type.float())
fnty = lc.Type.function(lc.Type.void(), [aryty, aryty, aryty, intty])
fn = mod.add_function(fnty, name='vector_add')
bbentry = fn.append_basic_block('entry')
bbloopcond = fn.append_basic_block('loop.cond')
bbloopbody = fn.append_basic_block('loop.body')
bbexit = fn.append_basic_block('exit')
builder = lc.Builder.new(bbentry)
# populate function body
in1, in2, out, size = fn.args
in1.add_attribute(lc.ATTR_NO_ALIAS)
in2.add_attribute(lc.ATTR_NO_ALIAS)
out.add_attribute(lc.ATTR_NO_ALIAS)
ZERO = lc.Constant.null(intty)
loopi_ptr = builder.alloca(intty)
builder.store(ZERO, loopi_ptr)
builder.branch(bbloopcond)
builder.position_at_end(bbloopcond)
loopi = builder.load(loopi_ptr)
loopcond = builder.icmp(lc.ICMP_ULT, loopi, size)
builder.cbranch(loopcond, bbloopbody, bbexit)
builder.position_at_end(bbloopbody)
in1elem = builder.load(builder.gep(in1, [loopi]))
in2elem = builder.load(builder.gep(in2, [loopi]))
outelem = builder.fadd(in1elem, in2elem)
builder.store(outelem, builder.gep(out, [loopi]))
next = builder.add(loopi, lc.Constant.int(intty, 1))
builder.store(next, loopi_ptr)
builder.branch(bbloopcond)
builder.position_at_end(bbexit)
builder.ret_void()
return mod, fn
def example(title, module_builder, opt):
print(title.center(80, '='))
mod, fn = module_builder()
eb = le.EngineBuilder.new(mod).opt(3)
if opt:
print('opt')
tm = eb.select_target()
pms = lp.build_pass_managers(mod=mod, tm=tm, opt=3, loop_vectorize=True,
fpm=False)
pms.pm.run(mod)
print(mod)
print(mod.to_native_assembly())
engine = eb.create()
ptr = engine.get_pointer_to_function(fn)
callable = CFUNCTYPE(None, POINTER(c_float), POINTER(c_float),
POINTER(c_float), c_int)(ptr)
N = 20
in1 = (c_float * N)(*range(N))
in2 = (c_float * N)(*range(N))
out = (c_float * N)()
print('in1: ', list(in1))
print('in1: ', list(in2))
callable(in1, in2, out, N)
print('out', list(out))
def main():
example('manual vector function', build_manual_vector, False)
example('auto vector function', build_auto_vector, True)
if __name__ == '__main__':
main()

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import opcode

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import dis

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
'''Defines a bytecode based LLVM translator for llpython code.
'''

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import itertools

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
import ctypes

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
import pprint

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
from . import opcode_util

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import sys

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
import dis

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
from .bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
import ctypes

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
def doslice (in_string, lower, upper):

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
import llvm.core as lc

View file

@ -2,6 +2,7 @@ import re
import sys
from distutils.spawn import find_executable
from os.path import abspath, dirname, isfile, join
from os import listdir
from subprocess import Popen, PIPE
@ -39,57 +40,17 @@ def libs_options():
# 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
LLVMMCJIT
LLVMLinker
LLVMMC
LLVMMCParser
LLVMObject
LLVMRuntimeDyld
LLVMScalarOpts
LLVMSelectionDAG
LLVMSupport
LLVMTarget
LLVMTransformUtils
LLVMVectorize
LLVMX86AsmParser
LLVMX86AsmPrinter
LLVMX86CodeGen
LLVMX86Desc
LLVMX86Disassembler
LLVMX86Info
LLVMX86Utils
LLVMDebugInfo
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')
bpath = join(find_llvm_prefix(), 'lib')
for filename in listdir(bpath):
filepath = join(bpath, filename)
if isfile(filepath) and filename.endswith('.lib') and filename.startswith('LLVM'):
name = filename.split('.', 1)[0]
print('-l%s' % name)
def main():
try:

View file

@ -4,10 +4,13 @@ del get_versions
from llvmpy import extra
version = extra.get_llvm_version()
del extra
class Wrapper(object):
__slots__ = '__ptr'
def __init__(self, ptr):
assert ptr
self.__ptr = ptr
@ -31,14 +34,14 @@ def _extract_ptrs(objs):
class LLVMException(Exception):
pass
def test(verbosity=1):
def test(verbosity=3, run_isolated=True):
"""test(verbosity=1) -> TextTestResult
Run self-test, and return the number of failures + errors
"""
from llvm.test_llvmpy import run
from llvm.tests import run
result = run(verbosity=verbosity)
return len(result.failures) + len(result.errors)
result = run(verbosity=verbosity, run_isolated=run_isolated)
errct = len(result.failures) + len(result.errors)
return errct

View file

@ -41,7 +41,7 @@ import contextlib, weakref
import llvm
from llvm._intrinsic_ids import *
from llvm.deprecated import deprecated
from llvmpy import api
#===----------------------------------------------------------------------===
@ -211,15 +211,17 @@ class CCEnum(Enum):
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
if llvm.version <= (3, 3):
CC_MBLAZE_INTR = ID.MBLAZE_INTR
CC_MBLAZE_SVOL = ID.MBLAZE_SVOL
CCEnum.declare()
# int predicates
class ICMPEnum(Enum):
prefix = 'ICMP_'
Predicate = api.llvm.CmpInst.Predicate
ICMP_EQ = Predicate.ICMP_EQ
@ -377,6 +379,7 @@ class Module(llvm.Wrapper):
module_obj = Module.new('my_module')
"""
__slots__ = '__weakref__'
__cache = weakref.WeakValueDictionary()
def __new__(cls, ptr):
@ -449,12 +452,12 @@ class Module(llvm.Wrapper):
"""
return str(self._ptr)
def __hash__(self):
return id(self._ptr)
def __eq__(self, rhs):
assert isinstance(rhs, Module), type(rhs)
if isinstance(rhs, Module):
return str(self) == str(rhs)
else:
return False
return self._ptr == rhs._ptr
def __ne__(self, rhs):
return not (self == rhs)
@ -686,6 +689,7 @@ class Type(llvm.Wrapper):
Use one of the static methods to create an instance. Example:
ty = Type.double()
"""
__slots__ = '__name__'
_type_ = api.llvm.Type
def __init__(self, ptr):
@ -878,6 +882,7 @@ class Type(llvm.Wrapper):
class IntegerType(Type):
"""Represents an integer type."""
__slots__ = ()
_type_ = api.llvm.IntegerType
@property
@ -887,6 +892,7 @@ class IntegerType(Type):
class FunctionType(Type):
"""Represents a function type."""
__slots__ = ()
_type_ = api.llvm.FunctionType
@property
@ -916,6 +922,7 @@ class FunctionType(Type):
class StructType(Type):
"""Represents a structure type."""
_type_ = api.llvm.StructType
__slots__ = ()
@property
def element_count(self):
@ -951,7 +958,7 @@ class StructType(Type):
def _get_name(self):
if self._ptr.isLiteral():
return ""
else:
else:
return self._ptr.getName()
name = property(_get_name, _set_name)
@ -974,6 +981,7 @@ class StructType(Type):
class ArrayType(Type):
"""Represents an array type."""
_type_ = api.llvm.ArrayType
__slots__ = ()
@property
def element(self):
@ -985,6 +993,7 @@ class ArrayType(Type):
class PointerType(Type):
_type_ = api.llvm.PointerType
__slots__ = ()
@property
def pointee(self):
@ -996,6 +1005,7 @@ class PointerType(Type):
class VectorType(Type):
_type_ = api.llvm.VectorType
__slots__ = ()
@property
def element(self):
@ -1007,6 +1017,7 @@ class VectorType(Type):
class Value(llvm.Wrapper):
_type_ = api.llvm.Value
__slots__ = '__weakref__'
def __init__(self, builder, ptr):
assert builder is _ValueFactory
@ -1037,6 +1048,9 @@ class Value(llvm.Wrapper):
def __str__(self):
return str(self._ptr)
def __hash__(self):
return hash(self._ptr)
def __eq__(self, rhs):
if isinstance(rhs, Value):
return str(self) == str(rhs)
@ -1072,6 +1086,7 @@ class Value(llvm.Wrapper):
class User(Value):
_type_ = api.llvm.User
__slots__ = ()
@property
def operand_count(self):
@ -1086,6 +1101,7 @@ class User(Value):
class Constant(User):
_type_ = api.llvm.Constant
__slots__ = ()
@staticmethod
def null(ty):
@ -1271,6 +1287,7 @@ class Constant(User):
class ConstantExpr(Constant):
_type_ = api.llvm.ConstantExpr
__slots__ = ()
@property
def opcode(self):
@ -1281,19 +1298,20 @@ class ConstantExpr(Constant):
return self._ptr.getOpcodeName()
class ConstantAggregateZero(Constant):
pass
__slots__ = ()
class ConstantDataArray(Constant):
pass
__slots__ = ()
class ConstantDataVector(Constant):
pass
__slots__ = ()
class ConstantInt(Constant):
_type_ = api.llvm.ConstantInt
__slots__ = ()
@property
def z_ext_value(self):
@ -1309,30 +1327,32 @@ class ConstantInt(Constant):
class ConstantFP(Constant):
pass
__slots__ = ()
class ConstantArray(Constant):
pass
__slots__ = ()
class ConstantStruct(Constant):
pass
__slots__ = ()
class ConstantVector(Constant):
pass
__slots__ = ()
class ConstantPointerNull(Constant):
pass
__slots__ = ()
class UndefValue(Constant):
pass
__slots__ = ()
class GlobalValue(Constant):
_type_ = api.llvm.GlobalValue
__slots__ = ()
def _get_linkage(self):
return self._ptr.getLinkage()
@ -1378,6 +1398,7 @@ class GlobalValue(Constant):
class GlobalVariable(GlobalValue):
_type_ = api.llvm.GlobalVariable
__slots__ = ()
@staticmethod
def new(module, ty, name, addrspace=0):
@ -1438,6 +1459,7 @@ class GlobalVariable(GlobalValue):
thread_local = property(_get_thread_local, _set_thread_local)
class Argument(Value):
__slots__ = ()
_type_ = api.llvm.Argument
_valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS,
ATTR_NO_CAPTURE, ATTR_STRUCT_RET])
@ -1449,7 +1471,7 @@ class Argument(Value):
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))
@ -1538,6 +1560,7 @@ class Argument(Value):
return self._ptr.hasStructRetAttr()
class Function(GlobalValue):
__slots__ = ()
_type_ = api.llvm.Function
@staticmethod
@ -1647,7 +1670,10 @@ class Function(GlobalValue):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAttribute(attr)
attrs = api.llvm.Attributes.get(context, attrbldr)
if llvm.version >= (3, 3):
attrs = api.llvm.Attribute.get(context, attrbldr)
else:
attrs = api.llvm.Attributes.get(context, attrbldr)
self._ptr.removeFnAttr(attrs)
def viewCFGOnly(self):
@ -1673,6 +1699,7 @@ class Function(GlobalValue):
#===----------------------------------------------------------------------===
class InlineAsm(Value):
__slots__ = ()
_type_ = api.llvm.InlineAsm
@staticmethod
@ -1687,6 +1714,7 @@ class InlineAsm(Value):
#===----------------------------------------------------------------------===
class MetaData(Value):
__slots__ = ()
_type_ = api.llvm.MDNode
@staticmethod
@ -1743,6 +1771,7 @@ class MetaDataString(Value):
class NamedMetaData(llvm.Wrapper):
__slots__ = ()
@staticmethod
def get_or_insert(mod, name):
@ -1772,6 +1801,7 @@ class NamedMetaData(llvm.Wrapper):
#===----------------------------------------------------------------------===
class Instruction(User):
__slots__ = ()
_type_ = api.llvm.Instruction
@property
@ -1853,6 +1883,7 @@ class Instruction(User):
class CallOrInvokeInstruction(Instruction):
__slots__ = ()
_type_ = api.llvm.CallInst, api.llvm.InvokeInst
def _get_cc(self):
@ -1867,21 +1898,33 @@ class CallOrInvokeInstruction(Instruction):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAttribute(attr)
attrs = api.llvm.Attributes.get(context, attrbldr)
if llvm.version >= (3, 3):
attrs = api.llvm.Attribute.get(context, attrbldr)
else:
attrs = api.llvm.Attributes.get(context, attrbldr)
self._ptr.addAttribute(idx, attrs)
def remove_parameter_attribute(self, idx, attr):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAttribute(attr)
attrs = api.llvm.Attributes.get(context, attrbldr)
if llvm.version >= (3, 3):
attrs = api.llvm.Attribute.get(context, attrbldr)
else:
attrs = api.llvm.Attributes.get(context, attrbldr)
self._ptr.removeAttribute(idx, attrs)
def set_parameter_alignment(self, idx, align):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAlignmentAttr(align)
attrs = api.llvm.Attributes.get(context, attrbldr)
if llvm.version >= (3, 3):
attrs = api.llvm.Attribute.get(context, attrbldr)
else:
attrs = api.llvm.Attributes.get(context, attrbldr)
self._ptr.addAttribute(idx, attrs)
def _get_called_function(self):
@ -1896,6 +1939,7 @@ class CallOrInvokeInstruction(Instruction):
class PHINode(Instruction):
__slots__ = ()
_type_ = api.llvm.PHINode
@property
@ -1913,6 +1957,7 @@ class PHINode(Instruction):
class SwitchInstruction(Instruction):
__slots__ = ()
_type_ = api.llvm.SwitchInst
def add_case(self, const, bblk):
@ -1920,6 +1965,7 @@ class SwitchInstruction(Instruction):
class CompareInstruction(Instruction):
__slots__ = ()
_type_ = api.llvm.CmpInst
@property
@ -1931,11 +1977,40 @@ class CompareInstruction(Instruction):
return FCMPEnum.get(n)
class AllocaInstruction(Instruction):
__slots__ = ()
_type_ = api.llvm.AllocaInst
@property
def alignment(self):
return self._ptr.getAlignment()
@alignment.setter
def alignment(self, n):
self._ptr.setAlignment(n)
@property
def array_size(self):
return self._ptr.getArraySize()
@array_size.setter
def array_size(self, value):
return self._ptr.setArraySize(value._ptr)._ptr
@property
def is_array(self):
return self._ptr.isArrayAllocation()
@property
def is_static(self):
return self._ptr.isStaticAlloca()
#===----------------------------------------------------------------------===
# Basic block
#===----------------------------------------------------------------------===
class BasicBlock(Value):
__slots__ = ()
_type_ = api.llvm.BasicBlock
def insert_before(self, name):
@ -1962,6 +2037,7 @@ class BasicBlock(Value):
class _ValueFactory(object):
__slots__ = ()
cache = weakref.WeakValueDictionary()
# value ID -> class map
@ -1990,7 +2066,8 @@ class _ValueFactory(object):
VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction,
VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction,
VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction,
VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction
VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction,
VALUE_INSTRUCTION + OPCODE_ALLOCA : AllocaInstruction,
}
@classmethod
@ -2037,6 +2114,7 @@ _atomic_orderings = {
}
class Builder(llvm.Wrapper):
__slots__ = ()
@staticmethod
def new(basic_block):
@ -2198,7 +2276,6 @@ class Builder(llvm.Wrapper):
# memory
def malloc(self, ty, name=""):
context = api.llvm.getGlobalContext()
allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr)
ity = allocsz.getType()
malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr,
@ -2212,7 +2289,6 @@ class Builder(llvm.Wrapper):
return _make_value(inst)
def malloc_array(self, ty, size, name=""):
context = api.llvm.getGlobalContext()
allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr)
ity = allocsz.getType()
malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr,
@ -2225,12 +2301,13 @@ class Builder(llvm.Wrapper):
inst = self._ptr.Insert(malloc, name)
return _make_value(inst)
def alloca(self, ty, name=""):
intty = Type.int()
return _make_value(self._ptr.CreateAlloca(ty._ptr, None, name))
def alloca(self, ty, size=None, name=""):
sizeptr = size._ptr if size else None
return _make_value(self._ptr.CreateAlloca(ty._ptr, sizeptr, name))
@deprecated
def alloca_array(self, ty, size, name=""):
return _make_value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name))
return self.alloca(ty, size, name=name)
def free(self, ptr):
free = api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr)
@ -2317,15 +2394,20 @@ class Builder(llvm.Wrapper):
# misc
def extract_value(self, retval, idx, name=""):
return _make_value(self._ptr.CreateExtractValue(retval._ptr, [idx], name))
if not isinstance(idx, (tuple, list)):
idx = [idx]
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=""):
if not isinstance(idx, (tuple, list)):
idx = [idx]
return _make_value(self._ptr.CreateInsertValue(retval._ptr,
rhs._ptr,
[idx],
idx,
name))
def phi(self, ty, name=""):

25
llvm/deprecated.py Normal file
View file

@ -0,0 +1,25 @@
"""
Shameless borrowed from Smart_deprecation_warnings
https://wiki.python.org/moin/PythonDecoratorLibrary
"""
import warnings
import functools
def deprecated(func):
"""This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
when the function is used."""
@functools.wraps(func)
def new_func(*args, **kwargs):
warnings.warn_explicit(
"Call to deprecated function %s." % (func.__name__,),
category=DeprecationWarning,
filename=func.func_code.co_filename,
lineno=func.func_code.co_firstlineno + 1
)
return func(*args, **kwargs)
return new_func

View file

@ -31,33 +31,22 @@
"Execution Engine and related classes."
import sys
from io import BytesIO
import contextlib
import llvm
from llvm import core
from llvm.passes import TargetData, TargetTransformInfo
from llvmpy import api, extra
#===----------------------------------------------------------------------===
# Enumerations
# import items which were moved to target module
#===----------------------------------------------------------------------===
from llvm.target import (initialize_all, initialize_target,
print_registered_targets, get_host_cpu_name, get_default_triple,
TargetMachine,
BO_BIG_ENDIAN, BO_LITTLE_ENDIAN,
CM_DEFAULT, CM_JITDEFAULT, CM_SMALL, CM_KERNEL, CM_MEDIUM, CM_LARGE,
RELOC_DEFAULT, RELOC_STATIC, RELOC_PIC, RELOC_DYNAMIC_NO_PIC)
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
# 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
@ -239,150 +228,6 @@ class ExecutionEngine(llvm.Wrapper):
ptr = self._ptr.getDataLayout()
return TargetData(ptr)
#===----------------------------------------------------------------------===
# 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', 'AsmParser']
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
'''
api.llvm.TargetRegistry.printRegisteredTargetsForVersion()
def get_host_cpu_name():
'''return the string name of the host CPU
'''
return api.llvm.sys.getHostCPUName()
def get_default_triple():
'''return the target triple of the host in str-rep
'''
return api.llvm.sys.getDefaultTargetTriple()
class TargetMachine(llvm.Wrapper):
@staticmethod
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
if not triple:
triple = get_default_triple()
if not cpu:
cpu = get_host_cpu_name()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(triple, cpu, features,
target_options,
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,
reloc=RELOC_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(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(str(triple), cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
def _emit_file(self, module, cgft):
pm = api.llvm.PassManager.new()
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)
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
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
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._ptr, 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()
#===----------------------------------------------------------------------===
# Dynamic Library
@ -393,3 +238,27 @@ def dylib_add_symbol(name, ptr):
def dylib_address_of_symbol(name):
return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name)
def dylib_import_library(filename):
"""Permanently import a dynamic library.
Returns a DynamicLibrary object
Raises RuntimeError
"""
return DynamicLibrary(filename)
class DynamicLibrary(object):
def __init__(self, filename):
"""
Raises RuntimeError
"""
self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary(
filename)
def get_address_of_symbol(self, symbol):
"""
Get the address of `symbol` (str) as integer
"""
return self._ptr.getAddressOfSymbol(symbol)

View file

@ -38,9 +38,11 @@ def _replace_with(builder, inst, func):
def load(arch):
'''Load the LLRT module corresponding to the given architecture
Creates a new module and optimizes it using the information from
Creates a new module and optimizes it using the information from
the host machine.
'''
if arch != 'x86_64':
arch = 'x86'
path = os.path.join(os.path.dirname(__file__), 'llrt', 'llrt_%s.ll' % arch)
with open(path) as fin:
lib = lc.Module.from_assembly(fin)

242
llvm/mc/__init__.py Normal file
View file

@ -0,0 +1,242 @@
import sys
import llvm
if llvm.version < (3, 4):
raise Exception("mc is not supported for llvm version less than 3.4")
from io import BytesIO
import contextlib
from llvmpy import api, extra
from llvmpy.api.llvm import MCDisassembler
class Operand(object):
def __init__(self, mcoperand, target_machine):
'''
@mcoperand: an MCOperand object
@target_machine: an llvm.target.TargetMachine object
'''
self.op = mcoperand
if not self.op:
raise llvm.LLVMException("null MCOperand argument")
self.tm = target_machine
def __str__(self):
s = "invalid"
if self.is_reg():
s = "reg(%s)" % (self.reg_name())
elif self.is_imm():
s = "imm(0x%02x)" % (self.op.getImm())
elif self.is_fp_imm():
s = "imm(%r)" % (self.op.getFPImm())
elif self.is_expr():
s = "expr(%r)" % (self.op.getExpr().getKind())
elif self.is_inst():
s = repr(Instr(self.op.getInst()))
return s
def __repr__(self):
return str(self)
def reg_name(self):
if self.is_reg():
s = self.tm.reg_info.getName(self.op.getReg())
if s.strip() == "":
return "?"
else:
return s
else:
return ""
def is_reg(self):
return self.op.isReg()
def is_imm(self):
return self.op.isImm()
def is_fp_imm(self):
return self.op.isFPImm()
def is_expr(self):
return self.op.isExpr()
def is_inst(self):
return self.op.isInst()
def get_imm(self):
if self.is_imm():
return self.op.getImm()
else:
return None
def get_fp_imm(self):
if self.is_fp_imm():
return self.op.getFPImm()
else:
return None
def get_inst(self):
if self.is_inst():
return Instr(self.op.getInst())
else:
return None
class Instr(object):
def __init__(self, mcinst, target_machine):
'''
@mcinst: an MCInst object
@target_machine: an llvm.target.TargetMachine object
'''
self.mcinst = mcinst
if not self.mcinst:
raise llvm.LLVMException("null MCInst argument")
self.tm = target_machine
def __str__(self):
os = extra.make_raw_ostream_for_printing()
self.tm.inst_printer.printInst(self.mcinst, os, "")
return str(os.str())
def __repr__(self):
return str(self)
def __len__(self):
''' the number of operands '''
return int(self.mcinst.size())
def operands(self):
amt = self.mcinst.getNumOperands()
if amt < 1:
return []
l = []
for i in range(0, amt):
l.append(Operand(self.mcinst.getOperand(i), self.tm))
return l
@property
def instr_desc(self):
return self.tm.instr_info.get(self.opcode)
@property
def flags(self):
return self.instr_desc.getFlags()
@property
def ts_flags(self):
return self.instr_desc.TSFlags
@property
def opcode(self):
return self.mcinst.getOpcode()
def is_branch(self):
return self.instr_desc.isBranch()
def is_cond_branch(self):
return self.instr_desc.isConditionalBranch()
def is_uncond_branch(self):
return self.instr_desc.isUnconditionalBranch()
def is_indirect_branch(self):
return self.instr_desc.isIndirectBranch()
def is_call(self):
return self.instr_desc.isCall()
def is_return(self):
return self.instr_desc.isReturn()
def is_terminator(self):
return self.instr_desc.isTerminator()
def is_barrier(self):
return self.instr_desc.isBarrier()
class BadInstr(Instr):
pass
class Disassembler(object):
def __init__(self, target_machine):
self.tm = target_machine
@property
def mdasm(self):
return self.tm.disassembler
@property
def mai(self):
return self.tm.asm_info
def instr(self, mcinst):
return Instr(mcinst, self.tm)
def bad_instr(self, mcinst):
return BadInstr(mcinst, self.tm)
def decode(self, bs, base_addr, align=None):
'''
decodes the bytes in @bs into instructions and yields
each instruction as it is decoded. @base_addr is the base address
where the instruction bytes are from (not an offset into
@bs). yields instructions in the form of (addr, data, inst) where
addr is an integer, data is a tuple of integers and inst is an instance of
llvm.mc.Instr. @align specifies the byte alignment of instructions and
is only used if an un-decodable instruction is encountered, in which
case the disassembler will skip the following bytes until the next
aligned address. if @align is unspecified, the default alignment
for the architecture will be used, however this may not be ideal
for disassembly. for example, the default alignment for ARM is 1, but you
probably want it to be 4 for the purposes of disassembling ARM
instructions.
'''
if isinstance(bs, str) and sys.version_info.major >= 3:
bs = bytes(map(lambda c: ord(c), bs))
elif not isinstance(bs, bytes):
raise TypeError("expected bs to be either 'str' or 'bytes' but got %s" % type(bs))
code = api.llvm.StringRefMemoryObject.new(bs, base_addr)
idx = 0
if not isinstance(align, int) or align < 1:
align = self.mai.getMinInstAlignment()
while(idx < code.getExtent()):
inst = api.llvm.MCInst.new()
addr = code.getBase() + idx
status, size = self.mdasm.getInstruction(inst, code, addr)
if size < 1:
size = (align - (idx % align))
amt_left = code.getExtent() - idx
if amt_left >= size:
data = code.readBytes(addr, size)
elif amt_left < 1:
break
else:
data = code.readBytes(addr, amt_left)
if sys.version_info.major < 3:
data = tuple(map(lambda b: ord(b), data))
else:
data = tuple(data)
if status == MCDisassembler.DecodeStatus.Fail:
yield (addr, data, None)
elif status == MCDisassembler.DecodeStatus.SoftFail:
yield (addr, data, self.bad_instr(inst))
else:
yield (addr, data, self.instr(inst))
idx += size

View file

@ -80,6 +80,15 @@ class PassManagerBuilder(llvm.Wrapper):
self._ptr.BBVectorize = enable
vectorize = bbvectorize
@property
def slpvectorize(self):
return self._ptr.SLPVectorize
@slpvectorize.setter
def slpvectorize(self, enable):
self._ptr.SLPVectorize = enable
else:
@property
def vectorize(self):
@ -120,13 +129,14 @@ class PassManagerBuilder(llvm.Wrapper):
def disable_unroll_loops(self, disable):
self._ptr.DisableUnrollLoops = disable
@property
def disable_simplify_lib_calls(self):
return self._ptr.DisableSimplifyLibCalls
if llvm.version <= (3, 3):
@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
@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)
@ -310,13 +320,15 @@ class TargetTransformInfo(Pass):
# Helpers
#===----------------------------------------------------------------------===
def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
inline_threshold=2000, pm=True, fpm=True, mod=None):
def build_pass_managers(tm, opt=2, size=0, loop_vectorize=False,
slp_vectorize=False, vectorize=False,
inline_threshold=None, 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.
size --- [0-2] Optimize for size. Default to 0.
loop_vectorize --- [boolean] Whether to use loop-vectorizer.
vectorize --- [boolean] Whether to use basic-block vectorizer.
inline_threshold --- [int] Threshold for the inliner.
@ -325,6 +337,18 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
fpm --- [boolean] Whether to build a function-level pass-manager.
mod --- [Module] The module object for the FunctionPassManager.
'''
if inline_threshold is None:
if 0 < opt < 3:
inline_threshold = 225
if size == 1:
inline_threshold = 75
elif size == 2:
inline_threshold = 25
if opt >= 3:
inline_threshold = 275
if pm:
pm = PassManager.new()
if fpm:
@ -337,22 +361,27 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
pmb.opt_level = opt
pmb.vectorize = vectorize
pmb.loop_vectorize = loop_vectorize
if llvm.version >= (3, 3):
pmb.slp_vectorize = slp_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):
if llvm.version <= (3, 2):
pm.add(TargetTransformInfo.new(tm))
else:
tm.add_analysis_passes(pm)
pmb.populate(pm)
if fpm:
fpm.add(tm.target_data.clone())
fpm.add(TargetLibraryInfo.new(tm.triple))
if llvm.version >= (3, 2):
if llvm.version <= (3, 2):
fpm.add(TargetTransformInfo.new(tm))
else:
tm.add_analysis_passes(fpm)
pmb.populate(fpm)
fpm.initialize()
from collections import namedtuple
return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm)

266
llvm/target.py Normal file
View file

@ -0,0 +1,266 @@
import llvm
from llvmpy import api, extra
from io import BytesIO
import contextlib
from llvm.passes import TargetData
#===----------------------------------------------------------------------===
# 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
# 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
def initialize_all():
api.llvm.InitializeAllTargets()
api.llvm.InitializeAllTargetInfos()
api.llvm.InitializeAllTargetMCs()
api.llvm.InitializeAllAsmPrinters()
api.llvm.InitializeAllDisassemblers()
api.llvm.InitializeAllAsmParsers()
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', 'AsmParser']
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
'''
api.llvm.TargetRegistry.printRegisteredTargetsForVersion()
def get_host_cpu_name():
'''return the string name of the host CPU
'''
return api.llvm.sys.getHostCPUName()
def get_default_triple():
'''return the target triple of the host in str-rep
'''
return api.llvm.sys.getDefaultTargetTriple()
class TargetMachine(llvm.Wrapper):
@staticmethod
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
if not triple:
triple = get_default_triple()
if not cpu:
cpu = get_host_cpu_name()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(triple, cpu, features,
target_options,
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,
reloc=RELOC_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(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(str(triple), cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
@staticmethod
def x86():
return TargetMachine.lookup('x86')
@staticmethod
def x86_64():
return TargetMachine.lookup('x86-64')
@staticmethod
def arm():
return TargetMachine.lookup('arm')
@staticmethod
def thumb():
return TargetMachine.lookup('thumb')
def _emit_file(self, module, cgft):
pm = api.llvm.PassManager.new()
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)
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
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
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._ptr, 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()
@property
def target(self):
return self._ptr.getTarget()
if llvm.version >= (3, 3):
def add_analysis_passes(self, pm):
self._ptr.addAnalysisPasses(pm._ptr)
if llvm.version >= (3, 4):
@property
def reg_info(self):
mri = self._ptr.getRegisterInfo()
if not mri:
raise llvm.LLVMException("no reg info for this machine")
return mri
@property
def subtarget_info(self):
sti = self._ptr.getSubtargetImpl()
if not sti:
raise llvm.LLVMException("no subtarget info for this machine")
return sti
@property
def asm_info(self):
ai = self._ptr.getMCAsmInfo()
if not ai:
raise llvm.LLVMException("no asm info for this machine")
return ai
@property
def instr_info(self):
ii = self._ptr.getInstrInfo()
if not ii:
raise llvm.LLVMException("no instr info for this machine")
return ii
@property
def instr_analysis(self):
if not getattr(self, '_mia', False):
self._mia = self.target.createMCInstrAnalysis(self.instr_info)
if not self._mia:
raise llvm.LLVMException("no instr analysis for this machine")
return self._mia
@property
def disassembler(self):
if not getattr(self, '_dasm', False):
self._dasm = self.target.createMCDisassembler(self.subtarget_info)
if not self._dasm:
raise llvm.LLVMException("no disassembler for this machine")
return self._dasm
@property
def inst_printer(self):
if not getattr(self, '_mip', False):
self._mip = self.target.createMCInstPrinter(
self.asm_info.getAssemblerDialect(),
self.asm_info,
self.instr_info,
self.reg_info,
self.subtarget_info
)
if not self._mip:
raise llvm.LLVMException("no instr printer for this machine")
return self._mip
def is_little_endian(self):
return self.asm_info.isLittleEndian()

File diff suppressed because it is too large Load diff

72
llvm/tests/__init__.py Normal file
View file

@ -0,0 +1,72 @@
from __future__ import print_function
import sys
import os
import unittest
import subprocess
import llvm
tests = [] # stores unittest.TestCase objects
# Isolated tests
# Tests that affect process-wide settings
isolated_tests = [] # stores modue name
def run(verbosity=1, run_isolated=True):
print('llvmpy is installed in: ' + os.path.dirname(__file__))
print('llvmpy version: ' + llvm.__version__)
print(sys.version)
files = filter(lambda s: s.startswith('test_') and s.endswith('.py'),
os.listdir(os.path.dirname(__file__)))
for f in files:
fname = f.split('.', 1)[0]
__import__('.'.join([__name__, fname]))
suite = unittest.TestSuite()
for cls in tests:
if cls:
suite.addTest(unittest.makeSuite(cls))
# The default stream fails in IPython qtconsole on Windows,
# so just using sys.stdout
kwargs = dict(verbosity=verbosity, stream=sys.stdout)
if sys.version_info[:2] > (2, 6):
kwargs['buffer'] = True
runner = unittest.TextTestRunner(**kwargs)
try:
from guppy import hpy
except ImportError:
testresult = runner.run(suite)
else:
hp = hpy()
hp.setref()
testresult = runner.run(suite)
print(hp.heap())
if testresult and run_isolated:
# Run isolated tests
print("run isolated tests".center(80, '-'))
for test in isolated_tests:
print(('testing %s' % test).center(80))
cmd = [sys.executable, '-m', test]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in p.stdout:
print(line.decode('utf8'), end='')
p.wait()
if p.returncode:
raise Exception("%s returned: %d" % (test, p.returncode))
return testresult
if __name__ == '__main__':
unittest.main()

78
llvm/tests/support.py Normal file
View file

@ -0,0 +1,78 @@
from __future__ import print_function, division
import sys
import platform
import unittest
import contextlib
import types
from llvm.tests import tests, isolated_tests # re-expose symbol
IS_PY3K = sys.version_info[0] >= 3
BITS = tuple.__itemsize__ * 8
OS = sys.platform
MACHINE = platform.machine()
INTEL_CPUS = 'i386', 'x86_64'
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 TestCase(_TestCase):
def assertClose(self, got, expect):
rel = abs(got - expect) / expect
self.assertTrue(rel < 1e-6, 'relative error = %f' % rel)
#-------------------------------------------------------------------------------
# Tests decorators
def _skipped(name, msg):
def _test(self):
if hasattr(unittest, 'SkipTest'):
raise unittest.SkipTest(msg)
else:
print('skipped %s' % name, msg)
return _test
def skip_if(cond, msg=''):
def skipper(test):
if not isinstance(test, types.FunctionType):
repl = None
else:
repl = _skipped(test, msg)
return repl if cond else test
return skipper
skip_if_not_64bits = skip_if(BITS != 64, msg='skipped not 64-bit')
skip_if_not_32bits = skip_if(BITS != 32, msg='skipped not 32-bits')
skip_if_win32 = skip_if(OS.startswith('win32'), msg='skipped win32')
skip_if_not_win32 = skip_if(not OS.startswith('win32'),
msg='skipped not win32')
skip_if_not_intel_cpu = skip_if(MACHINE not in INTEL_CPUS,
msg='skipped not Intel CPU')

24
llvm/tests/test_alloca.py Normal file
View file

@ -0,0 +1,24 @@
import unittest
from llvm.core import Type, Module, Builder, Constant
from .support import TestCase, tests
class TestAlloca(TestCase):
def test_alloca_alignment(self):
m = Module.new('')
f = m.add_function(Type.function(Type.void(), []), "foo")
b = Builder.new(f.append_basic_block(''))
inst = b.alloca(Type.int(32))
inst.alignment = 4
b.ret_void()
m.verify()
self.assertTrue(inst.is_static)
self.assertFalse(inst.is_array)
self.assertEqual(inst.alignment, 4)
self.assertEqual(str(inst.array_size), 'i32 1')
tests.append(TestAlloca)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,24 @@
import unittest
from llvm.core import Module, Type
import llvm.core as lc
from .support import TestCase, tests
class TestArgAttr(TestCase):
def test_arg_attr(self):
m = Module.new('oifjda')
vptr = Type.pointer(Type.float())
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)
if __name__ == '__main__':
unittest.main()

73
llvm/tests/test_arith.py Normal file
View file

@ -0,0 +1,73 @@
import unittest
import llvm
from llvm.core import (Module, Type, Builder)
from llvm.ee import EngineBuilder
from .support import TestCase, tests, skip_if, skip_if_not_64bits
@skip_if(llvm.version < (3, 3))
class TestArith(TestCase):
'''
Test basic arithmetic support with LLVM MCJIT
'''
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()]
if iop:
for ty in inttys:
self.func_template(ty, iop)
if fop:
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')
@skip_if_not_64bits
def test_div(self):
'''
known failure due to unresolved external symbol __udivdi3
'''
self.template('udiv', None) # 'fdiv')
@skip_if_not_64bits
def test_rem(self):
'''
known failure due to unresolved external symbol __umoddi3
'''
self.template('urem', None) # 'frem')
tests.append(TestArith)
if __name__ == '__main__':
unittest.main()

58
llvm/tests/test_asm.py Normal file
View file

@ -0,0 +1,58 @@
import os
import unittest
import tempfile
import shutil
from llvm.core import Module, Type
from .support import TestCase, tests
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 '<string>'.
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 '<string>'.
m2.id = m.id # Copy the name from `m`
self.assertEqual(str(m2).strip(), asm.strip())
tests.append(TestAsm)
if __name__ == '__main__':
unittest.main()

85
llvm/tests/test_atomic.py Normal file
View file

@ -0,0 +1,85 @@
import unittest
from llvm.core import (Module, Type, Builder, Constant)
from .support import TestCase, tests
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())
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())
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)
if __name__ == '__main__':
unittest.main()

33
llvm/tests/test_attr.py Normal file
View file

@ -0,0 +1,33 @@
import unittest
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from llvm.core import Module
from .support import TestCase, tests
class TestAttr(TestCase):
def make_module(self):
test_module = """
define void @sum(i32*, i32*) {
entry:
ret void
}
"""
buf = StringIO(test_module)
return Module.from_assembly(buf)
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)
if __name__ == '__main__':
unittest.main()

26
llvm/tests/test_cmp.py Normal file
View file

@ -0,0 +1,26 @@
import unittest
from llvm.core import (Module, Type, Builder, Constant)
import llvm.core as lc
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,23 @@
import unittest
from llvm.core import (Module, Type, Builder, Constant)
import llvm.core as lc
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,89 @@
import unittest
import math
from llvm.core import (Module, Type, Function, Builder,
Constant)
from llvm.ee import EngineBuilder
import llvm.core as lc
import llvm.ee as le
from llvm.workaround.avx_support import detect_avx_support
from .support import TestCase, tests, skip_if_not_intel_cpu, skip_if
@skip_if_not_intel_cpu
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)
@skip_if(not detect_avx_support(), msg="no AVX support")
def test_cpu_support6(self):
features = []
mattrs = ','.join(map(lambda s: '-%s' % s, features))
print('disable mattrs', mattrs)
self._template(mattrs)
tests.append(TestCPUSupport)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,65 @@
import unittest
from llvm.core import Module, Type, Builder, Constant
from llvm.ee import EngineBuilder
import llvm.ee as le
import llvmpy
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

37
llvm/tests/test_exact.py Normal file
View file

@ -0,0 +1,37 @@
import unittest
from llvm.core import (Module, Type, Builder)
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,47 @@
import unittest
from llvm.core import Type
import llvm.core as lc
import llvm.ee as le
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,34 @@
import unittest
from llvm.core import (Module, Type, Builder, Constant, inline_function)
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,31 @@
import sys
import os
import unittest
from llvm.core import Builder, Module, Type
import llvm.core as lc
from .support import TestCase, skip_if_not_intel_cpu, isolated_tests
@skip_if_not_intel_cpu
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)
isolated_tests.append(__name__)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,113 @@
import unittest
import sys
import math
from llvm.core import (Module, Type, Function, Builder, Constant)
import llvm.core as lc
import llvm.ee as le
from .support import TestCase, tests, BITS
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 ) ; <i32>:0 [#uses
# }
#
# declare i32 @llvm.bswap.i32(i32) nounwind readnone
#
# define float @mysin(float %x) {
# entry:
# %cosx = call float @llvm.cos.f32( float %x ) ; <float
# %cos2 = call float @llvm.powi.f32( float %cosx, i32 2 )
# %onemc2 = sub float 1.000000e+00, %cos2 ; <float> [#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
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])
golden = math.sin(1.234)
answer = retval.as_real(Type.float())
self.assertTrue(abs(answer-golden)/golden < 1e-5)
tests.append(TestIntrinsic)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,99 @@
import unittest
import sys
import math
from llvm.core import (Module, Type, Function, Builder)
import llvm.core as lc
import llvm.ee as le
from .support import TestCase, BITS, tests
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
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)
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,26 @@
import unittest
from llvm.core import (Module, Type, Builder)
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

34
llvm/tests/test_llrt.py Normal file
View file

@ -0,0 +1,34 @@
import unittest
import llvm.core as lc
import llvm.ee as le
from .support import TestCase, tests
class TestLLRT(TestCase):
def test_llrt_divmod(self):
from llvm import llrt
m = lc.Module.new('testllrt')
longlong = lc.Type.int(64)
lfunc = m.add_function(lc.Type.function(longlong, [longlong, longlong]), 'foo')
bldr = lc.Builder.new(lfunc.append_basic_block(''))
bldr.ret(bldr.udiv(*lfunc.args))
llrt.replace_divmod64(lfunc)
rt = llrt.LLRT()
rt.install_symbols()
engine = le.EngineBuilder.new(m).create()
pointer = engine.get_pointer_to_function(lfunc)
from ctypes import CFUNCTYPE, c_uint64
func = CFUNCTYPE(c_uint64, c_uint64, c_uint64)(pointer)
a, b = 98342, 2231
self.assertEqual(func(98342, 2231), 98342 // 2231)
rt.uninstall_symbols()
tests.append(TestLLRT)
if __name__ == '__main__':
unittest.main()

73
llvm/tests/test_mcjit.py Normal file
View file

@ -0,0 +1,73 @@
import unittest
import sys
import llvm
from llvm.core import (Module, Type, Builder)
from llvm.ee import EngineBuilder
import llvm.ee as le
from .support import TestCase, tests, BITS
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))
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) and
not (sys.platform.startswith('win32') and BITS == 64)):
# MCJIT broken in 3.2, the test will segfault in OSX?
# Compatbility problem on windows 7 64-bit?
tests.append(TestMCJIT)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,25 @@
import unittest
from llvm.core import (Module, Type, Constant, MetaData, MetaDataString)
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,20 @@
import unittest
from llvm.core import (Module, Type, Constant, MetaData)
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

81
llvm/tests/test_native.py Normal file
View file

@ -0,0 +1,81 @@
import unittest
import os
import sys
import shutil
import subprocess
import tempfile
from distutils.spawn import find_executable
from llvm.core import (Module, Type, Builder, Constant)
from .support import TestCase, IS_PY3K, tests, skip_if
@skip_if(sys.platform in ('win32', 'darwin'))
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):
cc = find_executable('cc')
if not cc:
return
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:
if IS_PY3K:
fout.write(output.encode('utf-8'))
else:
fout.write(output)
self._compile(src)
def test_object(self):
'''
Note: Older Darwin with GCC will report missing _main symbol when
compile the object file to an executable.
'''
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)
tests.append(TestNative)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,48 @@
import unittest
from llvm.core import Module, Type, Builder
from .support import TestCase, tests
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')
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,107 @@
import unittest
from llvm.core import Module, Type, GlobalVariable, Function, Builder
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

38
llvm/tests/test_opaque.py Normal file
View file

@ -0,0 +1,38 @@
import unittest
import llvm
from llvm.core import Type
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,66 @@
import unittest
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from llvm.core import Module
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

143
llvm/tests/test_passes.py Normal file
View file

@ -0,0 +1,143 @@
import unittest
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import llvm
from llvm.core import Module
import llvm.passes as lp
import llvm.ee as le
from .support import TestCase, tests
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)
if llvm.version <= (3, 3):
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)
if __name__ == '__main__':
unittest.main()

28
llvm/tests/test_struct.py Normal file
View file

@ -0,0 +1,28 @@
import unittest
from llvm.core import Type, Module, Builder, Constant
from .support import TestCase, tests
class TestStruct(TestCase):
def test_struct_identical(self):
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))
def test_struct_extract_value_2d(self):
ta = Type.struct([Type.int(32), Type.float()])
tb = Type.struct([ta, Type.float()])
m = Module.new('')
f = m.add_function(Type.function(Type.void(), []), "foo")
b = Builder.new(f.append_basic_block(''))
v = Constant.undef(tb)
ins = b.insert_value(v, Constant.real(Type.float(), 1.234), [0, 1])
ext = b.extract_value(ins, [0, 1])
b.ret_void()
m.verify()
self.assertEqual(str(ext), 'float 0x3FF3BE76C0000000')
tests.append(TestStruct)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,685 @@
from __future__ import print_function
from . import tests
import sys
import unittest
from ctypes import Structure, c_float, c_double, c_uint8, CFUNCTYPE
from llvm import core as lc
from llvm import ee as le
from .support import (skip_if_win32, skip_if_not_win32, skip_if_not_32bits,
skip_if_not_64bits, skip_if_not_intel_cpu, TestCase)
class TwoDoubleOneByte(Structure):
_fields_ = ('x', c_double), ('y', c_double), ('z', c_uint8)
def __repr__(self):
return '<x=%f y=%f z=%d>' % (self.x, self.y, self.z)
class TwoDouble(Structure):
_fields_ = ('x', c_double), ('y', c_double)
def __repr__(self):
return '<x=%f y=%f>' % (self.x, self.y)
class TwoFloat(Structure):
_fields_ = ('x', c_float), ('y', c_float)
def __repr__(self):
return '<x=%f y=%f>' % (self.x, self.y)
class OneByte(Structure):
_fields_ = [('x', c_uint8)]
def __repr__(self):
return '<x=%d>' % (self.x,)
@skip_if_not_intel_cpu
@skip_if_win32
class TestStructSystemVABI(TestCase):
'''
Non microsoft convention
'''
#----------------------------------------------------------------------
# 64 bits
@skip_if_not_64bits
def test_bigger_than_two_words_64(self):
m = lc.Module.new('test_struct_arg')
double_type = lc.Type.double()
uint8_type = lc.Type.int(8)
struct_type = lc.Type.struct([double_type, double_type, uint8_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1, e2, e3 = [builder.extract_value(arg, i) for i in range(3)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
ret = builder.insert_value(ret, e3, 2)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoDoubleOneByte, TwoDoubleOneByte)
cfunc = cfunctype(ptr)
arg = TwoDoubleOneByte(x=1.321321, y=6.54352, z=128)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
self.assertEqual(arg.z, ret.z)
@skip_if_not_64bits
def test_just_two_words_64(self):
m = lc.Module.new('test_struct_arg')
double_type = lc.Type.double()
struct_type = lc.Type.struct([double_type, double_type])
func_type = lc.Type.function(struct_type, [struct_type])
func = m.add_function(func_type, name='foo')
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = func.args[0]
e1, e2 = [builder.extract_value(arg, i) for i in range(2)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
builder.ret(ret)
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoDouble, TwoDouble)
cfunc = cfunctype(ptr)
arg = TwoDouble(x=1.321321, y=6.54352)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
@skip_if_not_64bits
def test_two_halfwords(self):
'''Arguments smaller or equal to a word is packed into a word.
Passing as struct { float, float } occupies two XMM registers instead
of one.
The output must be in XMM.
'''
m = lc.Module.new('test_struct_arg')
float_type = lc.Type.float()
struct_type = lc.Type.vector(float_type, 2)
func_type = lc.Type.function(struct_type, [struct_type])
func = m.add_function(func_type, name='foo')
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = func.args[0]
constint = lambda x: lc.Constant.int(lc.Type.int(), x)
e1, e2 = [builder.extract_element(arg, constint(i))
for i in range(2)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_element(lc.Constant.undef(struct_type), se1,
constint(0))
ret = builder.insert_element(ret, se2, constint(1))
builder.ret(ret)
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoFloat, TwoFloat)
cfunc = cfunctype(ptr)
arg = TwoFloat(x=1.321321, y=6.54352)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
#----------------------------------------------------------------------
# 32 bits
@skip_if_not_32bits
def test_structure_abi_32_1(self):
'''x86 is simple. Always pass structure as memory.
'''
m = lc.Module.new('test_struct_arg')
double_type = lc.Type.double()
uint8_type = lc.Type.int(8)
struct_type = lc.Type.struct([double_type, double_type, uint8_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1, e2, e3 = [builder.extract_value(arg, i) for i in range(3)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
ret = builder.insert_value(ret, e3, 2)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoDoubleOneByte, TwoDoubleOneByte)
cfunc = cfunctype(ptr)
arg = TwoDoubleOneByte(x=1.321321, y=6.54352, z=128)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
self.assertEqual(arg.z, ret.z)
@skip_if_not_32bits
def test_structure_abi_32_2(self):
'''x86 is simple. Always pass structure as memory.
'''
m = lc.Module.new('test_struct_arg')
float_type = lc.Type.float()
struct_type = lc.Type.struct([float_type, float_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1, e2 = [builder.extract_value(arg, i) for i in range(2)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoFloat, TwoFloat)
cfunc = cfunctype(ptr)
arg = TwoFloat(x=1.321321, y=6.54352)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
@skip_if_not_32bits
def test_structure_abi_32_3(self):
'''x86 is simple. Always pass structure as memory.
'''
m = lc.Module.new('test_struct_arg')
uint8_type = lc.Type.int(8)
struct_type = lc.Type.struct([uint8_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1 = builder.extract_value(arg, 0)
se1 = builder.mul(e1, e1)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(OneByte, OneByte)
cfunc = cfunctype(ptr)
arg = OneByte(x=8)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertEqual(arg.x * arg.x, ret.x)
tests.append(TestStructSystemVABI)
@skip_if_not_intel_cpu
@skip_if_not_win32
class TestStructMicrosoftABI(TestCase):
'''
Microsoft convention
'''
#----------------------------------------------------------------------
# 64 bits
@skip_if_not_64bits
def test_bigger_than_two_words_64(self):
m = lc.Module.new('test_struct_arg')
double_type = lc.Type.double()
uint8_type = lc.Type.int(8)
struct_type = lc.Type.struct([double_type, double_type, uint8_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1, e2, e3 = [builder.extract_value(arg, i) for i in range(3)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
ret = builder.insert_value(ret, e3, 2)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoDoubleOneByte, TwoDoubleOneByte)
cfunc = cfunctype(ptr)
arg = TwoDoubleOneByte(x=1.321321, y=6.54352, z=128)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
self.assertEqual(arg.z, ret.z)
@skip_if_not_64bits
def test_just_two_words_64(self):
m = lc.Module.new('test_struct_arg')
double_type = lc.Type.double()
struct_type = lc.Type.struct([double_type, double_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1, e2 = [builder.extract_value(arg, i) for i in range(2)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoDouble, TwoDouble)
cfunc = cfunctype(ptr)
arg = TwoDouble(x=1.321321, y=6.54352)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
@skip_if_not_64bits
def test_two_halfwords(self):
'''Arguments smaller or equal to a word is packed into a word.
Floats structure are not passed on the XMM.
Treat it as a i64.
'''
m = lc.Module.new('test_struct_arg')
float_type = lc.Type.float()
struct_type = lc.Type.struct([float_type, float_type])
abi_type = lc.Type.int(64)
func_type = lc.Type.function(abi_type, [abi_type])
func = m.add_function(func_type, name='foo')
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = func.args[0]
struct_ptr = builder.alloca(struct_type)
struct_int_ptr = builder.bitcast(struct_ptr, lc.Type.pointer(abi_type))
builder.store(arg, struct_int_ptr)
arg = builder.load(struct_ptr)
e1, e2 = [builder.extract_value(arg, i) for i in range(2)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
builder.store(ret, struct_ptr)
ret = builder.load(struct_int_ptr)
builder.ret(ret)
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoFloat, TwoFloat)
cfunc = cfunctype(ptr)
arg = TwoFloat(x=1.321321, y=6.54352)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
#----------------------------------------------------------------------
# 32 bits
@skip_if_not_32bits
def test_one_word_register(self):
'''Argument is passed by memory.
Return value is passed by register.
'''
m = lc.Module.new('test_struct_arg')
uint8_type = lc.Type.int(8)
struct_type = lc.Type.struct([uint8_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(struct_type, [struct_ptr_type])
func = m.add_function(func_type, name='foo')
# pass structure by value
func.args[0].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[0])
e1 = builder.extract_value(arg, 0)
se1 = builder.mul(e1, e1)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
builder.ret(ret)
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(OneByte, OneByte)
cfunc = cfunctype(ptr)
arg = OneByte(x=8)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertEqual(arg.x * arg.x, ret.x)
@skip_if_not_32bits
def test_two_floats(self):
'''Argument is passed by register.
Return in 2 registers
'''
m = lc.Module.new('test_struct_arg')
float_type = lc.Type.float()
struct_type = lc.Type.struct([float_type, float_type])
abi_type = lc.Type.int(64)
func_type = lc.Type.function(abi_type, [struct_type])
func = m.add_function(func_type, name='foo')
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
out_ptr = builder.alloca(struct_type)
arg = func.args[0]
e1, e2 = [builder.extract_value(arg, i) for i in range(2)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
builder.store(ret, out_ptr)
out_int_ptr = builder.bitcast(out_ptr, lc.Type.pointer(abi_type))
builder.ret(builder.load(out_int_ptr))
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoFloat, TwoFloat)
cfunc = cfunctype(ptr)
arg = TwoFloat(x=1.321321, y=6.54352)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
@skip_if_not_32bits
def test_bigger_than_two_words(self):
'''Pass in memory.
'''
m = lc.Module.new('test_struct_arg')
double_type = lc.Type.double()
uint8_type = lc.Type.int(8)
struct_type = lc.Type.struct([double_type, double_type, uint8_type])
struct_ptr_type = lc.Type.pointer(struct_type)
func_type = lc.Type.function(lc.Type.void(),
[struct_ptr_type, struct_ptr_type])
func = m.add_function(func_type, name='foo')
# return value pointer
func.args[0].add_attribute(lc.ATTR_STRUCT_RET)
# pass structure by value
func.args[1].add_attribute(lc.ATTR_BY_VAL)
# define function body
builder = lc.Builder.new(func.append_basic_block(''))
arg = builder.load(func.args[1])
e1, e2, e3 = [builder.extract_value(arg, i) for i in range(3)]
se1 = builder.fmul(e1, e2)
se2 = builder.fdiv(e1, e2)
ret = builder.insert_value(lc.Constant.undef(struct_type), se1, 0)
ret = builder.insert_value(ret, se2, 1)
ret = builder.insert_value(ret, e3, 2)
builder.store(ret, func.args[0])
builder.ret_void()
del builder
# verify
m.verify()
print(m)
# use with ctypes
engine = le.EngineBuilder.new(m).create()
ptr = engine.get_pointer_to_function(func)
cfunctype = CFUNCTYPE(TwoDoubleOneByte, TwoDoubleOneByte)
cfunc = cfunctype(ptr)
arg = TwoDoubleOneByte(x=1.321321, y=6.54352, z=128)
ret = cfunc(arg)
print(arg)
print(ret)
self.assertClose(arg.x * arg.y, ret.x)
self.assertClose(arg.x / arg.y, ret.y)
self.assertEqual(arg.z, ret.z)
tests.append(TestStructMicrosoftABI)
if __name__ == "__main__":
unittest.main()

36
llvm/tests/test_switch.py Normal file
View file

@ -0,0 +1,36 @@
import unittest
from llvm.core import (Module, Type, Builder, Constant)
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,62 @@
import unittest
import llvm.core as lc
import llvm.ee as le
from llvm.core import Type, Builder
from .support import TestCase, tests, skip_if
# Check PTX backend
if le.initialize_target('PTX', noraise=True):
PTX_ARCH = 'ptx64'
elif le.initialize_target('NVPTX', noraise=True):
PTX_ARCH = 'nvptx64'
else:
PTX_ARCH = None
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))
self.assertTrue(le.get_host_cpu_name())
@skip_if(not PTX_ARCH, msg='LLVM is not compiled with PTX enabled')
def test_ptx(self):
arch = PTX_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)
self.assertIn('foo', ptxasm)
if arch == 'nvptx64':
self.assertIn('.address_size 64', ptxasm)
self.assertIn('sm_20', ptxasm)
def _build_module(self):
m = lc.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
tests.append(TestTargetMachines)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,30 @@
import unittest
from llvm.core import Type
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

43
llvm/tests/test_uses.py Normal file
View file

@ -0,0 +1,43 @@
import unittest
from llvm.core import Module, Type, Builder, Constant
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,59 @@
import unittest
from llvm.core import Module, Type, Builder
from .support import TestCase, tests
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)
if __name__ == '__main__':
unittest.main()

0
llvm/utils/__init__.py Normal file
View file

View file

@ -0,0 +1,181 @@
from __future__ import print_function, absolute_import
import sys
from llvm.core import Type, Function, Builder, Module
import llvm.core as lc
import llvm.ee as le
import multiprocessing
from ctypes import *
INTRINSICS = {}
CTYPES_MAP = {
Type.int(): c_int32,
Type.int(64): c_int64,
Type.float(): c_float,
Type.double(): c_double,
}
def register(name, retty, *args):
def wrap(fn):
INTRINSICS[name] = (retty, args), fn
return fn
return wrap
def intr_impl(intrcode, *types):
def impl(module, builder, args):
intr = Function.intrinsic(module, intrcode, types)
r = builder.call(intr, args)
return r
return impl
register("llvm.powi.f64", Type.double(), Type.double(), Type.int())\
(intr_impl(lc.INTR_POWI, Type.double()))
register("llvm.powi.f32", Type.float(), Type.float(), Type.int())\
(intr_impl(lc.INTR_POWI, Type.float()))
register("llvm.pow.f64", Type.double(), Type.double(), Type.double())\
(intr_impl(lc.INTR_POW, Type.double()))
register("llvm.pow.f32", Type.float(), Type.float(), Type.float())\
(intr_impl(lc.INTR_POW, Type.float()))
register("llvm.sin.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_SIN, Type.double()))
register("llvm.sin.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_SIN, Type.float()))
register("llvm.cos.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_COS, Type.double()))
register("llvm.cos.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_COS, Type.float()))
register("llvm.log.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_LOG, Type.double()))
register("llvm.log.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_LOG, Type.float()))
register("llvm.log2.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_LOG2, Type.double()))
register("llvm.log2.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_LOG2, Type.float()))
register("llvm.log10.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_LOG10, Type.double()))
register("llvm.log10.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_LOG10, Type.float()))
register("llvm.sqrt.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_SQRT, Type.double()))
register("llvm.sqrt.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_SQRT, Type.float()))
register("llvm.exp.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_EXP, Type.double()))
register("llvm.exp.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_EXP, Type.float()))
register("llvm.exp2.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_EXP2, Type.double()))
register("llvm.exp2.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_EXP2, Type.float()))
register("llvm.fabs.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_FABS, Type.double()))
register("llvm.fabs.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_FABS, Type.float()))
register("llvm.floor.f64", Type.double(), Type.double())\
(intr_impl(lc.INTR_FLOOR, Type.double()))
register("llvm.floor.f32", Type.float(), Type.float())\
(intr_impl(lc.INTR_FLOOR, Type.float()))
def build_test(name):
(retty, args), impl = INTRINSICS[name]
module = Module.new("test.%s" % name)
fn = module.add_function(Type.function(retty, args), name="test_%s" % name)
builder = Builder.new(fn.append_basic_block(""))
retval = impl(module, builder, fn.args)
builder.ret(retval)
fn.verify()
module.verify()
return module, fn
def run_test(name):
module, fn = build_test(name)
eb = le.EngineBuilder.new(module).mcjit(True)
engine = eb.create()
ptr = engine.get_pointer_to_function(fn)
argtys = fn.type.pointee.args
retty = fn.type.pointee.return_type
cargtys = [CTYPES_MAP[a] for a in argtys]
cretty = CTYPES_MAP[retty]
cfunc = CFUNCTYPE(cretty, *cargtys)(ptr)
args = [1] * len(cargtys)
cfunc(*args)
def spawner(name):
print("Testing %s" % name)
proc = multiprocessing.Process(target=run_test, args=(name,))
print('-' * 80)
proc.start()
proc.join()
if proc.exitcode != 0:
print("FAILED")
ok = False
else:
print("PASSED")
ok = True
print('=' * 80)
print()
return ok
USAGE = """
Args: [name]
name: intrinsic name to test
If no name is given, test all intrinsics.
"""
def main(argv=()):
if len(argv) == 1:
intrname = argv[1]
spawner(intrname)
elif not argv:
failed = []
for name in sorted(INTRINSICS):
if not spawner(name):
failed.append(name)
print("Summary:")
for name in failed:
print("%s failed" % name)
else:
print(USAGE)
if __name__ == '__main__':
main(argv=sys.argv[1:])

View file

@ -12,7 +12,11 @@ http://software.intel.com/sites/default/files/m/a/b/3/4/d/41604-319433-012a.pdf
"""
import sys, os, subprocess
import sys
import os
import subprocess
import contextlib
def detect_avx_support(option='detect'):
'''Detect AVX support'''
@ -36,13 +40,25 @@ def detect_unix_like():
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
with contextlib.closing(info):
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
@contextlib.contextmanager
def _close_popen(popen):
if sys.version_info[0] >= 3:
with popen:
yield
else:
yield
popen.stdout.close()
def detect_osx_like():
try:
@ -50,9 +66,11 @@ def detect_osx_like():
stdout=subprocess.PIPE)
except OSError:
return False
features = info.stdout.read().decode('UTF8')
features = features.split()
return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features
with _close_popen(info):
features = info.stdout.read().decode('UTF8')
features = features.split()
return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features
if __name__ == '__main__':

View file

@ -1,18 +1,18 @@
# This should be moved to llvmpy
#
#
# There are different array kinds parameterized by eltype and nd
#
# Contiguous or Fortran
#
# Contiguous or Fortran
# struct {
# eltype *data;
# intp shape[nd];
# intp shape[nd];
# } contiguous_array(eltype, nd)
#
# struct {
# eltype *data;
# diminfo shape[nd];
# } strided_array(eltype, nd)
#
#
# struct {
# eltype *data;
# intp shape[nd];
@ -40,7 +40,7 @@
# int32 nd;
# diminfo shape[nd];
# } strided_array_nd(eltype)
#
#
#
# Backward compatible but deprecated:
# struct {
@ -50,25 +50,25 @@
# 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
# intp strides[ind]; dimkind = STRIDED_SOA
#
import llvm.core as lc
@ -95,7 +95,7 @@ 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_ND, F_CONTIGUOUS_ND, STRIDED_ND, STRIDED_SOA_DK,
C_CONTIGUOUS_DK, F_CONTIGUOUS_DK, STRIDED_DK, STRIDED_SOA_DK)
_invmap = {}
@ -105,7 +105,7 @@ def kind_to_str(kind):
if not _invmap:
for key, value in globals().items():
if isinstance(value, int) and value in array_kinds:
_invmap[value] = key
_invmap[value] = key
return _invmap[kind]
def str_to_kind(str):
@ -157,7 +157,7 @@ def array_type(nd, kind, el_type=char_type):
terms.append(Type.array(intp_type, nd)) # shape
elif base == STRIDED:
terms.append(Type.array(diminfo_type, nd)) # diminfo
elif base == STRIDED_SOA:
elif base == STRIDED_SOA:
terms.extend([Type.array(intp_type, nd), # shape
Type.array(intp_type, nd)]) # strides
@ -184,8 +184,8 @@ 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)):
not (isinstance(a1, lc.ArrayType) or
(a1 == int32_type) or (a1 == int16_type)):
return None
data_type = a0.pointee
@ -214,7 +214,7 @@ def _raw_check_array(arrtyp):
c_contiguous = C_CONTIGUOUS_DK
f_contiguous = F_CONTIGUOUS_DK
else:
num = 1
num = 1
strided = STRIDED
strided_soa = STRIDED_SOA
c_contiguous = C_CONTIGUOUS
@ -254,4 +254,4 @@ def test():
assert check_array(arr) == (STRIDED_SOA, 3, char_type)
if __name__ == '__main__':
test()
test()

View file

@ -349,7 +349,7 @@ class CBuilder(object):
elif not isinstance(count, lc.Value):
count = self.constant(types.int, count).value
ptr = self.builder.alloca_array(ty, count, name=name)
ptr = self.builder.alloca(ty, size=count, name=name)
return CArray(self, ptr)
def ret(self, val=None):

View file

@ -1,55 +1,95 @@
#include <Python.h>
#include <structmember.h>
#include <python3adapt.h>
#include <capsulethunk.h>
#include <llvm_binding/capsule_context.h>
#include <llvm_binding/auto_pyobject.h>
#include <string>
#include <sstream>
static PyObject* TheAPIModule = NULL;
static PyObject* TheCapsuleModule = NULL;
static PyObject* TheCapsuleClass = NULL;
static PyObject* TheWrapperClass = NULL;
static PyObject* TheCache = NULL;
static PyObject* TheAddrDtorDict = NULL;
static PyObject* TheClassesDict = NULL;
static PyObject* TheAddrRefCt = NULL;
static PyObject* ConstantOne = NULL;
static PyObject* TheDowncastModule = NULL;
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);
PyObject* GetAPIModule(){
if (NULL == TheAPIModule)
TheAPIModule = PyImport_ImportModule("llvmpy._api");
return TheAPIModule;
}
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);
PyObject* GetCapsuleModule(){
if (NULL == TheCapsuleModule)
TheCapsuleModule = PyImport_ImportModule("llvmpy.capsule");
return TheCapsuleModule;
}
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;
}
PyObject* GetCapsuleClass() {
if (NULL == TheCapsuleClass)
TheCapsuleClass = PyObject_GetAttrString(GetCapsuleModule(),
"Capsule");
return TheCapsuleClass;
}
// ------------------
// PyCapsule Context
// ------------------
static
PyObject* GetWrapperClass() {
if (NULL == TheWrapperClass)
TheWrapperClass = PyObject_GetAttrString(GetCapsuleModule(),
"Wrapper");
return TheWrapperClass;
}
static
CapsuleContext* getContext(PyObject* self, PyObject* args) {
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
}
PyObject* GetCache() {
if (NULL == TheCache)
TheCache = PyObject_GetAttrString(GetCapsuleModule(), "_cache");
return TheCache;
}
static
PyObject* GetAddrDtorDict() {
if (NULL == TheAddrDtorDict)
TheAddrDtorDict = PyObject_GetAttrString(GetCapsuleModule(),
"_addr2dtor");
return TheAddrDtorDict;
}
static
PyObject* GetClassesDict() {
if (NULL == TheClassesDict)
TheClassesDict = PyObject_GetAttrString(GetCapsuleModule(),
"_pyclasses");
return TheClassesDict;
}
static
PyObject* GetAddrRefCt() {
if (NULL == TheAddrRefCt)
TheAddrRefCt = PyObject_GetAttrString(GetCapsuleModule(),
"_addr2refct");
return TheAddrRefCt;
}
static
PyObject* GetDowncastModule() {
if (NULL == TheDowncastModule)
TheDowncastModule = PyObject_GetAttrString(GetAPIModule(),
"downcast");
return TheDowncastModule;
}
static
CapsuleContext* GetContext(PyObject *obj) {
void* context = PyCapsule_GetContext(obj);
if (!context) {
PyErr_SetString(PyExc_TypeError, "PyCapsule has no context.");
@ -59,9 +99,8 @@ CapsuleContext* getContext(PyObject* self, PyObject* args) {
}
static
PyObject* getClassName(PyObject* self, PyObject* args) {
CapsuleContext* context = getContext(self, args);
//Assert(context->_magic == 0xdead);
PyObject* GetClassName(PyObject* obj) {
CapsuleContext* context = GetContext(obj);
if (!context) {
return NULL;
} else {
@ -69,6 +108,476 @@ PyObject* getClassName(PyObject* self, PyObject* args) {
}
}
static
PyObject* getClassName(PyObject* self, PyObject* args) {
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
}
return GetClassName(obj);
}
static
PyObject* GetName(PyObject* obj) {
const char* name = PyCapsule_GetName(obj);
if (!name) return NULL;
return PyString_FromString(name);
}
static
PyObject* getName(PyObject* self, PyObject* args) {
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj)){
return NULL;
}
return GetName(obj);
}
static
PyObject* GetPointer(PyObject* obj){
void *pointer = PyCapsule_GetPointer(obj, PyCapsule_GetName(obj));
if (!pointer) return NULL;
return PyLong_FromVoidPtr(pointer);
}
static
PyObject* getPointer(PyObject* self, PyObject* args) {
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj)){
return NULL;
}
return GetPointer(obj);
}
static
bool Check(PyObject* obj){
return PyCapsule_CheckExact(obj);
}
static
PyObject* check(PyObject* self, PyObject* args) {
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj)){
return NULL;
}
if (Check(obj)) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
}
static PyObject* Unwrap(PyObject* obj) {
if (PyObject_IsInstance(obj, GetWrapperClass())) {
return PyObject_GetAttrString(obj, "_ptr");
} else {
Py_INCREF(obj);
return obj;
}
}
/*
Unwrap a Wrapper instance into the underlying PyCapsule.
If `obj` is not a Wrapper instance, returns `obj`.
*/
static PyObject* unwrap(PyObject* self, PyObject* args) {
PyObject *obj;
if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
}
return Unwrap(obj);
}
static bool HasOwnership(PyObject* obj) {
PyObject* addr = GetPointer(obj);
PyObject* name = GetName(obj);
auto_pyobject nameaddr = PyTuple_Pack(2, name, addr);
PyObject* dtor = PyDict_GetItem(GetAddrDtorDict(), *nameaddr);
if (!dtor || dtor == Py_None) {
return false;
} else {
return true;
}
}
static PyObject* has_ownership(PyObject* self, PyObject* args) {
PyObject *obj;
if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
}
if (HasOwnership(obj)) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
}
static
void NormalizeString(std::ostream &os, const char* str) {
for(; *str; ++str){
if (*str == ':') {
os << '_';
if(*(str + 1) == ':') { ++str; }
} else {
os << *str;
}
}
}
static
PyObject* WrapCore(PyObject *oldCap, bool owned) {
auto_pyobject cap = PyObject_CallFunctionObjArgs(GetCapsuleClass(), oldCap,
NULL);
auto_pyobject cls = PyObject_CallMethod(*cap, "get_class", "");
auto_pyobject addr = GetPointer(oldCap);
auto_pyobject name = GetName(oldCap);
// look up cached object
auto_pyobject cache_cls = PyObject_GetItem(GetCache(), *cls);
Assert(*cache_cls);
int addr_in_cache = PyMapping_HasKey(*cache_cls, *addr);
PyObject* obj = NULL;
if (addr_in_cache) {
obj = PyObject_GetItem(*cache_cls, *addr);
} else {
if (!owned) {
auto_pyobject hasDtor = PyObject_CallMethod(*cls, "_has_dtor", "");
if (PyObject_IsTrue(*hasDtor)) {
auto_pyobject key = PyTuple_Pack(2, *name, *addr);
auto_pyobject val = PyObject_GetAttrString(*cls, "_delete_");
int ok = PyDict_SetItem(GetAddrDtorDict(), *key, *val);
Assert(ok != -1);
}
}
obj = PyObject_CallMethod(*cap, "instantiate", "");
int ok = PyObject_SetItem(*cache_cls, *addr, obj);
Assert(ok != -1);
}
Assert(obj);
return obj;
}
static
PyObject* Wrap(PyObject* cap, bool owned){
if (!Check(cap)) {
if (PyList_Check(cap)) {
const int N = PyList_Size(cap);
PyObject* result = PyList_New(N);
for (int i = 0; i < N; ++i){
PyObject* item = PyList_GetItem(cap, i);
if (!item)
return NULL;
PyObject* out = Wrap(item, false);
if (!out) return NULL;
if (-1 == PyList_SetItem(result, i, out))
return NULL;
}
return result;
} else {
Py_INCREF(cap);
return cap;
}
}
return WrapCore(cap, owned);
}
static
PyObject* wrap(PyObject* self, PyObject* args) {
PyObject* obj;
PyObject* owned = NULL;
if (!PyArg_ParseTuple(args, "O|O", &obj, &owned)) {
return NULL;
}
bool ownedFlag = false;
if (owned) {
ownedFlag = PyObject_IsTrue(owned);
}
return Wrap(obj, ownedFlag);
}
static
PyObject* downcast(PyObject* self, PyObject* args) {
PyObject *obj, *cls;
if (!PyArg_ParseTuple(args, "OO", &obj, &cls)) {
return NULL;
}
auto_pyobject objType = PyObject_Type(obj);
if (*objType == cls) {
Py_INCREF(obj);
return obj;
}
PyObject* apiModule = GetAPIModule();
auto_pyobject fromTy = PyObject_GetAttrString(obj, "_llvm_type_");
auto_pyobject toTy = PyObject_GetAttrString(cls, "_llvm_type_");
std::ostringstream oss;
auto_pyobject fromTyStr = PyObject_Str(*fromTy);
auto_pyobject toTyStr = PyObject_Str(*toTy);
const char * fromCS = PyString_AsString(*fromTyStr);
const char * toCS = PyString_AsString(*toTyStr);
oss << "downcast_";
NormalizeString(oss, fromCS);
oss << "_to_";
NormalizeString(oss, toCS);
std::string fname = oss.str();
auto_pyobject caster = PyObject_GetAttrString(GetDowncastModule(),
fname.c_str());
if (!caster) {
std::ostringstream oss;
oss << "Downcast from " << fromCS << " to " << toCS;
std::string errmsg = oss.str();
PyErr_SetString(PyExc_TypeError, errmsg.c_str());
return NULL;
}
auto_pyobject oldObj = Unwrap(obj);
auto_pyobject newObj = PyObject_CallFunctionObjArgs(*caster, *oldObj,
NULL);
bool used_to_own = HasOwnership(*oldObj);
PyObject *result = Wrap(*newObj, !used_to_own);
int status = PyObject_Not(result);
switch(status) {
case 0:
return result;
case 1:
default:
PyErr_SetString(PyExc_ValueError, "Downcast failed");
Py_XDECREF(result);
return NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
struct CapsuleObject {
PyObject_HEAD;
PyObject *capsule;
};
static
void Capsule_dealloc(CapsuleObject* self) {
Py_XDECREF(self->capsule);
Py_TYPE(self)->tp_free((PyObject*)self);
}
static
int Capsule_init(CapsuleObject *self, PyObject *args, PyObject *kwds)
{
PyObject *cap;
if (!PyArg_ParseTuple(args, "O", &cap)) {
return -1;
}
if (!Check(cap)) {
PyErr_SetString(PyExc_TypeError, "Expected PyCapsule object");
return -1;
}
Py_INCREF(cap);
self->capsule = cap;
PyObject* addr2refct = GetAddrRefCt();
auto_pyobject ptr = GetPointer(self->capsule);
auto_pyobject refct = PyObject_GetItem(addr2refct, *ptr);
auto_pyobject inc = PyNumber_InPlaceAdd(*refct, ConstantOne);
return PyObject_SetItem(addr2refct, *ptr, *inc);
}
static
PyObject* Capsule_getclassname(CapsuleObject* self, void *closure) {
return GetClassName(self->capsule);
}
static
PyObject* Capsule_getname(CapsuleObject* self, void *closure) {
return GetName(self->capsule);
}
static
PyObject* Capsule_getpointer(CapsuleObject* self, void *closure) {
return GetPointer(self->capsule);
}
static
PyObject* Capsule_GetClass(CapsuleObject *self){
PyObject *pycls = GetClassesDict();
auto_pyobject key = GetClassName(self->capsule);
return PyDict_GetItem(pycls, *key); // borrowed reference
}
static
PyObject* Capsule_get_class(CapsuleObject* self, PyObject* args) {
PyObject* out = Capsule_GetClass(self);
Py_XINCREF(out);
return out;
}
static
PyObject* Capsule_instantiate(CapsuleObject* self, PyObject* args) {
return PyObject_CallFunctionObjArgs(Capsule_GetClass(self), self, NULL);
}
/// Rotate Right
static unsigned long RotR(unsigned long hash, int offset){
if (offset == 0) return hash;
unsigned long out = hash << (sizeof(hash) * 8 - offset);
out |= hash >> offset;
return out;
}
/*
This is called everytime an object is returned from LLVM.
It derserves to be optimized to reduce unnecessary Python object allocation.
The following implements a simple hash function that uses XOR and
right-rotation.
*/
static
long Capsule_hash(CapsuleObject *self) {
const char* name = PyCapsule_GetName(self->capsule);
void *pointer = PyCapsule_GetPointer(self->capsule, name);
unsigned long hash = 0xabcd1234 ^ (unsigned long)pointer;
// The first loop accounts for the different LLVM class name and the
// length of the name.
for(const char* p = name; *p != '\0'; ++p) {
hash ^= *p;
hash = RotR(hash, 11);
}
// The second loop accounts for the pointer identity.
for(int i = 0; i <sizeof(pointer); ++i) {
hash ^= ((unsigned char*)&pointer)[i];
hash = RotR(hash, 11);
}
return hash;
}
static
bool Capsule_eq(PyObject *self, PyObject *other) {
if (PyObject_Type(self) == PyObject_Type(other)) {
CapsuleObject *a = (CapsuleObject*)self;
CapsuleObject *b = (CapsuleObject*)other;
void* pa = PyCapsule_GetPointer(a->capsule,
PyCapsule_GetName(a->capsule));
void* pb = PyCapsule_GetPointer(b->capsule,
PyCapsule_GetName(b->capsule));
return pa == pb;
}
return false;
}
static
PyObject* Capsule_richcmp(PyObject *a, PyObject *b, int op) {
bool ret = Capsule_eq(a, b);
switch(op) {
case Py_EQ: break;
case Py_NE: ret = !ret; break;
default:
return Py_NotImplemented;
}
if (ret) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
}
static PyMemberDef Capsule_members[] = {
{"capsule", T_OBJECT_EX, offsetof(CapsuleObject, capsule), READONLY, "capsule"},
{ NULL },
};
static PyMethodDef Capsule_methods[] = {
{ "get_class", (PyCFunction)Capsule_get_class, METH_NOARGS,
"Get Capsule class"},
{ "instantiate", (PyCFunction)Capsule_instantiate, METH_NOARGS,
"create a new instance"},
{ NULL },
};
static PyGetSetDef Capsule_getseters[] = {
{"classname", (getter)Capsule_getclassname, NULL, "class name", NULL},
{"name", (getter)Capsule_getname, NULL, "name", NULL},
{"pointer", (getter)Capsule_getpointer, NULL, "pointer", NULL},
{ NULL },
};
static PyTypeObject CapsuleType = {
#if (PY_MAJOR_VERSION < 3)
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
#else
PyVarObject_HEAD_INIT(NULL, 0)
#endif
"_capsule.Capsule", /*tp_name*/
sizeof(CapsuleObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Capsule_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)Capsule_hash, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Capsule object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)Capsule_richcmp, /*tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Capsule_methods, /* tp_methods */
Capsule_members, /* tp_members */
Capsule_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Capsule_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
///////////////////////////////////////////////////////////////////////////////
static PyMethodDef core_methods[] = {
#define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS , NULL }
@ -76,6 +585,10 @@ static PyMethodDef core_methods[] = {
declmethod(getPointer),
declmethod(check),
declmethod(getClassName),
declmethod(unwrap),
declmethod(wrap),
declmethod(has_ownership),
declmethod(downcast),
{ NULL },
#undef declmethod
};
@ -106,10 +619,21 @@ extern "C" {
#else
PyObject *module = Py_InitModule("_capsule", core_methods);
#endif
if (module == NULL)
if (module == NULL){
INITERROR;
}
if (module) {
CapsuleType.tp_new = PyType_GenericNew;
if (PyType_Ready(&CapsuleType) < 0) {
INITERROR;
}
Py_INCREF(&CapsuleType);
PyModule_AddObject(module, "Capsule", (PyObject*)(&CapsuleType));
ConstantOne = PyInt_FromLong(1);
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}

View file

@ -1,17 +1,27 @@
from weakref import WeakKeyDictionary, WeakValueDictionary, ref
from weakref import WeakValueDictionary
from collections import defaultdict
import logging
from llvmpy._capsule import (unwrap, has_ownership, downcast, wrap,
getClassName, getName, getPointer, Capsule)
logger = logging.getLogger(__name__)
NO_DEBUG = False
def silent_logger():
'''
Silent logger for unless we have a error message.
'''
global NO_DEBUG
logger.setLevel(logging.ERROR)
NO_DEBUG = True
# 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.
@ -26,75 +36,63 @@ def set_debug(enabled):
else:
logger.setLevel(logging.WARNING)
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((name, addr), None)
if dtor is not None:
logger.debug('Destroy %s %s', name, hex(addr))
dtor(item.capsule)
class Capsule(object):
"Wraps PyCapsule so that we can build weakref of it."
#class Capsule(object):
# "Wraps PyCapsule so that we can build weakref of it."
# from ._capsule import check, getClassName, getName, getPointer
# __slots__ = "capsule"
#
# 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 self.getClassName(self.capsule)
#
# @property
# def name(self):
# return self.getName(self.capsule)
#
# @property
# def pointer(self):
# return self.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 isinstance(other, Capsule) and self.pointer == other.pointer:
# assert self.name == other.name
# return True
# else:
# return False
#
# def __hash__(self):
# return hash((self.pointer, self.name))
#
# def __ne__(self, other):
# return not (self == other)
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 self.getClassName(self.capsule)
@property
def name(self):
return self.getName(self.capsule)
@property
def pointer(self):
return self.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 __hash__(self):
return hash((self.pointer, self.name))
def __ne__(self, other):
return not (self == other)
class WeakRef(ref):
pass
_addr2refct = defaultdict(lambda: 0)
_capsule2weak = WeakKeyDictionary()
#_capsule2weak = WeakKeyDictionary()
_addr2dtor = {}
_pyclasses = {}
@ -102,15 +100,16 @@ _pyclasses = {}
# NOTE: The same 'addr' may appear in multiple class bins.
_cache = defaultdict(WeakValueDictionary)
def release_ownership(old):
logger.debug('Release %s', old)
addr = Capsule.getPointer(old)
name = Capsule.getName(old)
addr = getPointer(old)
name = getName(old)
if _addr2dtor.get((name, addr)) is None:
clsname = Capsule.getClassName(old)
clsname = getClassName(old)
if not _pyclasses[clsname]._has_dtor():
return
# Guard duplicated release
# Guard duplicated release
raise Exception("Already released")
_addr2dtor[(name, addr)] = None
@ -120,61 +119,86 @@ def obtain_ownership(cap):
if cls._has_dtor():
addr = cap.pointer
name = cap.name
assert _addr2dtor[addr] is None
assert _addr2dtor[(name, addr)] is None
_addr2dtor[(name, addr)] = cls._delete_
def has_ownership(cap):
addr = Capsule.getPointer(cap)
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.
If `cap` is not a PyCapsule, returns `cap`
'''
if not Capsule.valid(cap):
if isinstance(cap, list):
return list(map(wrap, cap))
return cap # bypass if cap is not a PyCapsule and not a list
#def has_ownership(cap):
# addr = Capsule.getPointer(cap)
# name = Capsule.getName(cap)
# return _addr2dtor.get((name, addr)) is not None
cap = Capsule(cap)
cls = cap.get_class()
addr = cap.pointer
name = cap.name
# 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()
_cache[cls][addr] = obj # cache it
return obj
def unwrap(obj):
#def wrap(cap, owned=False):
# '''Wrap a PyCapsule with the corresponding Wrapper class.
# If `cap` is not a PyCapsule, returns `cap`
# '''
# if not Capsule.valid(cap):
# if isinstance(cap, list):
# return list(map(wrap, cap))
# return cap # bypass if cap is not a PyCapsule and not a list
#
# cap = Capsule(cap)
# cls = cap.get_class()
# addr = cap.pointer
# name = cap.name
# # 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()
# _cache[cls][addr] = obj # cache it
# 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
# if isinstance(obj, Wrapper):
# return obj._ptr
# else:
# return obj
def register_class(clsname):
def _wrapped(cls):
_pyclasses[clsname] = cls
return cls
return _wrapped
class Wrapper(object):
__slots__ = '__capsule'
def __init__(self, capsule):
self.__capsule = capsule
def __del__(self):
if _addr2refct is None:
# System is tearing down
# No need to free anything
return
item = self.__capsule
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((name, addr), None)
if dtor is not None:
if not NO_DEBUG:
# Some globals in logger could be removed by python GC
# at interpreter teardown.
# That can cause exception raised and ignored message.
logger.debug('Destroy %s %s', name, hex(addr))
dtor(item.capsule)
@property
def _capsule(self):
return self.__capsule
@ -187,10 +211,11 @@ class Wrapper(object):
return hash(self._capsule)
def __eq__(self, other):
return self._capsule == other._capsule
if isinstance(other, Wrapper):
return self._capsule == other._capsule
def __ne__(self, other):
return not(self == other)
return not (self == other)
def _downcast(self, newcls):
return downcast(self, newcls)
@ -199,24 +224,25 @@ class Wrapper(object):
def _has_dtor(cls):
return hasattr(cls, '_delete_')
def downcast(obj, cls):
from . 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('::', '_')
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)
res = wrap(new, owned=not used_to_own)
if not res:
raise ValueError("Downcast failed")
return res
#def downcast(obj, cls):
# from . 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('::', '_')
# 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)
# res = wrap(new, owned=not used_to_own)
# if not res:
# raise ValueError("Downcast failed")
# return res

View file

@ -1,5 +1,4 @@
import inspect, textwrap
import functools
import codegen as cg
import os
@ -8,10 +7,12 @@ namespaces = {}
RESERVED = frozenset(['None'])
def makedir(directory):
if not os.path.exists(directory):
os.makedirs(directory)
class SubModule(object):
def __init__(self):
self.methods = []
@ -293,6 +294,10 @@ class Class(SubModule, _Type):
writer.println('@capsule.register_class("%s")' % self.fullname)
with writer.block('class %(clsname)s(%(bases)s):' % locals()):
writer.println('_llvm_type_ = "%s"' % self.fullname)
if self.bases:
writer.println('__slots__ = ()')
else:
writer.println('__slots__ = "__weakref__"')
for enum in self.enums:
enum.compile_py(writer)
for meth in self.methods:
@ -333,7 +338,7 @@ class Class(SubModule, _Type):
writer.die_if_false(raw, verbose=name)
ptrty = ptr(self).fullname
ty = self.fullname
fmt = 'typecast< %(ty)s >::from(%(raw)s)'
fmt = 'unwrap_as<%(ty)s, %(name)s >::from(%(raw)s)'
casted = writer.declare(ptrty, fmt % locals())
writer.die_if_false(casted)
return casted
@ -399,6 +404,7 @@ class Enum(object):
writer.println(fmt % locals())
writer.println()
class Method(object):
_kind_ = 'meth'
@ -516,6 +522,7 @@ class Method(object):
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):
super(CustomMethod, self).__init__(retty, *argtys)
@ -594,6 +601,7 @@ class CustomFunction(Function):
def fullname(self):
return self.realname
class Destructor(Method):
_kind_ = 'dtor'
@ -625,6 +633,7 @@ class Constructor(StaticMethod):
ret = writer.declare(retty.fullname, stmt)
return ret
class ref(_Type):
def __init__(self, element):
assert isinstance(element, Class), type(element)
@ -686,13 +695,16 @@ class ptr(_Type):
return writer.pycapsule_new(val, self.element.capsule_name,
self.element.fullname)
class ownedptr(ptr):
pass
def const(ptr_or_ref):
ptr_or_ref.const = True
return ptr_or_ref
class cast(_Type):
format = 'O'
@ -757,6 +769,7 @@ class CustomPythonMethod(object):
for line in self.sourcelines:
writer.println(line)
class CustomPythonStaticMethod(CustomPythonMethod):
def compile_py(self, writer):
writer.println('@staticmethod')
@ -845,6 +858,7 @@ class Attr(object):
TARGETS_BUILT = os.environ.get('LLVM_TARGETS_BUILT', '').split()
def _parse_llvm_version(ver):
import re
m = re.compile(r'(\d+)\.(\d+)').match(ver)

View file

@ -202,7 +202,8 @@ class CppCodeWriter(CodeWriterBase):
def pycapsule_new(self, ptr, name, clsname):
name_soften = mangle(name)
ret = self.call('pycapsule_new', 'PyObject*', ptr, quote(name),
cast_to_base = 'cast_to_base<%s >::from(%s)' % (name, ptr)
ret = self.call('pycapsule_new', 'PyObject*', cast_to_base, quote(name),
quote(clsname))
with self.block('if (!%(ret)s)' % locals()):
self.return_null()

View file

@ -9,7 +9,7 @@ extern "C" {
#if (PY_MAJOR_VERSION >= 3)
PyObject *
PyMODINIT_FUNC
PyInit_%(module)s(void)
{
PyObject *module = create_python_module("%(module)s", meth_%(ns)s);

View file

@ -256,6 +256,7 @@ template<class Td>
struct typecast {
template<class Ts> static
Td* from(Ts* src) {
// check why this is only used in Python3
return llvm::dyn_cast<Td>(src);
}
@ -265,3 +266,24 @@ struct typecast {
}
};
template<class Td, class Tbase>
struct unwrap_as {
static
Td* from(void* src) {
Tbase* base = static_cast<Tbase*>(src);
return static_cast<Td*>(base);
}
};
template<class Td>
struct cast_to_base {
template<class Ts> static
Td* from(Ts* src){
return static_cast<Td*>(src);
}
template<class Ts> static
const Td* from(const Ts* src){
return static_cast<const Td*>(src);
}
};

View file

@ -1,6 +1,6 @@
#include <Python.h>
#include <llvm/ADT/SmallVector.h>
#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 3
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3
#include <llvm/IR/Value.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Function.h>
@ -8,6 +8,10 @@
#include <llvm/IR/Constants.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/IRBuilder.h>
#if LLVM_VERSION_MINOR >= 4
#include <llvm/Support/MemoryObject.h>
#include <llvm/MC/MCDisassembler.h>
#endif
#else
#include <llvm/Value.h>
#include <llvm/DerivedTypes.h>
@ -36,7 +40,7 @@
namespace extra{
using namespace llvm;
class raw_svector_ostream_helper: public raw_svector_ostream {
SmallVectorImpl<char> *SV;
public:
@ -81,7 +85,7 @@ PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args)
{
using extra::raw_svector_ostream_helper;
using llvm::raw_svector_ostream;
if (!PyArg_ParseTuple(args, "")) {
return NULL;
}
@ -95,7 +99,7 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args)
{
using llvm::Type;
typedef llvm::SmallVector<llvm::Type*, 8> SmallVector_Type;
SmallVector_Type* SV = new SmallVector_Type;
Py_ssize_t size = PyTuple_Size(args);
for (Py_ssize_t i = 0; i < size; ++i) {
@ -182,8 +186,8 @@ PyObject* iterator_to_pylist_deref(iterator begin, iterator end,
{
PyObject* list = PyList_New(0);
for(; begin != end; ++begin) {
PyObject* cap = pycapsule_new(&*begin, capsuleName, className);
PyList_Append(list, cap);
auto_pyobject cap = pycapsule_new(&*begin, capsuleName, className);
PyList_Append(list, *cap);
}
return list;
}
@ -194,8 +198,8 @@ PyObject* iterator_to_pylist(iterator begin, iterator end,
{
PyObject* list = PyList_New(0);
for(; begin != end; ++begin) {
PyObject* cap = pycapsule_new(*begin, capsuleName, className);
PyList_Append(list, cap);
auto_pyobject cap = pycapsule_new(*begin, capsuleName, className);
PyList_Append(list, *cap);
}
return list;
}
@ -416,7 +420,7 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE,
PyErr_SetString(PyExc_RuntimeError, "Failed to index into args?");
return NULL;
}
GenericValue* gv = static_cast<GenericValue*>(
PyCapsule_GetPointer(obj, GVN));
@ -571,11 +575,11 @@ PyObject* TargetMachine_addPassesToEmitFile(
bool status = TM->addPassesToEmitFile(PM, fso, FTy, disableVerify);
if (status) {
StringRef sr = rso.str();
PyObject* buf = PyString_FromStringAndSize(sr.data(), sr.size());
auto_pyobject buf = PyString_FromStringAndSize(sr.data(), sr.size());
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;
@ -622,7 +626,7 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker,
if (! failed) {
Py_RETURN_FALSE;
} else {
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
if (NULL == callwrite(ErrMsg, *buf)){
return NULL;
@ -857,6 +861,27 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename,
}
}
static
PyObject* DynamicLibrary_getPermanentLibrary(const char * Filename,
PyObject* ErrMsg = 0)
{
using namespace llvm::sys;
std::string errmsg;
DynamicLibrary dylib = DynamicLibrary::getPermanentLibrary(Filename, &errmsg);
if (!dylib.isValid()) {
if (ErrMsg) {
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
if (!callwrite(ErrMsg, *buf))
return NULL;
}
PyErr_SetString(PyExc_RuntimeError, errmsg.c_str());
return NULL;
}
return pycapsule_new(new DynamicLibrary(dylib),
"llvm::sys::DynamicLibrary",
"llvm::sys::DynamicLibrary");
}
class PassRegistryEnumerator : public llvm::PassRegistrationListener{
public:
PyObject* List;
@ -866,7 +891,8 @@ public:
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));
auto_pyobject pair = Py_BuildValue("(OO)", passArg, passName);
PyList_Append(List, *pair);
}
};
@ -921,7 +947,6 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch,
}
}
static
PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error)
{
@ -942,6 +967,66 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error)
}
static
PyObject* TargetRegistry_targets_list()
{
using namespace llvm;
return iterator_to_pylist_deref<TargetRegistry::iterator>(
TargetRegistry::begin(), TargetRegistry::end(),
"llvm::Target", "llvm::Target");
}
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 4
static
PyObject* MemoryObject_readBytes(const llvm::MemoryObject *mobj,
uint64_t addr,
uint64_t size
)
{
int status;
uint8_t *bytes;
PyObject* po;
if(size < 1)
goto fail;
bytes = new uint8_t[size];
if(bytes == NULL)
goto fail;
status = mobj->readBytes(addr, size, bytes);
if(status != 0) {
delete bytes;
goto fail;
}
po = PyBytes_FromStringAndSize((const char *) bytes, size);
delete bytes;
return po;
fail:
Py_RETURN_NONE;
}
static
PyObject* MCDisassembler_getInstruction(llvm::MCDisassembler *disasm,
llvm::MCInst &instr,
const llvm::MemoryObject &region,
uint64_t address
)
{
uint64_t size;
llvm::MCDisassembler::DecodeStatus status;
size = 0;
status = disasm->getInstruction(instr, size, region, address,
llvm::nulls(), llvm::nulls());
return Py_BuildValue("(i,i)", int(status), size);
}
#endif /* llvm >= 3.4 */
static
PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features)
{
@ -983,4 +1068,5 @@ PyObject* llvm_sys_isBigEndianHost()
else
Py_RETURN_FALSE;
}
#endif
#endif

View file

@ -31,7 +31,7 @@ components = ['core', 'analysis', 'scalaropts',
'interpreter', 'bitreader',
'bitwriter', 'instrumentation', 'ipa',
'ipo', 'transformutils', 'asmparser',
'linker', 'support', 'vectorize',
'linker', 'support', 'vectorize', 'all-targets'
]
nvptx = ['nvptx',

View file

@ -21,14 +21,14 @@ 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,
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''')
delete = Destructor()

View file

@ -1,12 +1,13 @@
from binding import *
from .namespace import llvm
from .Value import Function, BasicBlock
from .Value import Function, BasicBlock, Value
from .Instruction import Instruction, TerminatorInst
from .LLVMContext import LLVMContext
from .ADT.StringRef import StringRef
@BasicBlock
class BasicBlock:
_downcast_ = Value
Create = StaticMethod(ptr(BasicBlock), ref(LLVMContext),
cast(str, StringRef),
ptr(Function),

View file

@ -1,10 +1,16 @@
from binding import *
from .namespace import llvm
ccs = '''
C, Fast, Cold, GHC, FirstTargetCC, X86_StdCall, X86_FastCall,
ARM_APCS, ARM_AAPCS, ARM_AAPCS_VFP, MSP430_INTR, X86_ThisCall,
PTX_Kernel, PTX_Device,
'''
if LLVM_VERSION <= (3, 3):
ccs += "MBLAZE_INTR, MBLAZE_SVOL,"
ccs += 'SPIR_FUNC, SPIR_KERNEL, Intel_OCL_BI'
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,
SPIR_KERNEL, Intel_OCL_BI
''') # HiPE
ID = CallingConv.Enum('ID', ccs) # HiPE

View file

@ -6,7 +6,7 @@ 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 DIFile, DIEnumerator, DIType, DIBasicType, DIDerivedType, DICompositeType
from .DebugInfo import DIDescriptor, DIArray, DISubrange, DIGlobalVariable
from .DebugInfo import DIVariable, DISubprogram, DINameSpace, DILexicalBlockFile
from .DebugInfo import DILexicalBlock
@ -25,7 +25,8 @@ class DIBuilder:
new = Constructor(ref(Module))
delete = Destructor()
getCU = Method(const(ptr(MDNode)))
if LLVM_VERSION <= (3, 3):
getCU = Method(const(ptr(MDNode)))
finalize = Method()
createCompileUnit = Method(Void,
@ -46,12 +47,16 @@ class DIBuilder:
createEnumerator = Method(DIEnumerator,
stringref_arg, # Name
uint64_arg, # Val
uint64_arg if LLVM_VERSION <= (3, 3) else int64_arg, # Val
)
createNullPtrType = Method(DIType,
stringref_arg, # Name
)
if LLVM_VERSION <= (3, 3):
createNullPtrType = Method(DIType,
stringref_arg, # Name
)
else:
createNullPtrType = Method(DIBasicType)
createBasicType = Method(DIType,
stringref_arg, # Name
@ -85,7 +90,7 @@ class DIBuilder:
ref(DIDescriptor), # Context
)
createFriend = Method(DIType,
createFriend = Method(DIType if LLVM_VERSION <= (3, 3) else DIDerivedType,
ref(DIType), # Ty
ref(DIType), # FriendTy
)
@ -169,7 +174,7 @@ class DIBuilder:
ref(DIArray), # Subscripts
)
createVectorType = Method(DIType,
createVectorType = Method(DIType if LLVM_VERSION <= (3, 3) else DICompositeType,
uint64_arg, # Size
uint64_arg, # AlignInBits
ref(DIType), # Ty
@ -199,7 +204,7 @@ class DIBuilder:
createObjectPointerType = Method(DIType,
ref(DIType), # Ty
)
#createTemporaryType = Method(DIType, ref(DIFile)).require_only(0)
createForwardDecl = Method(DIType,
@ -245,7 +250,7 @@ class DIBuilder:
bool_arg, # isLocalToUnit
ptr(Value), # Val
)
createLocalVariable = Method(DIVariable,
unsigned_arg, # Tag,
ref(DIDescriptor), # Scope,
@ -268,14 +273,14 @@ class DIBuilder:
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
ref(DIType if LLVM_VERSION <= (3, 3) else DICompositeType), # Ty
bool_arg, # isLocalToUnit
bool_arg, # isDefinition
unsigned_arg, # ScopeLine
@ -293,7 +298,7 @@ class DIBuilder:
stringref_arg, # LinkageName
ref(DIFile), # File
unsigned_arg, # LineNo
ref(DIType), # Ty
ref(DIType if LLVM_VERSION <= (3, 3) else DICompositeType), # Ty
bool_arg, # isLocalToUnit
bool_arg, # isDefinition
unsigned_arg, # Virtuality=0
@ -313,7 +318,7 @@ class DIBuilder:
unsigned_arg, # LineNo
)
createLexicalBlockFile = Method(DILexicalBlockFile,
createLexicalBlockFile = Method(DILexicalBlockFile,
ref(DIDescriptor), # Scope,
ref(DIFile), # File
)
@ -324,7 +329,7 @@ class DIBuilder:
unsigned_arg, # Line,
unsigned_arg, # Col
)
_insertDeclare_1 = Method(ptr(Instruction),
ptr(Value), # Storage,
ref(DIVariable), # VarInfo

View file

@ -44,7 +44,7 @@ class DIFile:
@DIEnumerator
class DIEnumerator:
getName = Method(return_stringref)
getEnumValue = Method(cast(Uint64, int))
getEnumValue = Method(cast(Uint64 if LLVM_VERSION <= (3, 3) else Int64, int))
Verify = Method(return_bool)
@DIType

View file

@ -19,7 +19,7 @@ class Function:
_include_ = 'llvm/IR/Function.h'
else:
_include_ = 'llvm/Function.h'
_downcast_ = GlobalValue, Constant, Value
getReturnType = Method(ptr(Type))

View file

@ -346,6 +346,9 @@ class AllocaInst:
isStaticAlloca = Method(cast(Bool, bool))
getArraySize = Method(ptr(Value))
getAllocatedType = Method(ptr(Type))
getAlignment = Method(cast(Unsigned, int))
setAlignment = Method(Void, cast(int, Unsigned))
getArraySize = Method(ptr(Value))
@CastInst

157
llvmpy/src/MC/__init__.py Normal file
View file

@ -0,0 +1,157 @@
#this file is not processed unless the llvm library is
#version 3.4 or higher. see llvmpy/__init__.py for details.
from binding import *
from ..namespace import llvm
from ..Support.StringRefMemoryObject import MemoryObject
from ..Support.raw_ostream import raw_ostream
from src.ADT.StringRef import StringRef
MCSubtargetInfo = llvm.Class()
MCDisassembler = llvm.Class()
MCInst = llvm.Class()
MCOperand = llvm.Class()
MCExpr = llvm.Class()
MCAsmInfo = llvm.Class()
MCRegisterInfo = llvm.Class()
MCInstrInfo = llvm.Class()
MCInstrAnalysis = llvm.Class()
MCInstPrinter = llvm.Class()
MCInstrDesc = llvm.Class()
TargetSubtargetInfo = llvm.Class(MCSubtargetInfo)
TargetInstrInfo = llvm.Class(MCInstrInfo)
TargetRegisterInfo = llvm.Class(MCRegisterInfo)
@MCInstrDesc
class MCInstrDesc:
_include_ = "llvm/MC/MCInstrDesc.h"
TSFlags = Attr(getter=cast(Uint64, int), setter=cast(int, Uint64))
getFlags = Method(cast(Unsigned, int))
getOpcode = Method(cast(Unsigned, int))
def _ret_bool():
return Method(cast(Bool, bool))
isReturn = _ret_bool()
isCall = _ret_bool()
isBarrier = _ret_bool()
isBranch = _ret_bool()
isTerminator = _ret_bool()
isIndirectBranch = _ret_bool()
isConditionalBranch = _ret_bool()
isUnconditionalBranch = _ret_bool()
@MCSubtargetInfo
class MCSubtargetInfo:
pass
@TargetSubtargetInfo
class TargetSubtargetInfo:
_include_ = 'llvm/Target/TargetSubtargetInfo.h'
@MCExpr
class MCExpr:
_include_ = "llvm/MC/MCExpr.h"
ExprKind = Enum('Binary', 'Constant', 'SymbolRef', 'Unary', 'Target')
getKind = Method(ExprKind)
@MCOperand
class MCOperand:
_include_ = "llvm/MC/MCInst.h"
isValid = Method(cast(Bool, bool))
isReg = Method(cast(Bool, bool))
isImm = Method(cast(Bool, bool))
isFPImm = Method(cast(Bool, bool))
isExpr = Method(cast(Bool, bool))
isInst = Method(cast(Bool, bool))
getReg = Method(cast(Unsigned, int))
getImm = Method(cast(Int64, int))
getFPImm = Method(cast(Double, float))
getExpr = Method(const(ownedptr(MCExpr)))
@MCInst
class MCInst:
_include_ = "llvm/MC/MCInst.h"
new = Constructor()
size = Method(cast(Size_t, int))
getNumOperands = Method(cast(Unsigned, int))
getOperand = Method(const(ref(MCOperand)), cast(int, Unsigned))
getOpcode = Method(cast(Unsigned, int))
MCOperand.getInst = Method(const(ownedptr(MCInst)))
@MCAsmInfo
class MCAsmInfo:
_include_ = "llvm/MC/MCAsmInfo.h"
getAssemblerDialect = Method(cast(Unsigned, int))
getMinInstAlignment = Method(cast(Unsigned, int))
isLittleEndian = Method(cast(Bool, bool))
@MCRegisterInfo
class MCRegisterInfo:
_include_ = "llvm/MC/MCRegisterInfo.h"
getName = Method(cast(ConstCharPtr, str), cast(int, Unsigned))
@TargetRegisterInfo
class TargetRegisterInfo:
_include_ = "llvm/Target/TargetRegisterInfo.h"
@MCInstrInfo
class MCInstrInfo:
_include_ = "llvm/MC/MCInstrInfo.h"
get = Method(const(ref(MCInstrDesc)), cast(int, Unsigned))
@TargetInstrInfo
class TargetInstrInfo:
_include_ = 'llvm/Target/TargetInstrInfo.h'
@MCInstrAnalysis
class MCInstrAnalysis:
_include_ = "llvm/MC/MCInstrAnalysis.h"
def _take_mcinst_ret_bool():
return Method(cast(Bool, bool), const(ref(MCInst)))
isBranch = _take_mcinst_ret_bool()
isConditionalBranch = _take_mcinst_ret_bool()
isUnconditionalBranch = _take_mcinst_ret_bool()
isIndirectBranch = _take_mcinst_ret_bool()
isCall = _take_mcinst_ret_bool()
isReturn = _take_mcinst_ret_bool()
isTerminator = _take_mcinst_ret_bool()
@MCInstPrinter
class MCInstPrinter:
_include_ = "llvm/MC/MCInstPrinter.h"
printInst = Method(Void,
const(ptr(MCInst)), #MI
ref(raw_ostream), #OS
cast(str, StringRef) #Annot
)
@MCDisassembler
class MCDisassembler:
_include_ = "llvm/MC/MCDisassembler.h"
DecodeStatus = Enum('Fail', 'SoftFail', 'Success')
getInstruction = CustomMethod('MCDisassembler_getInstruction',
PyObjectPtr,
ref(MCInst),
ref(MemoryObject),
cast(int, Uint64)
)

File diff suppressed because it is too large Load diff

View file

@ -26,3 +26,10 @@ class DynamicLibrary:
cast(str, StringRef), # symbolName
cast(int, VoidPtr), # address
)
getPermanentLibrary = CustomStaticMethod(
'DynamicLibrary_getPermanentLibrary',
PyObjectPtr,
cast(str, ConstCharPtr), # filename
PyObjectPtr, # std::string * errmsg = 0
).require_only(1)

View file

@ -17,7 +17,7 @@ if LLVM_VERSION >= (3, 3):
cast(Bool, bool))
else:
isLittleEndianHost = sys.Function('isLittleEndianHost',
cast(Bool, bool))

View file

@ -0,0 +1,32 @@
from binding import *
from ..namespace import llvm
from ..ADT.StringRef import StringRef
if LLVM_VERSION >= (3, 4):
MemoryObject = llvm.Class()
StringRefMemoryObject = llvm.Class(MemoryObject)
@MemoryObject
class MemoryObject:
_include_ = "llvm/Support/MemoryObject.h"
getBase = Method(cast(Uint64, int))
getExtent = Method(cast(Uint64, int))
readBytes = CustomMethod('MemoryObject_readBytes',
PyObjectPtr,
cast(int, Uint64), #address
cast(int, Uint64) #size
)
@CustomPythonMethod
def readAll(self):
result = self.readBytes(self.getBase(), self.getExtent())
if not result:
raise Exception("expected readBytes to be successful!")
return result
@StringRefMemoryObject
class StringRefMemoryObject:
_include_ = "llvm/Support/StringRefMemoryObject.h"
new = Constructor(cast(bytes, StringRef), cast(int, Uint64))

View file

@ -12,9 +12,18 @@ from src.Target.TargetMachine import TargetMachine
from src.Target.TargetOptions import TargetOptions
from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt
if LLVM_VERSION >= (3, 4):
from src.MC import MCSubtargetInfo
from src.MC import MCDisassembler
from src.MC import MCRegisterInfo
from src.MC import MCAsmInfo
from src.MC import MCInstrInfo
from src.MC import MCInstrAnalysis
from src.MC import MCInstPrinter
@Target
class Target:
getNext = Method(const(ptr(Target)))
getNext = Method(const(ownedptr(Target)))
getName = Method(cast(StdString, str))
getShortDescription = Method(cast(StdString, str))
@ -43,7 +52,35 @@ class Target:
CodeGenOpt.Level, # = CodeGenOpt.Default
).require_only(4)
if LLVM_VERSION >= (3, 4):
createMCSubtargetInfo = Method(ptr(MCSubtargetInfo),
cast(str, StringRef), #triple
cast(str, StringRef), #cpu
cast(str, StringRef) #features
)
createMCDisassembler = Method(ptr(MCDisassembler), ref(MCSubtargetInfo))
createMCRegInfo = Method(ptr(MCRegisterInfo),
cast(str, StringRef) #Triple
)
createMCAsmInfo = Method(ptr(MCAsmInfo),
const(ref(MCRegisterInfo)), #MRI
cast(str, StringRef) #Triple
)
createMCInstrInfo = Method(ptr(MCInstrInfo))
createMCInstrAnalysis = Method(ptr(MCInstrAnalysis), const(ptr(MCInstrInfo)))
createMCInstPrinter = Method(ptr(MCInstPrinter),
cast(int, Unsigned), #SyntaxVariant
const(ref(MCAsmInfo)), #MAI
const(ref(MCInstrInfo)), #MII
const(ref(MCRegisterInfo)), #MRI
const(ref(MCSubtargetInfo)) #STI
)
@TargetRegistry
class TargetRegistry:
printRegisteredTargetsForVersion = StaticMethod()
@ -66,3 +103,6 @@ class TargetRegistry:
PyObjectPtr, # const Target*
PyObjectPtr, # std::string &Error
)
targetsList = CustomStaticMethod('TargetRegistry_targets_list', PyObjectPtr)

View file

@ -14,10 +14,13 @@ 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')
InitializeAllTargets = llvm.Function('InitializeAllTargets')
InitializeAllTargetInfos = llvm.Function('InitializeAllTargetInfos')
InitializeAllTargetMCs = llvm.Function('InitializeAllTargetMCs')
InitializeAllAsmPrinters = llvm.Function('InitializeAllAsmPrinters')
InitializeAllDisassemblers = llvm.Function('InitializeAllDisassemblers')
InitializeAllAsmParsers = llvm.Function('InitializeAllAsmParsers')
for target in TARGETS_BUILT:
decls = 'Target', 'TargetInfo', 'TargetMC', 'AsmPrinter'

View file

@ -8,6 +8,11 @@ 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
if LLVM_VERSION >= (3, 4):
from src.MC import MCAsmInfo, \
TargetInstrInfo, \
TargetSubtargetInfo, \
TargetRegisterInfo
if LLVM_VERSION < (3, 3):
from src.TargetTransformInfo import (ScalarTargetTransformInfo,
@ -48,6 +53,9 @@ class TargetMachine:
getVectorTargetTransformInfo = Method(const(
ownedptr(VectorTargetTransformInfo)))
else:
addAnalysisPasses = Method(Void, ref(PassManagerBase))
addPassesToEmitFile = Method(cast(bool, Bool),
ref(PassManagerBase),
ref(formatted_raw_ostream),
@ -55,4 +63,12 @@ class TargetMachine:
cast(bool, Bool)
).require_only(3)
if LLVM_VERSION >= (3, 4):
getSubtargetImpl = Method(const(ownedptr(TargetSubtargetInfo)))
getMCAsmInfo = Method(const(ownedptr(MCAsmInfo)))
getInstrInfo = Method(const(ownedptr(TargetInstrInfo)))
getRegisterInfo = Method(const(ownedptr(TargetRegisterInfo)))

View file

@ -33,7 +33,9 @@ class PassManagerBuilder:
return Attr(getter=cast(Bool, bool),
setter=cast(bool, Bool))
DisableSimplifyLibCalls = _attr_bool()
if LLVM_VERSION <= (3, 3):
DisableSimplifyLibCalls = _attr_bool()
DisableUnitAtATime = _attr_bool()
DisableUnrollLoops = _attr_bool()
if LLVM_VERSION >= (3, 3):

View file

@ -13,4 +13,4 @@ SplitBlockAndInsertIfThen = llvm.Function('SplitBlockAndInsertIfThen',
ReplaceInstWithInst = llvm.Function('ReplaceInstWithInst',
Void,
ptr(Instruction), # from
ptr(Instruction)) # to
ptr(Instruction)) # to

View file

@ -1,4 +1,7 @@
import os.path
from binding import LLVM_VERSION
above_33 = ("MC")
def _init(root=__name__, file=__file__):
base = os.path.dirname(file)
@ -9,6 +12,10 @@ def _init(root=__name__, file=__file__):
is_python_module = is_directory and not fname.startswith('__')
if (is_python_module or is_python_script) and not is_init_script:
print(fname)
if fname in above_33 and LLVM_VERSION <= (3, 3):
print("skip %s because llvm version is not above 3.3" % fname)
continue
modname = os.path.basename(fname).rsplit('.', 1)[0]
#importlib.import_module('.' + modname, __name__)
__import__('.'.join([root, modname]))

View file

@ -63,7 +63,7 @@ def auto_intrinsic_gen(incdir):
print("Generate intrinsic IDs")
from tools import intrgen
if llvm_version.startswith('3.3'):
if llvm_version.startswith('3.3') or llvm_version.startswith('3.4'):
path = "%s/llvm/IR/Intrinsics.gen" % incdir
else:
path = "%s/llvm/Intrinsics.gen" % incdir
@ -128,7 +128,7 @@ else:
['core', 'analysis', 'scalaropts', 'executionengine', 'mcjit',
'jit', 'native', 'interpreter', 'bitreader', 'bitwriter',
'instrumentation', 'ipa', 'ipo', 'transformutils',
'asmparser', 'linker', 'support', 'vectorize']
'asmparser', 'linker', 'support', 'vectorize', 'all-targets']
+ extra_components)
if sys.platform == 'win32':
@ -184,10 +184,14 @@ setup(
maintainer_email = 'llvmpy@continuum.io',
url = 'http://www.llvmpy.org/',
packages = ['llvm', 'llvm.workaround',
'llvm.mc',
'llvm_cbuilder',
'llpython',
'llvm_array',
'llvmpy.api', 'llvmpy.api.llvm'],
'llvmpy.api', 'llvmpy.api.llvm',
'llvm.tests',
'llvm.utils',],
package_data = {'llvm': ['llrt/*.ll']},
py_modules = ['llvmpy',
'llvmpy._capsule',
'llvmpy._api',

View file

@ -0,0 +1,64 @@
import llvm
if llvm.version >= (3, 4):
from llvm.target import TargetMachine
from llvm import mc
from llvm.mc import Disassembler
llvm.target.initialize_all()
def print_instructions(dasm, bs, align=None):
branch_properties = [
'is_branch',
'is_cond_branch',
'is_uncond_branch',
'is_indirect_branch',
'is_call',
'is_return',
'is_terminator',
'is_barrier'
]
print("print instructions")
for (addr, data, inst) in dasm.decode(bs, 0x4000, align):
if inst is None:
print("\t0x%x => (bad)" % (addr))
else:
ops = ", ".join(map(lambda op: repr(op), inst.operands()))
if isinstance(inst, mc.BadInstr):
print("\t0x%x (bad) ops = %s" % (addr, ops))
else:
print("\t0x%x ops = %s" % (addr, ops))
print("\t\topcode = 0x%x, flags = 0x%x, tsflags = 0x%x" % (inst.opcode, inst.flags, inst.ts_flags))
for line in str(inst).split("\n"):
print("\t\t%-24s %s" % ("".join(map(lambda b: "%02x" % b, data))+":", line.strip()))
for bp in branch_properties:
print("\t\t%-22s%r" % (bp+":", getattr(inst, bp)() ))
x86 = TargetMachine.x86()
print("x86: LE=%s" % x86.is_little_endian())
print_instructions(Disassembler(x86), "\x01\xc3\xc3\xcc\x90")
x86_64 = TargetMachine.x86_64()
print("x86-64: LE=%s" % x86_64.is_little_endian())
print_instructions(Disassembler(x86_64), "\x55\x48\x89\xe8")
arm = TargetMachine.arm()
print("arm: LE=%s" % arm.is_little_endian())
code = [
"\xe9\x2d\x48\x00",
"\xea\x00\x00\x06",
"\xe2\x4d\xd0\x20",
"\xe2\x8d\xb0\x04",
"\xe5\x0b\x00\x20",
"\x03\x30\x22\xe0", #bad instruction to test alignment
"\x73\x20\xef\xe6", #bad instruction to test alignment
"\x18\x00\x1b\xe5",
"\x10\x30\xa0\xe3"
]
print_instructions(Disassembler(arm), "".join(map(lambda s: s[::-1], code)), 4)

View file

@ -0,0 +1,38 @@
import llvm.target
from llvmpy import api, extra
def main():
if llvm.version < (3, 4):
return 0
triple = "i386--"
print("init start")
api.llvm.InitializeAllTargets()
api.llvm.InitializeAllTargetInfos()
api.llvm.InitializeAllTargetMCs()
api.llvm.InitializeAllAsmParsers()
api.llvm.InitializeAllAsmPrinters()
api.llvm.InitializeAllDisassemblers()
print("init done\n")
tm = llvm.target.TargetMachine.x86()
if not tm:
print("error: failed to lookup target x86 \n")
return 1
print("created target machine\n")
MII = tm.instr_info
if not MII:
print("error: no instruction info for target " + triple + "\n")
return 1
print("created instr info\n")
MID = MII.get(919) #int3
print("INT3(%d): flags=0x%x, tsflags=0x%x\n" % (MID.getOpcode(), MID.getFlags(), MID.TSFlags))
return 0
exit(main())

Some files were not shown because too many files have changed in this diff Show more