Compare commits

...

544 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
Siu Kwan Lam
bf8693bb80 disable float div/mod test temporarily 2013-08-14 17:45:38 -05:00
Siu Kwan Lam
e69048ad3d add div64 and mod64 2013-08-14 17:24:34 -05:00
Siu Kwan Lam
8480d55faf add sdivmod;
improve build system;
2013-08-14 15:29:13 -05:00
majidaldo
7d1c4c18a0 high version number 2013-08-14 14:39:10 -05:00
Siu Kwan Lam
07c64779d8 begin low-level runtime implementation 2013-08-13 18:38:41 -05:00
Siu Kwan Lam
d10b182479 dislabe MCJIT tests for LLVM3.2 2013-08-13 15:27:54 -05:00
majidaldo
1be8b07ced charpath just for linux 2013-08-13 14:59:33 -05:00
majidaldo
3a289ccace add percent python 2013-08-13 14:55:42 -05:00
majidaldo
bf0253c9f9 add chrpath 2013-08-13 14:55:13 -05:00
majidaldo
d060c10096 add conda build script 2013-08-13 14:42:54 -05:00
Siu Kwan Lam
1ed3c77310 add neg nuw nsw 2013-08-12 16:16:38 -05:00
Siu Kwan Lam
cfe5e9ea92 add exact flag to IRBuilder 2013-08-12 16:11:34 -05:00
Siu Kwan Lam
1e9d37a64e add no-signed-wrap and no-unsigned-wrap flags to IRBuilder 2013-08-12 15:59:17 -05:00
Siu Kwan Lam
eb4fc653f2 ensure MCJIT ELF autoselect works 2013-08-12 14:52:16 -05:00
Siu Kwan Lam
b4d943a671 add autoselect ELF generation for MCJIT 2013-08-12 14:43:30 -05:00
Siu Kwan Lam
c20c4d776f fix exception handling for TargetMachine 2013-08-12 14:43:30 -05:00
Ilan Schnell
84a95945ea update marker header file 2013-08-06 14:17:14 -05:00
Siu Kwan Lam
0421ad8456 add dev docs 2013-08-02 12:12:47 -05:00
Siu Kwan Lam
2a25b1c2b3 fix avx detection for py3 2013-08-01 13:04:04 -05:00
Siu Kwan Lam
c4db61c7f5 add test for basic arith operators and problems for div and mod on 32bit platforms 2013-08-01 13:02:45 -05:00
Siu Kwan Lam
c0e9dedc90 add binding to dynamiclibrary namespace for multimodule linking 2013-07-31 17:50:30 -05:00
Siu Kwan Lam
319984f0e0 add MCJIT test 2013-07-31 16:57:29 -05:00
Siu Kwan Lam
56a511854a update "attribute(s)" ignorance 2013-07-31 16:43:50 -05:00
Siu Kwan Lam
625858aa6f fixes 2013-07-31 16:05:24 -05:00
Siu Kwan Lam
6d3253e4ea Add things to make MCJIT working 2013-07-31 15:44:01 -05:00
Siu Kwan Lam
4c1b9016fb binding compiles with llvm 3.3 2013-07-31 15:12:23 -05:00
Siu Kwan Lam
2338eae5f6 Fix py3 str has no buffer interface 2013-06-13 17:17:43 -05:00
Siu Kwan Lam
2415042a2a DIDescriptor does not inherit MDNode 2013-05-31 15:01:02 -05:00
Siu Kwan Lam
ad287faeb1 Fixes a werid case of refct problem 2013-05-31 14:01:57 -05:00
Ilan Schnell
69c75355f4 fix future import 2013-05-31 11:47:51 -05:00
Siu Kwan Lam
84f1b433de Use if-else instead of try-except for perf reason 2013-05-30 14:04:08 -05:00
Siu Kwan Lam
2e8944916c Add DIBuilder binding 2013-05-29 19:13:45 -05:00
Siu Kwan Lam
17ec89e457 Fix win32 build 2013-05-28 19:23:45 -05:00
Mark Florisson
6b333e84aa Use error message string from BytesIO 2013-05-27 12:22:13 +01:00
Travis E. Oliphant
009239713e Update llvm_array concepts. 2013-05-25 13:35:45 -05:00
Travis E. Oliphant
1812cff2d0 Fix import problem. 2013-05-25 13:34:14 -05:00
Siu Kwan Lam
a0eb03b239 Fix CompareInstruction.predicate 2013-05-23 11:45:15 -05:00
Siu Kwan Lam
5b2b878f24 Enable MCJIT 2013-05-22 15:17:59 -05:00
Siu Kwan Lam
edab81ed7e Fix GC problem with Module when it is GCed but re-instantiate from GlobalValue.module. 2013-05-17 14:05:40 -05:00
Siu Kwan Lam
96dc907613 Make enum integer constants prints name 2013-05-16 13:46:57 -05:00
Siu Kwan Lam
592f9c6988 Allow retrieving argument attributes 2013-05-16 13:45:59 -05:00
Siu Kwan Lam
331f71f26f Fix hashing of llvm type 2013-05-16 11:34:27 -05:00
Siu Kwan Lam
db7323771f Fix PR 2013-05-14 11:23:50 -05:00
Travis E. Oliphant
f4b320ff09 Fix a few erros. Add an array type 2013-05-14 11:12:51 -05:00
Siu Kwan Lam
08bed7dd74 Fix bug with Module.to_bitcode() (Reported by Jun Koi) 2013-05-14 10:33:49 -05:00
Travis E. Oliphant
c118427118 Don't get name field from literal structure and avoid a segfault. 2013-05-14 04:26:10 -05:00
Siu Kwan Lam
3e0dc25070 Silent capsule memory logger. 2013-05-10 10:58:51 -05:00
Siu Kwan Lam
489d8056b9 Fix error msg 2013-05-03 10:57:38 -05:00
Siu Kwan Lam
a357987597 Allow initialization of other targets.
- Remove PTX/NVPTX targets from default built and init
2013-05-03 10:45:02 -05:00
Siu Kwan Lam
b754e803ec Cleanup 2013-05-02 12:17:38 -05:00
Siu Kwan Lam
a5f6f2596f Fix ignored name arg 2013-05-02 12:16:39 -05:00
Siu Kwan Lam
238ea0e453 Merge pull request #69 from connerbryan/master
Allow Retrieval of Metadata on Instructions
2013-05-02 10:16:12 -07:00
Conner Bryan
e74b26f84c Add methods to instructions to retrieve metadata and determine if metadata exists for the instruction. 2013-04-27 09:01:32 -03:00
Siu Kwan Lam
020032b578 Update docs 2013-04-25 14:10:57 -05:00
Siu Kwan Lam
777eea719c Merge pull request #68 from davipo/master
Fix corrupted text and example in section 7.3 of docs / source / doc / kaleidoscope
2013-04-11 10:35:14 -07:00
David H Post
66346ee507 Corruption fixed in doc/llvm.core.Constant.rst (bottom of page needs work) 2013-04-11 02:36:00 -05:00
David H Post
125e65e261 Fix corrupted text and example in 7.3 Memory in LLVM 2013-04-10 15:15:19 -05:00
Siu Kwan Lam
2479c2dc22 More detail 2013-04-08 11:28:42 -05:00
Siu Kwan Lam
003768cdea Prettify docs.
(Does this trigger a NOTE section?)
2013-04-08 11:20:21 -05:00
Siu Kwan Lam
ca8fa2593a Add LLVM source link 2013-04-08 11:17:51 -05:00
Siu Kwan Lam
fab52057ba Improve docs on LLVM build instruction 2013-04-08 11:14:11 -05:00
Siu Kwan Lam
0b1abe7b26 Add isLayoutIdentical 2013-04-01 11:24:19 -05:00
Siu Kwan Lam
22b5d4695c Add mutateType 2013-04-01 11:24:09 -05:00
Siu Kwan Lam
b13aee0668 Two llvm wrapped instances are the same if they point to the same thing 2013-03-28 22:05:12 -05:00
Siu Kwan Lam
b14161c184 Add Constant to GlobalVariable cast 2013-03-25 17:23:41 -05:00
Siu Kwan Lam
6c2ed9a3ed Add some more to CallInst and StoreInst 2013-03-25 11:23:16 -05:00
Siu Kwan Lam
b6c1e7a961 Add some utils in BasicBlockUtils.h 2013-03-24 14:58:04 -05:00
Siu Kwan Lam
8800ebac66 Add downcast mapping 2013-03-24 14:58:04 -05:00
Siu Kwan Lam
1b2a9dec9a Add splitBasicBlock 2013-03-24 14:58:04 -05:00
Siu Kwan Lam
a8c78a6e2e Temporily remove setErrorStr. Current implementation does not work. 2013-03-24 14:58:04 -05:00
Siu Kwan Lam
d06a5f3eb4 Fix setOptLevel in EngineBuilder 2013-03-24 14:58:04 -05:00
Siu Kwan Lam
01c8ec1769 Merge pull request #64 from markflorisson88/master
Add some bitwise operations
2013-03-14 09:31:18 -07:00
Mark Florisson
b913b2840e Support non-inplace versions of bitwise left and right shift, and, or and xor 2013-03-14 15:21:14 +00:00
Siu Kwan Lam
edc391f292 Merge pull request #61 from hgrecco/master
Fix Python 3.2 and provides testing for travis
2013-03-13 08:35:24 -07:00
Siu Kwan Lam
ec0dda4621 Fix ownership bug 2013-03-12 21:38:00 -05:00
Hernan Grecco
bd129baa0a Reimplemented FunctionAlreadyExists and usage (Exceptions are not iterable in Python 3) 2013-03-11 16:03:43 -03:00
Ilan Schnell
6f524130d0 formatting 2013-03-05 17:21:28 -06:00
Siu Kwan Lam
e63bdd6da2 Update changelog 2013-03-05 17:17:21 -06:00
Ilan Schnell
67f4acf91f update changelog 2013-03-05 16:49:40 -06:00
Ilan Schnell
3c4769c58d test bug: only attempt to compile when cc is available 2013-03-05 16:47:31 -06:00
Hernan Grecco
b8da3c7a73 Changed imports in llpython 2013-03-05 18:11:08 -03:00
Hernan Grecco
931352d4bf Fix memory leak in Python 3.2 2013-03-05 14:31:21 -03:00
Hernan Grecco
e4996f02d7 Fix for Python 3.2 2013-03-05 00:05:31 -03:00
Hernan Grecco
372d601875 Changed test command for travis 2013-03-04 23:37:28 -03:00
Hernan Grecco
a5078d6cd7 Added testing infrastructure with travis 2013-03-03 17:31:33 -03:00
Siu Kwan Lam
f5fd7241ea Merge pull request #59 from hgrecco/master
Implemented Python 3 compatible division in IntegerValue and RealValue
2013-03-02 12:06:23 -08:00
Ilan Schnell
f8deae06dd remove excess whitespace 2013-03-02 12:56:00 -06:00
Ilan Schnell
ba759b59d0 update supported dependencies in readme 2013-03-02 12:53:31 -06:00
Hernan Grecco
bb43f4097a Implemented Python 3 compatible division in IntegerValue and RealValue 2013-03-01 19:49:29 -03:00
Siu Kwan Lam
fde153aab6 Add relocation model enums and allow TargetMachine to handle these enums 2013-02-28 18:05:30 -06:00
Siu Kwan Lam
51ff879a07 Fix incorrect use of StringRef in return value 2013-02-28 00:07:18 -06:00
Siu Kwan Lam
e89c19ee60 Ensure order of imported modules 2013-02-28 00:00:25 -06:00
Siu Kwan Lam
f172e82f10 Use .data() instead of .c_str() 2013-02-27 20:28:30 -06:00
Ilan Schnell
91d2740fbf disable lib2to3 conversion 2013-02-27 20:00:42 -06:00
Siu Kwan Lam
75b7d11fb1 Add prints to help debug. 2013-02-27 20:00:50 -06:00
Ilan Schnell
61d8105e2c add missing static library (Windows) 2013-02-27 19:26:25 -06:00
Siu Kwan Lam
d9c2ec696d Fix: "and" is not available in all compilers. 2013-02-27 19:31:26 -06:00
Siu Kwan Lam
1a34e412a5 Fix: "not" is not available on some compiler. 2013-02-27 19:27:34 -06:00
Siu Kwan Lam
4bf0fa65ef Attempt to fix build on 32-bit linux 2013-02-27 19:22:32 -06:00
Siu Kwan Lam
268dc2466a Fix build on win32 due to missing environ variable 2013-02-27 19:12:23 -06:00
Siu Kwan Lam
0cccb3dec9 Attempt to fix object code printing problem due to unicode 2013-02-27 19:03:44 -06:00
Siu Kwan Lam
9df508f7c0 Fix test with unicode problem in py3k 2013-02-27 18:43:57 -06:00
Siu Kwan Lam
cd8d622fc9 Fix mysin test for AVX support 2013-02-27 18:34:00 -06:00
Siu Kwan Lam
9f9d5a6081 More fixes to disable AVX in tests 2013-02-27 18:31:54 -06:00
Siu Kwan Lam
8073b67c96 Fix test related to AVX instructions. 2013-02-27 18:28:15 -06:00
Siu Kwan Lam
f3e7b39bc9 Update changelog 2013-02-27 16:36:21 -06:00
Siu Kwan Lam
d485c22b08 Add llvm.workaround package 2013-02-27 16:32:00 -06:00
Siu Kwan Lam
ae6dab8e50 Pass llvm version and ptx support to wrapper generator through environ 2013-02-27 14:53:49 -06:00
Siu Kwan Lam
5d83d626f6 Update setup script 2013-02-27 14:20:45 -06:00
Siu Kwan Lam
17096867f7 Merge branch 'newbinding_integrate'
Conflicts:
	llvm/core.py
2013-02-27 13:52:37 -06:00
Siu Kwan Lam
93cd20e933 Fix for python 3 2013-02-27 13:48:08 -06:00
Siu Kwan Lam
740d2595ee Replace StringIO with BytesIO 2013-02-27 13:25:19 -06:00
cuda
c3a08a446f Fix import and Makefile on Linux 2013-02-27 11:28:07 -06:00
Siu Kwan Lam
dd9ba65328 Bug fixes 2013-02-26 18:43:49 -06:00
Jon Riehl
894539681b Modified documentation configuration to search for build specific to Python version. Updated copyright. First attempt at using llvm._version to set documentation version. 2013-02-26 15:48:00 -06:00
Jon Riehl
cada51e297 Merge branch 'docs-fixes' of github.com:pfalcon/llvmpy into _pr57 2013-02-26 14:58:12 -06:00
Jon Riehl
7b1a825380 Merge pull request #56 from pfalcon/pfalcon
Typo fix - could *not* invoke llvm-config.
2013-02-26 12:50:38 -08:00
Siu Kwan Lam
c1b46e4384 Fix test 2013-02-25 10:02:49 -06:00
Siu Kwan Lam
d270f47328 Fix writing to file-like obj in python3.3 2013-02-24 13:22:30 -06:00
Paul Sokolovsky
4e87b5170a Allow Sphinx build docs with docstrings without installing module. 2013-02-24 00:44:48 +02:00
Paul Sokolovsky
d36cd1dbc7 Add docstring documentation to all llvm.core classes.
Some classes have docstrings, and lack rST docs (e.g. Module), few others
vice versa. It's unclear what is the best way to deal with this. IMHO,
docstrings should prevail, i.e. existing docs would rather be moved
to docstings. Anyway, for now just make sure that users don't miss
documentation, even if it's just list of classmembers.
2013-02-24 00:44:48 +02:00
Paul Sokolovsky
d74ff4dc2b Fill in required explicit argument for code-block. 2013-02-24 00:44:48 +02:00
Paul Sokolovsky
8086487ab7 Fix "title underline too short" warnings. 2013-02-24 00:44:48 +02:00
Paul Sokolovsky
769376b055 Sublists must have blank lines before and after. 2013-02-24 00:44:48 +02:00
Paul Sokolovsky
650a49dcab Fix import statements. 2013-02-24 00:44:48 +02:00
Paul Sokolovsky
fccf439117 Add missing titles to few docs to make sure they're rendered in docs. 2013-02-24 00:44:48 +02:00
Paul Sokolovsky
6c07747a3b Typo fix - could *not* invoke llvm-config. 2013-02-23 21:52:23 +02:00
Siu Kwan Lam
45e70333fd Adapt to python 3.3 2013-02-22 19:17:56 -06:00
Siu Kwan Lam
a275068193 Fix formatted_raw_ostream ownership error with the underlying stream. 2013-02-22 17:58:38 -06:00
Siu Kwan Lam
74982d6fef Adapt to work in python2.6 2013-02-22 17:58:11 -06:00
Siu Kwan Lam
435b92b4a4 Fix VectorType.element 2013-02-22 10:50:18 -06:00
Siu Kwan Lam
d270e885cc Add ptrtoint cast in cbuilder 2013-02-22 10:43:34 -06:00
Siu Kwan Lam
42f7219c3f Allow function.verify to raise exception on error. 2013-02-22 10:43:11 -06:00
Siu Kwan Lam
175f558ce0 Add error checking for common mistake in Builder.call 2013-02-19 10:54:31 -06:00
Siu Kwan Lam
58d410b347 Merge pull request #55 from pfalcon/pfalcon
Correct if-then-else LLVM asm example.
2013-02-19 08:13:48 -08:00
Mark Florisson
081b41db60 Allow casting pointers to ints in cbuilder 2013-02-19 15:25:10 +00:00
Paul Sokolovsky
bf484aa216 Correct if-then-else LLVM asm example.
As was present vividly breaks LLVM IR constraints on SSA and basic-blocks:
same var being assigned twice, no control transfer at the end of basic block.
Compare with the original:
http://www.mdevan.org/llvm-py/kaleidoscope/PythonLangImpl5.html
2013-02-19 08:36:52 +02:00
Ilan Schnell
20d0bf9f2a add missing dummy options 2013-02-17 16:37:57 -06:00
Siu Kwan Lam
1647580a41 LinkModules should release ownership of the other module when not preserving 2013-02-16 21:54:12 -06:00
Ilan Schnell
acd6ab685b enhance setup error messages 2013-02-16 19:20:06 -06:00
Ilan Schnell
0cc2e516ac enable new llvm-config on Windows and update changelog 2013-02-16 14:29:43 -06:00
Ilan Schnell
92c9813b3e fix library name 2013-02-16 12:50:22 -06:00
Ilan Schnell
013c7d2009 add impoved version of llvm-config for Windows 2013-02-16 10:54:25 -06:00
Ilan Schnell
ffa713e332 improve error handling 2013-02-16 01:34:51 -06:00
Ilan Schnell
a7c650a458 simplified checking for valid llvm-config command 2013-02-16 01:24:27 -06:00
Ilan Schnell
079e31c474 remove unused code 2013-02-16 01:15:37 -06:00
Ilan Schnell
7813bec6e9 add error handling 2013-02-16 01:14:06 -06:00
Ilan Schnell
26c4380c2b cleanup run_2to3 in setup.py 2013-02-16 00:14:43 -06:00
Siu Kwan Lam
bf121485ad Fix problem with caching llvm.core.Value objects. 2013-02-15 13:30:50 -06:00
Siu Kwan Lam
cb00dcc52c Fix a bug in CreatInsertValue and one in ConstantInt. 2013-02-13 18:12:45 -06:00
Siu Kwan Lam
d2dc34cdd3 Try to fix invalid dtor call 2013-02-13 17:12:54 -06:00
Siu Kwan Lam
a09394cacd Fix a lots of bugs in the newbinding to pass all the tests.
NOTE: debug info has not been implemented yet.
2013-02-13 15:52:53 -06:00
Ilan Schnell
0036d55eea remove excess whitespace 2013-02-12 11:55:04 -06:00
Ilan Schnell
b4f4483809 Py3k fixes for Windows 2013-02-12 11:24:36 -06:00
Siu Kwan Lam
a97b26415e Update old API to use the new binding.
Have not run the testsuite yet.
2013-02-11 18:15:22 -06:00
Siu Kwan Lam
2d8c6f0a41 Add PassRegistry, PassSupport, TargetRegistry, TargetOptions, and functions in Host.h
And a few other fixes
2013-02-11 18:13:38 -06:00
Siu Kwan Lam
3189be4d58 Rename newbinding directory to llvmpy. 2013-02-11 10:21:13 -06:00
Siu Kwan Lam
0681d2f37e Fixes various problem in llvm.core 2013-02-08 18:22:53 -06:00
Siu Kwan Lam
230583f42d Fix bug with empty namespace 2013-02-08 18:16:26 -06:00
Siu Kwan Lam
1fb6b05715 Finished wrapper in llvm.core 2013-02-08 18:13:45 -06:00
Siu Kwan Lam
8700bbc4f1 Fix segfault on exit 2013-02-08 18:13:16 -06:00
Siu Kwan Lam
60336d1c5f Add DynamicLibrary and InlineFunction 2013-02-08 18:13:04 -06:00
Siu Kwan Lam
c66dad7ece Implement commandline namespace 2013-02-08 18:12:36 -06:00
Siu Kwan Lam
355332d6d8 Add NVPTX components 2013-02-08 18:12:07 -06:00
Siu Kwan Lam
6eae24bcf3 Set default namespace to top-level C++ namespace. 2013-02-08 18:11:19 -06:00
Siu Kwan Lam
7c39bd1f5b Refactor to allow sub-namespace declaration 2013-02-08 16:03:29 -06:00
Siu Kwan Lam
fe383ca326 More to IRBuilder and Instruction 2013-02-07 17:40:00 -06:00
Siu Kwan Lam
b9ac22d136 More to BasicBlock 2013-02-07 15:31:54 -06:00
Siu Kwan Lam
113f30ffab Add more to Instruction 2013-02-07 15:23:31 -06:00
Siu Kwan Lam
541c119fc3 Add binding for MDNode, MDString, InlineAsm 2013-02-07 14:00:38 -06:00
Siu Kwan Lam
11cc78d780 Add binding for Intrinsics.
Add support for functions that free the resource but is not a destructor.
2013-02-07 13:27:03 -06:00
Siu Kwan Lam
aa5b969961 Expand test 2013-02-06 21:31:24 -06:00
Siu Kwan Lam
cd1fa4c4d8 Add binding for Attributes, Argument, Constants, CallingConv, GlobalValue, GlobalVariable, etc. 2013-02-06 21:31:14 -06:00
Siu Kwan Lam
39de8c4003 Expand test 2013-02-05 18:49:33 -06:00
Siu Kwan Lam
9c81fa1f63 Add more functions to GlobalValue GlobalVariable, StructType and Module 2013-02-05 18:49:13 -06:00
Siu Kwan Lam
c98a1274d9 Add Linker and Assembly (IR) Parser 2013-02-05 18:48:09 -06:00
Siu Kwan Lam
450c29e052 Swap out old llvm code 2013-02-05 15:30:43 -06:00
Siu Kwan Lam
da85049eb9 Add support to emit assembly. 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
168510222f Add Module bitcode writer/parser 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
961c5e99e1 Re-organize 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
c085bef46e Rename the tests 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
1f49bb6d7c Binding for PassManagerBuilder 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
7788346152 Improve enum implementation 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
372d6804e4 Add bindings for Pass, PassManagers, PassManagerBuilder and TargetLibraryInfo. 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
9485d03e18 binding for Target, Triple, TargetMachine 2013-02-05 13:47:35 -06:00
Siu Kwan Lam
ca0a2b9fdd binding for EngineBuilder 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
78f9c9a610 Completed binding for most of ExecutionEngine 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
25b498c8fa Improve refct and management of capsules 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
437b1e9490 All of DataLayout, IRBuilder and started on ExecutionEngine. 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
59d0dfddc7 Continue to implement IRBuilder 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
895d114730 Add CustonPythonMethod and CustonPythonStaticMethod. 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
7aa9487f2f pycapsule_new should return a None object if ptr is NULL. 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
af7962a2ca Remove IterToList, llvm_extra.h.
Add CustomMethod.
2013-02-05 13:47:34 -06:00
Siu Kwan Lam
d939728938 Forgot to push files for previous commit. 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
fa4927e1fb Start to work on IRBuilder 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
821e937837 Add binding util for iterator to list 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
d1931cc499 Fix duplicated semicolon 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
0168315076 Explicitly declare class name when registering classes 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
4b5cb100f7 Auto discover binding modules 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
c76096bbcb Add Function and some Function methods 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
3c81157ede Add downcasting 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
eba88b32ba Major refactoring 2013-02-05 13:47:34 -06:00
Siu Kwan Lam
a3da74c416 Expand Value class 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
c247cf9527 Update generator script so that order of modules does not matter. 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
e9e1f5703d Add Value, User, Constant 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
e9be14ca0e Refactor raw_svector_stream_helper 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
6a861d82e6 Implement SmallVector_Type, pycapsule_new 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
ef4c0d3be3 Rename extra.h to llvm_extra.h 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
6afab6268c Refactor mangle 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
6b88ffbaed Add custom binding to SmallVector<Type*> 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
ce103975b8 Clean up test 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
f95b691b61 Expand Module binding 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
3e89a97fdb Improve Makefile 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
bd550e3c0e Implement StaticMultiMethod 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
f88036274a Fix and rewrite the memory management for capsules. 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
089c825b0c Add cleantemp rule in Makefile 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
e39e1c7205 Add logging 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
36df29ba71 Add enum support 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
d0935fe533 Organize code layout 2013-02-05 13:47:33 -06:00
Siu Kwan Lam
5c1e8985a1 Delete empty unused Makefile 2013-02-05 13:47:32 -06:00
Siu Kwan Lam
47771d8dbc Add README 2013-02-05 13:47:32 -06:00
Siu Kwan Lam
a12c4da93d Init commit for work on new binding
This contains the foundation for the new binding as well as early work on Module and Type.
2013-02-05 13:47:32 -06:00
Siu Kwan Lam
b793e72189 Merge pull request #52 from cpcloud/master
Add GIT to llvm/_version.py
2013-02-04 09:43:31 -08:00
Phillip Cloud
c822f5f9f7 add GIT variable to _version.py 2013-02-02 20:44:27 -05:00
Ilan Schnell
0a6a11f35a add missing llvm/_version.py 2013-02-01 16:04:58 -06:00
Ilan Schnell
3f789913f5 add versioneer 2013-02-01 15:55:12 -06:00
Ilan Schnell
4fb7549243 add release date 2013-02-01 14:16:38 -06:00
Siu Kwan Lam
7bd02ef91a Update changelog about recent llpython fixes. 2013-02-01 12:06:17 -06:00
Ilan Schnell
fe37d8bae0 DOC: explain link detection in changelog 2013-01-31 20:21:15 -06:00
Ilan Schnell
5dd0948c65 cleanup 2013-01-31 17:54:20 -06:00
Ilan Schnell
1d4c431b23 minor simplification 2013-01-31 17:53:01 -06:00
Siu Kwan Lam
5d54bbb1cd Autodetect libLLVM*.so and use it if it exists; or, user can override if LLVMPY_DYNLINK. 2013-01-31 16:00:39 -06:00
Jon Riehl
b895f1fc99 Added explicit branch to otherwise unterminated basic blocks in llpython.byte_translator. 2013-01-29 16:44:03 -06:00
Jon Riehl
ffc067f852 Attempt at a fix for issue #48. 2013-01-28 20:08:09 -06:00
Siu Kwan Lam
7e7b362e47 Get llvm version as a string. It may contain 'svn' postfix. 2013-01-26 11:20:53 -06:00
Ilan Schnell
3d66981cc1 update changelog 2013-01-25 17:06:42 -06:00
Ilan Schnell
8b918f37d6 change default 2013-01-25 17:01:54 -06:00
Ilan Schnell
3772b8ba6e REL: master now 0.10.2 2013-01-25 14:05:40 -06:00
Ilan Schnell
4ab6791e78 fix version string 2013-01-25 13:57:43 -06:00
Ilan Schnell
d355facf25 DOC: formatting 2013-01-25 13:55:19 -06:00
Ilan Schnell
c0ff3615ee update changelog 2013-01-25 13:48:52 -06:00
Mark Florisson
60795adb5e Implement JUMP_IF_FALSE bytecode instruction in llpython 2013-01-24 20:10:41 -06:00
Siu Kwan Lam
3b1ae9889d Ensure python2.6 support 2013-01-24 11:58:28 -06:00
Mark Florisson
2bef762ba2 Add testcase with debuginfo and trap for gdb 2013-01-23 19:49:38 -06:00
Siu Kwan Lam
1ccda1ca5c Merge pull request #47 from llvmpy/debuginfo
Debuginfo
2013-01-23 12:09:16 -08:00
Mark Florisson
b46757f492 Accept list of values and LLVM values as debug descriptors 2013-01-22 11:21:17 -06:00
Siu Kwan Lam
2689694de9 Merge pull request #46 from cgohlke/patch-2
Detect and use NVPTX libraries on Windows
2013-01-22 08:02:19 -08:00
Siu Kwan Lam
e6ff2b46e2 Merge pull request #45 from cgohlke/patch-1
Fix ImportError on Python 3
2013-01-22 08:01:26 -08:00
Mark Florisson
3b75974731 Add basic block and instruction position descriptors 2013-01-21 20:58:32 -06:00
Mark Florisson
3fba8e4adf Support optional LLVM-level debug info 2013-01-21 19:30:46 -06:00
Mark Florisson
f6e687ae66 Allow declarative specification of debug descriptors 2013-01-21 16:54:51 -06:00
Mark Florisson
f05222caec Add file descriptors and per-module metadata caching 2013-01-21 13:04:50 -06:00
Mark Florisson
8c6384f242 Test dwarf compile unit with DW_LANG_C89 2013-01-21 12:41:49 -06:00
Mark Florisson
7c9f73ccc7 Allow debug description of compilation unit 2013-01-21 11:14:17 -06:00
Mark Florisson
93f8c70d19 Expose dwarf constants for debug info generation 2013-01-21 10:52:29 -06:00
Christoph Gohlke
5209cdb032 Detect and use NVPTX libraries on Windows 2013-01-18 13:49:15 -08:00
Christoph Gohlke
203858f417 Fix ImportError on Python 3 2013-01-18 13:40:48 -08:00
Siu Kwan Lam
d8ffc18ffc Update changelog. 2013-01-18 12:06:19 -06:00
Ilan Schnell
591d31414f update changelog 2013-01-18 11:47:43 -06:00
Ilan Schnell
50e92b4abe fix known failing tests on MacOSX for now 2013-01-18 11:44:38 -06:00
Siu Kwan Lam
0cb552a1ca Fix TestCPUFeature test; more explicit. 2013-01-18 11:38:04 -06:00
Siu Kwan Lam
6bc5b72c71 Fix: ExecutionEngine should own TargetData instance returned from ee.target_data 2013-01-18 11:38:04 -06:00
Ilan Schnell
ca1a23dff5 skip failing tests on 32-bit Windows 2013-01-18 11:26:37 -06:00
Siu Kwan Lam
206d512c10 Fix LLVMLinkModules for LLVM-3.1 2013-01-17 19:06:06 -06:00
Siu Kwan Lam
7451f6ca4a Add tests for double-precision intrinsics 2013-01-17 17:12:11 -06:00
Siu Kwan Lam
343efc6379 C-wrapper includes file and lineno when unknown exceptino is encountered 2013-01-17 16:44:01 -06:00
Siu Kwan Lam
1daec8ff63 Add simpler intrinsic tests for debug llvm-3.2 on windows 32-bit 2013-01-17 16:43:27 -06:00
Siu Kwan Lam
c7320e84de Add tests for cpu features support 2013-01-17 16:08:47 -06:00
Siu Kwan Lam
d0fd53fda3 Revert "Workaround for LLVM-3.2 invalid reporting of host triple on darwin9.8"
This reverts commit ea315a58cb.
2013-01-17 14:22:27 -06:00
Siu Kwan Lam
ea315a58cb Workaround for LLVM-3.2 invalid reporting of host triple on darwin9.8 2013-01-17 14:13:03 -06:00
Siu Kwan Lam
2d3889111b Cleanup usage of long long; replace with PY_LONG_LONG.
For address, use PyLong_AsVoidPtr.
2013-01-17 13:16:53 -06:00
Ilan Schnell
0f3dfb85d4 simplified avx detection on Linux 2013-01-16 19:56:42 -06:00
Siu Kwan Lam
00b3449443 Try PY_LONG_LONG replacement for unsigned long long 2013-01-16 19:36:26 -06:00
Siu Kwan Lam
5d4759bd55 Workaround for AVX on old kernels. 2013-01-16 18:18:50 -06:00
Siu Kwan Lam
bdac4a809d Add lazy compilation option.
Unify execution engine creation through engine-builder internally.
2013-01-16 17:52:33 -06:00
Siu Kwan Lam
91a10e6a8e Fix TargetMachine ownership in EngineBuilder. 2013-01-14 20:34:29 -06:00
Siu Kwan Lam
8b58488bbd Add GEP inbounds 2013-01-14 10:30:58 -06:00
Mark Florisson
9874d8048d Run 2to3 for python 3 install 2013-01-13 17:00:17 -06:00
Ilan Schnell
995d14e1d0 fix (Windows) issue #42 2013-01-11 11:20:24 -06:00
Siu Kwan Lam
207254fe50 Make note about preverifier bug in LLVM that *.verify() will abort upon error 2013-01-10 17:13:06 -06:00
Siu Kwan Lam
31fbc3ae64 Module.link_in should not delete other.ptr and should prevent the other.ptr from being destroyed 2013-01-10 17:10:40 -06:00
Siu Kwan Lam
a0a777e1aa llvm_cbuilder: global string should use LINKONCE_ODR 2013-01-10 16:58:50 -06:00
Siu Kwan Lam
ee62b0c96c Fix Module.link_in so it reports error and destory the other module when preserve=False 2013-01-10 16:52:25 -06:00
Siu Kwan Lam
f731332360 Builder.branch will check if the basicblock has terminator when running in debug mode. 2013-01-10 16:43:14 -06:00
Siu Kwan Lam
9dadd9f1df Use 'L' format for unsigned long long to be consistent 2013-01-10 09:44:00 -06:00
Ilan Schnell
cc8b16b9ca next version will be 0.10.0 2013-01-08 16:12:26 -06:00
Siu Kwan Lam
64880e7d69 Fix invalid use of long for address. Use unsigned long long for cross-platform 64-bit int. 2013-01-08 16:09:51 -06:00
Jon Riehl
ee2d86e86f Merge pull request #41 from valtron/master
Updated names of passes in Kaleidoscope tutorial
2013-01-08 13:47:17 -08:00
Siu Kwan Lam
371e940c83 Reverse finalizer 2013-01-07 16:39:41 -06:00
Siu Kwan Lam
5fc5ba2e66 Fix free/delete mismatch in LLVMGetNativeCodeFromModule 2013-01-07 16:39:32 -06:00
Siu Kwan Lam
8ca0e79bd0 Fix free/delete mismatch in LLVMGetBitcodeFromModule 2013-01-07 15:14:46 -06:00
Siu Kwan Lam
af6b0d7823 Suppress warning for missing loop-vectorizer feature if user is not enabling it. 2013-01-07 14:00:11 -06:00
valtron
e02cd0a977 Updated names of passes 2013-01-05 02:46:52 -07:00
Siu Kwan Lam
9571aefbe0 Add ExecutionEngine.add_global_mapping 2013-01-04 15:15:41 -06:00
Siu Kwan Lam
457cd24986 Add test for ExecutionEngine.get_pointer_to_global 2013-01-04 14:25:39 -06:00
Siu Kwan Lam
5b6a1d75f8 Fix breakage of LLVM 3.1.
Add LLVM version number in llvmpy.
2013-01-04 14:24:26 -06:00
Bradley M. Froehle
dd32ce56b1 Wrap LLVMGetPointerToGlobal & add ExecutionEngine.get_pointer_to_global. 2013-01-04 10:21:55 -06:00
Siu Kwan Lam
f01da12e16 Add CodeModel 2013-01-03 15:37:11 -06:00
Siu Kwan Lam
bc20661343 Introduce finalizer module to manage finalization of C resources. 2013-01-03 14:44:32 -06:00
Siu Kwan Lam
e8c7fcfd32 Add optional TargetMachine param to EngineBuilder.create. 2013-01-03 11:47:24 -06:00
Siu Kwan Lam
a6ed8d55f8 Add clone method to TargetData. 2013-01-03 10:17:23 -06:00
Siu Kwan Lam
3fbce4c0f9 Fix exception syntax for Py3 2013-01-03 09:56:42 -06:00
Siu Kwan Lam
e2ec14bbb9 Add test to verify new pass APIs and loop-vectorizer. 2013-01-02 17:42:28 -06:00
Siu Kwan Lam
7f9c91e2aa Add simpler API for building pass-managers given a TargetMachine. 2013-01-02 17:42:28 -06:00
Siu Kwan Lam
3b399f9d8b Adding target specific passes. 2013-01-02 17:42:28 -06:00
Siu Kwan Lam
bcc467b2b5 Add auto detect PTX/NVPTX support and disable them in the C-extension. 2013-01-02 17:42:28 -06:00
Siu Kwan Lam
ff92a05858 Begin to expose Pass class. 2013-01-02 17:42:28 -06:00
Mark Florisson
b22c023301 Make cbuilder optimizations optional 2013-01-02 19:17:12 +00:00
Siu Kwan Lam
ff51552838 Update README for LLVM 3.2. 2012-12-31 10:45:21 -06:00
Siu Kwan Lam
10e83f306f Add PassManagerBuilder.loop_vectorize property 2012-12-31 10:45:21 -06:00
Siu Kwan Lam
edcef56f05 Merge pull request #37 from ehiggs/master
Issue #34 Pypi package does not include "tools" directory
2012-12-31 08:44:50 -08:00
Ewan Higgs
d397f4c497 Issue #34 - Add tools to MANIFEST.in 2012-12-30 21:08:38 +00:00
Siu Kwan Lam
5da98dac49 Add macros to enable support for llvm3.1. 2012-12-27 17:10:12 -06:00
xol
f3e9eb0b05 Fix for llvm 3.2 - TargetData -> DataLayout 2012-12-27 14:06:47 -06:00
Siu Kwan Lam
e2e6221f25 Fix last commit 2012-12-17 14:24:05 -06:00
Jon Riehl
f2e65c6c54 Proposed fix for issue #31. 2012-12-17 14:14:31 -06:00
Siu Kwan Lam
436a12db03 Add Stephen's llvm-cbuilder examples. 2012-12-17 14:12:48 -06:00
Siu Kwan Lam
970ba92720 Merge pull request #35 from meteogrid/master
Added Instruction.erase_from_parent wrapper
2012-12-17 12:12:32 -08:00
Siu Kwan Lam
d12b145bee Merge pull request #33 from jszakmeister/fix-bugs-in-tutorial
Fix bugs in tutorial
2012-12-17 12:07:21 -08:00
Alberto Valverde
5c5f3015f7 exposed LLVMInstructionEraseFromParent 2012-12-14 23:54:49 +01:00
Siu Kwan Lam
03e54f2c12 Expose preserve flag for Module.link_in 2012-12-04 13:50:16 -06:00
John Szakmeister
b3a04c4a34 Move the closing curly branch to line up with the rest of the code. 2012-11-30 04:45:30 -05:00
John Szakmeister
78f81fec73 Fix the id matching in the kaleidoscope tutorial. 2012-11-30 04:04:14 -05:00
John Szakmeister
7c7c198953 Mark a block of code as text, and remove the python-isms.
The kaleidoscope language being implemented looks similar to Python, but
is not the same.
2012-11-30 04:01:04 -05:00
John Szakmeister
f9376bf2d0 Fix an error in the full listing for the kaleidoscope lexer. 2012-11-30 03:29:40 -05:00
Siu Kwan Lam
d491d91dd2 Add TBAA Builder 2012-11-29 12:36:54 -06:00
Maggie Mari
425e382368 Fixed broken link in llvmpy docs. 2012-11-12 10:51:42 -06:00
Maggie Mari
52d7b8b6f5 Adding reference pages to toctree. 2012-11-12 10:51:42 -06:00
Travis E. Oliphant
7adecd8f5d master is now 0.9.1 2012-11-11 01:43:47 -06:00
Travis E. Oliphant
6f234dbf2c Revert to 0.9 2012-11-11 01:42:21 -06:00
Travis E. Oliphant
0691800c84 Add comma 2012-11-11 01:39:58 -06:00
Travis E. Oliphant
469349be07 Fix author. 2012-11-11 01:37:33 -06:00
Ilan Schnell
f6a974a767 REL: master is now 0.9.1 2012-11-10 19:39:23 -06:00
Travis E. Oliphant
a2c5e861c4 Change author and email and version 2012-11-10 19:01:32 -06:00
Travis E. Oliphant
994c1432a6 Add documentation for llvm_cbuilder 2012-11-10 18:56:24 -06:00
Travis E. Oliphant
a52db30af8 Add llvm_cbuilder tests 2012-11-10 18:56:02 -06:00
Travis E. Oliphant
d795000176 Merge branch 'llvm_cbuilder_tests' 2012-11-10 18:44:42 -06:00
Travis E. Oliphant
4bc9f00d95 Collect the directory to move 2012-11-10 18:43:19 -06:00
Travis E. Oliphant
23a2d3a446 Collect the directory to move 2012-11-10 18:43:10 -06:00
Jon Riehl
22d8e0048b Moved and updated LLPython (formerly LLNumba) documentation from Numba repository. 2012-11-08 15:51:14 -06:00
Mark Florisson
5b9885fc40 Allow creating a cbuilder struct from a minitype struct type 2012-11-08 12:15:00 +00:00
Travis E. Oliphant
ac791e5c38 Change name to llpython and remove llnumba references. 2012-11-07 12:14:01 -06:00
Travis E. Oliphant
affc4c016f Merge branch 'llpython' 2012-11-07 12:09:55 -06:00
Travis E. Oliphant
bbc7a4ddf0 Ready for numba/llnumba -> llvmpy/llpython 2012-11-07 12:08:32 -06:00
Travis E. Oliphant
119ef50689 Add llvm_cbuilder to list of packages. 2012-11-07 11:03:50 -06:00
Travis E. Oliphant
23e3f43d44 Merge branch 'llvm_cbuilder' 2012-11-07 11:02:50 -06:00
Travis E. Oliphant
004313fcbd Collected the data to move llvm_cbuilder 2012-11-07 11:01:40 -06:00
Siu Kwan Lam
2685d60e38 Fix CDefinition.
Note: This fixes a horrible undeterminisitic bug for parallel vectorize.
2012-11-05 14:59:43 -06:00
Siu Kwan Lam
2799e9f452 Test for InlineAsm 2012-11-01 11:42:30 -05:00
Siu Kwan Lam
b9d05bb6fe Can now modify called_function of CallOrInvokeInstruction 2012-11-01 11:42:10 -05:00
Siu Kwan Lam
507ff73061 Add InlineAsm 2012-10-31 16:41:10 -05:00
Mark Florisson
bd377de198 Fix cbuilder CDefinition specialization design and magic 2012-10-29 14:16:13 +00:00
Mark Wiebe
6133b643d8 Fix PTX lib detection logic on windows 2012-10-26 15:33:42 -07:00
Mark Florisson
87a44e3117 Get array slicing and expressions compiling 2012-10-26 20:40:06 +01:00
Siu Kwan Lam
daa62d9f78 Add address-space control to global-variable 2012-10-26 14:08:33 -05:00
Jon Riehl
6d19096438 Prototyped non-Python string slicing implementation. 2012-10-24 17:14:32 -05:00
Jon Riehl
c8e44702cb Got AST translation working for numba.tests.test_cstring.
Modified AST type inference to use Python API for string to number conversion (was using atol/atof, which suppress Python errors).
Tweaked numba.functions.CStringSlice2, and added numba.functions.CStringSlice2Len (currently unused).
Added support for PyInt_FromString and PyFloat_FromString in numba.functions.
Modified llnumba slicing code to type properly on 64-bit systems.
Changed string slice support in numba.transforms to use Python slicing by default.
2012-10-23 14:35:07 -05:00
Jon Riehl
2b2407b82f Merge branch 'master' of github.com:jriehl/numba
Conflicts:
	numba/functions.py
2012-10-19 17:12:13 -05:00
Jon Riehl
47cd581ca5 Working on using InternalFunction instances from ast_translate. Fixed bug in AST modulo implementation. 2012-10-19 17:10:46 -05:00
Siu Kwan Lam
d781e83bd1 can now clone modules 2012-10-19 16:18:24 -05:00
Jon Riehl
23a5dd0dff Merge branch 'master' of github.com:jriehl/numba 2012-10-19 11:44:01 -05:00
Jon Riehl
aab2c39fc9 Working on using InternalFunction instances from ast_translate. Fixed bug in AST modulo implementation. 2012-10-19 11:43:45 -05:00
Jon Riehl
9b1b444000 Working on using InternalFunction instances from ast_translate. Fixed bug in AST modulo implementation. 2012-10-18 16:01:32 -05:00
Jon Riehl
b7fba64e53 Merge branch 'master' of github.com:jriehl/numba 2012-10-18 11:33:38 -05:00
Jon Riehl
80437fc077 Got nobitey unit test working using llnumba for wrapper generation. 2012-10-18 10:23:44 -05:00
Jon Riehl
01d0ff4eba Added manual linkage to nobitey when target module isn't the same as the source module. 2012-10-18 10:23:44 -05:00
Siu Kwan Lam
e0d1b94053 Add NamedMetaData 2012-10-16 16:35:20 -05:00
Jon Riehl
ba309ea6c5 Got nobitey unit test working using llnumba for wrapper generation. 2012-10-16 12:36:47 -05:00
Jon Riehl
40b84ffd74 Added manual linkage to nobitey when target module isn't the same as the source module. 2012-10-16 10:18:13 -05:00
Jon Riehl
fe1ba06698 Adding docstrings for some of llnumba. 2012-10-15 15:21:53 -05:00
Jon Riehl
99c9a1f204 Still trying to get whitespace in ast_type_inference merge-worthy. 2012-10-15 15:07:16 -05:00
Jon Riehl
3f0a4a74f7 Moved llnumba out of sandbox. 2012-10-15 15:02:55 -05:00
Mark Florisson
6041f2df84 Add 'numba/minivect/' from commit 'e0f32ee9d15e6f913a8bdcd9214783be2758b7d8'
git-subtree-dir: numba/minivect
git-subtree-mainline: 1b07f0bbc9cf0898320e1ec303a1906c9c91130d
git-subtree-split: e0f32ee9d15e6f913a8bdcd9214783be2758b7d8
2012-10-13 16:38:19 +01:00
Jon Riehl
6d8fbafb54 Moved llnumba out of sandbox. 2012-10-11 15:46:56 -05:00
Siu Kwan Lam
d1fefe5a69 Fix doc about Python3.2 testing 2012-10-10 10:58:02 -05:00
Thomas Kluyver
87ffb437d8 Fix a couple of tests for Python 3 2012-10-10 10:49:48 -05:00
Thomas Kluyver
aba3e208d2 Improve bytes/unicode distinction for reading modules from bitcode & assembly 2012-10-10 10:49:48 -05:00
Thomas Kluyver
1c15a9784b Fix minor problems under Python 3 from running the tests 2012-10-10 10:49:48 -05:00
Siu Kwan Lam
bba30621f1 Allow to_native_object & to_native_assembly to receive an optional fileobj to write to. 2012-10-10 10:47:56 -05:00
Siu Kwan Lam
e42dfd9abb Improve PTX support discovery and make it optional. 2012-10-04 12:59:48 -05:00
Travis E. Oliphant
cdd26cde58 New version number and update README 2012-10-03 21:42:11 -05:00
Mark Florisson
f0ad108e2c Fix some stuff
support casting int <-> pointers in llvm_cbuilder
    assign ndarray type to fake PyArrays
2012-09-27 16:30:14 +01:00
Travis E. Oliphant
ab0ce0d49a Update numbapro to handle latest numba changes. 2012-09-27 01:11:35 -05:00
Mark Florisson
20a896b206 Start on array expressions 2012-09-24 12:21:12 +01:00
Siu Kwan Lam
b9584e1071 Fix assertion error in python source due to invalid lineno increment inside llvm_cbuilder.translator. 2012-09-21 19:37:10 -07:00
Mark Florisson
bc03c9a8b7 Fix GC head for debug builds for gufunc fake arrays 2012-09-21 22:46:48 +02:00
Mark Florisson
10b3f188cc Some more progress towards CUDA gufuncs 2012-09-21 22:46:48 +02:00
Mark Florisson
cd9c5e7c79 Use meta to decompile python functions into ASTs 2012-09-21 22:39:48 +02:00
Mark Florisson
b0137289b9 Use meta to decompile python functions into ASTs 2012-09-21 22:39:48 +02:00
Siu Kwan Lam
8a159b35f0 refactor llvm_cbuilder 2012-09-07 17:53:22 -07:00
Siu Kwan Lam
af44641bb9 add noalias attribute to parameters 2012-09-07 17:53:22 -07:00
Siu Kwan Lam
1e4633c44d add invariant variable 2012-09-07 17:53:22 -07:00
Siu Kwan Lam
b941ae5f1f Use non-temporal hint at memory store for vectorizer.
Note: LLVM optimizer is smart enough to not use NT write if it is slower.
2012-09-07 17:53:22 -07:00
Siu Kwan Lam
8505256510 Inline ufunc kernel in vectorize. (Better io throughput) 2012-09-04 10:08:07 -07:00
Mark Wiebe
428f4ad530 Fix debug print test, make it account for some system printf variations 2012-08-31 12:18:26 -07:00
Mark Wiebe
a6e7bcb015 Skip tests using pthreads on Windows
Note: They were causing hard exits of Python, not exceptions, this
      is something that will have to be fixed in the future
2012-08-31 10:53:37 -07:00
Mark Wiebe
e7b1af043f Use the function's calling convention when doing the call in cbuilder 2012-08-30 18:13:03 -07:00
Siu Kwan Lam
a046685b2c Add calling_conv.
Set win32 api to use CC_X86_STDCALL. (need testing)
2012-08-30 12:23:53 -07:00
bryan
fb30295e62 rename to prevent import collision 2012-08-30 13:31:50 -05:00
Siu Kwan Lam
d390960657 Add llvm_cbuilder translate features:
* handle while loop
 * handle for loop
 * handle immediate values

Todo: handle "break" and "continue"
2012-08-23 11:43:24 -05:00
Siu Kwan Lam
eeda441dac Added stream vectorize. 2012-08-22 13:23:52 -05:00
Siu Kwan Lam
4d773ed5ed Add alignment control to vector_load/store.
E.g: align=1 for universal alignment. default to aligned.
2012-08-21 18:32:44 -05:00
Siu Kwan Lam
2218f1d49e Improve vector load store.
Changes make llvm emit parallel ld/st instead of scalar ld/st.
2012-08-21 17:26:12 -05:00
Siu Kwan Lam
5513a34e80 Add some doc and cleanup 2012-08-21 14:17:14 -05:00
Siu Kwan Lam
5319fb8c98 Add initial vector support 2012-08-21 12:33:21 -05:00
Siu Kwan Lam
562e3c1e46 Fix: if-else branch should terminate automatically. Insert unreachable to if.end block if necessary. 2012-08-21 12:30:35 -05:00
Siu Kwan Lam
d55bb95d4d Add translator to convert python code to llvm cbuilder construct 2012-08-21 12:30:35 -05:00
Siu Kwan Lam
f9d7195413 reorganize 2012-08-13 15:53:09 -07:00
Siu Kwan Lam
1009daf3fa Add notebook: parallel_vectorize 2012-08-11 14:55:35 -07:00
Siu Kwan Lam
c1d3044c77 Fix parallel_vectorize_from_func:
* use signed integer;
* use multiprocessing.cpu_count() to determine # of threads.
2012-08-11 14:06:13 -07:00
Siu Kwan Lam
7f84ecbe3b Add notebook: llvm_cbuilder quick tour 2012-08-10 17:58:54 -07:00
Siu Kwan Lam
9ccc6782c7 Add doc for parallel_vectorize_from_func.
Add FunctionAlreadyExists exception.
2012-08-08 17:46:20 -07:00
Siu Kwan Lam
c6d5538ead Add usecase tests 2012-08-08 17:33:34 -07:00
Siu Kwan Lam
753f74d485 Fix tests 2012-08-08 17:33:24 -07:00
Siu Kwan Lam
b23d7909fb add parallel_vectorize_from_func 2012-08-08 17:33:00 -07:00
Siu Kwan Lam
e35b8ca636 Add some float casting 2012-08-08 17:32:39 -07:00
Siu Kwan Lam
3b0aeea6f2 change CDeclare to CFuncRef 2012-08-08 16:27:57 -07:00
Siu Kwan Lam
3009d8468f more cleanup and doc 2012-08-08 15:29:16 -07:00
Siu Kwan Lam
68e2359ad2 cleanup and doc 2012-08-08 15:17:31 -07:00
Siu Kwan Lam
8b45094e20 Add test that uses function pointer. 2012-08-07 16:56:28 -07:00
Siu Kwan Lam
2acc070984 Refactor.
Modify the way CDefinition is specialized.
2012-08-07 16:55:33 -07:00
Siu Kwan Lam
01054c726f Add specialize() for cleaner specialization of CDefinition. 2012-08-06 20:25:36 -07:00
Siu Kwan Lam
b5893d4ebb Add test to use numpy.fromfunc.
Depends on numpy branch "ufunc-from-function-pointer" in git://github.com/jayvius/numpy.git
2012-08-06 17:02:04 -07:00
Siu Kwan Lam
150f497ed0 Add specializable parallel ufunc.
Update test.
Some fixes.
2012-08-06 15:33:36 -07:00
Siu Kwan Lam
fef9c2efbf Add CBuilder.depends to automatically insert depending function. 2012-08-06 14:46:27 -07:00
Siu Kwan Lam
c43b27356b Fix 2012-08-06 14:23:43 -07:00
Siu Kwan Lam
1594e5456a Got test_parallel_vectorize working. 2012-08-06 11:35:03 -07:00
Siu Kwan Lam
891daa1164 Added test implementation of parallel-vectorize (incomplete).
Various fix.
2012-08-05 21:35:02 -07:00
Siu Kwan Lam
0654e00ab1 Add printf() and friends.
Disable logging in old tests.
2012-08-04 19:13:35 -07:00
Siu Kwan Lam
673ada6a4e Fix and add tests. 2012-08-04 15:18:41 -07:00
Siu Kwan Lam
b45c768cc5 Fix 2012-08-04 15:14:09 -07:00
Siu Kwan Lam
184e4ea1a1 Add API for structure 2012-08-03 22:30:54 -07:00
Siu Kwan Lam
f1e10e849f Fix __div__ for py3.
Add test for nested-loops.
2012-08-03 17:02:01 -07:00
Siu Kwan Lam
aebb9857eb Drop volatile option in atomic ops.
Add volatile option to store.
2012-08-03 16:31:23 -07:00
Siu Kwan Lam
8381b25f66 Add atomic ops 2012-08-03 16:26:46 -07:00
Siu Kwan Lam
7238fecc7f add build & test instruction to README 2012-08-02 14:20:02 -07:00
Siu Kwan Lam
6981206096 Add TODO and README files. 2012-08-01 20:14:34 -07:00
Siu Kwan Lam
066480fbb8 Add parallel-vectorize prototype.
Add llvm_cbuilder.
2012-08-01 19:02:58 -07:00
298 changed files with 24581 additions and 11933 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
llvm/_version.py export-subst

3
.gitignore vendored
View file

@ -2,4 +2,7 @@
build
_build
*.pyc
*.so
/llvm/_intrinsic_ids.py
llvm_
newbinding/api/*

24
.travis.yml Normal file
View file

@ -0,0 +1,24 @@
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
branches:
only:
- master
install:
- wget "http://repo.continuum.io/pkgs/free/linux-64/llvm-3.2-0.tar.bz2"
- tar -xjf llvm-3.2-0.tar.bz2
- PATH+=":`pwd`/bin"
- export LD_LIBRARY_PATH="`pwd`/lib"
- export LLVM_CONFIG_PATH="`pwd`/bin/llvm-config"
- $LLVM_CONFIG_PATH --cflags # test llvm-config
- export LLVMPY_DYNLINK=1
- python setup.py install -q
script: cd ~; python -c "import sys;import llvm;sys.exit(0 if llvm.test() == 0 else 1)"

107
CHANGELOG
View file

@ -1,14 +1,88 @@
2014-04-28 0.12.5:
---------------------
* Fixes memory leaks (#92)
* Fixes tarball (#99)
0.7, in progress:
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
* fix Python 3 division (Hernan Grecco) (Issue #59)
* add relocation enums and add reloc argument for TargetMachine
2013-03-01 0.11.0:
--------------------
* fix Python 3 support on Windows
* New llvm binding
2013-02-01 0.10.2:
--------------------
* change default to link dynamically to LLVM use:
$ export LLVMPY_DYNLINK=0 # link statically
$ export LLVMPY_DYNLINK=1 # link dynamically
$ unset LLVMPY_DYNLINK # tries to link dynamically if LLVM shared
# objects are found and statically otherwise
* fix llpython for Python 2.6 support
2013-01-25 0.10.1:
--------------------
* fix support for Python 2.6
2013-01-18 0.10.0:
--------------------
* Add LLVM 3.2 support.
* New TargetData class.
* Fixed windows issue (Issue #42).
* Add ExecutionEngine.add_global_mapping and .get_pointer_to_global.
* Improved TargetMachine class and added code-model constants (CM_*).
* Added llvm.passes.build_pass_managers as a simpler way to build PassManagers.
in progress, 0.7:
-----------------
* Add llvm.core.Argument.alignment property.
* Migrate to LLVM 2.8.
* Fix ffi link issue on darwin (Albert Mietus) (Issue #29).
* LLVM tutorial ported (Max Shawabkeh) (Issue #33).
0.6, 31-Aug-2010:
2010-08-31 0.6:
-----------------
* Add and remove function attributes (Krzysztof Goj) (Issue #21).
* Wrap fadd,fsub,fmul (Aaron S Lav) (Issue #31).
* Migrate to LLVM 2.7.
@ -27,16 +101,16 @@
* Migrate to LLVM 2.5.
0.5, 22-Nov-2008:
2008-11-22 0.5:
-----------------
* Added vicmp, vfcmp instructions and constant expressions.
* Builds on FreeBSD.
* Updated documentation.
* Migrate to LLVM 2.4.
0.4, 21-Nov-2008:
2008-11-21 0.4:
-----------------
* Code cleanup, added license headers.
* Added llvm.core.load_library_permanently() (Issue #12).
* Fix comparison using != (Issue #11).
@ -45,8 +119,8 @@
* Added viewCFG methods to Function (Paulo Silva).
0.3, 8-Sep-2008:
2008-09-08 0.3:
-----------------
* Passes added.
* Assembly support: create modules from .ll files.
* Various bug fixes.
@ -58,13 +132,13 @@
* Updated documentation.
0.2.1, 18-Jun-2008:
2008-06-28 0.2.1:
-------------------
* Build cleanly with LLVM 2.3 and 2.3svn.
0.2, 15-Jun-2008:
2008-06-15 0.2:
-----------------
* Independent package, need not be unpacked into llvm/bindings.
* Fixed ownership issues with Module/ModuleProvider.
* Modules, values and types can be stringified, to get their LLVM
@ -79,7 +153,6 @@
* Lots of cleanup.
0.1, 10-May-2008:
* Initial release.
2008-05-10 0.1:
-----------------
* Initial release

View file

@ -1,4 +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

@ -10,27 +10,55 @@ http://www.llvmpy.org
Versions
--------
This package has only been tested with LLVM 3.1, and Python 2.7, (not Python 3.x).
This package has been tested with LLVM 3.2, Python 2.6, 2.7 and 3.3.
Other Python versions may work.
Quickstart
----------
1. Get 3.1 version of LLVM, build it. Make sure ``--enable-pic`` is passed to
LLVM's ``configure``.
1. Get and extract LLVM 3.2 source tarball from
`llvm.org <http://llvm.org/releases/download.html#3.2>`_. Then, ``cd`` into
the extracted directory.
2. Get llvm-py and install it::
2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``.
**Note**: Without the ``--enable-optimized`` flag, debug build will be
selected. Unless you are developing LLVM or llvmpy, it is recommended
that the flag is used to reduce build time and binary size.
**Note**: Use prefix to select the installation path. It is recommended
to separate your custom build from the default system package. Please
replace ``LLVM_INSTALL_PATH`` with your own path.
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::
$ git clone git@github.com:llvmpy/llvmpy.git
$ cd llvmpy
$ python setup.py install
$ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install
Run the tests::
$ python -c "import llvm; llvm.test()"
3. See documentation at 'http://www.llvmpy.org/pages.html' and examples
5. See documentation at 'http://www.llvmpy.org' and examples
under 'test'.
Common Build Problems
---------------------
1. If llvmpy cannot be imported due to "undefined symbol:
_ZTIN4llvm24PassRegistrationListenerE", it is because RTTI is not enabled
when building LLVM. "_ZTIN4llvm24PassRegistrationListenerE" is the typeinfo
of PassRegistrationListener class.
LICENSE
-------

144
README_LLVM_CBUILDER.md Normal file
View file

@ -0,0 +1,144 @@
LLVM CBuilder
=============
A few short examples:
(TODO: add more later)
```python
from llvm.core import *
from llvm_cbuilder import *
import llvm_cbuilder.shortnames as C
```
```python
class Square(CDefinition):
_name_ = 'square'
_retty_ = C.double
_argtys_ = [ ('x', C.double) ]
def body(self, x):
y = x * x
self.ret(y)
```
```python
m = Module.new('my_module')
llvm_square = Square()(m)
print(m)
```
```
; ModuleID = 'my_module'
define double @square(double %x) {
decl:
%0 = fmul double %x, %x
ret double %0
}
```
```python
class IsPrime(CDefinition):
_name_ = 'isprime'
_retty_ = C.int
_argtys_ = [('x', C.int)]
def body(self, x):
false = zero = self.constant(C.int, 0)
true = one = self.constant(C.int, 1)
two = self.constant(C.int, 2)
with self.ifelse( x <= two ) as ifelse:
with ifelse.then():
self.ret(true)
with self.ifelse( (x % two) == zero ) as ifelse:
with ifelse.then():
self.ret(false)
idx = self.var(C.int, 3, name='idx')
with self.loop() as loop:
with loop.condition() as setcond:
setcond( idx < x )
with loop.body():
with self.ifelse( (x % idx ) == zero ) as ifelse:
with ifelse.then():
self.ret(false)
idx += two
self.ret(true)
```
```
define i32 @isprime(i32 %x) {
decl:
%0 = icmp sle i32 %x, 2
br i1 %0, label %if.then, label %if.end
if.then: ; preds = %loop.body, %loop.cond, %if.end, %decl
%merge = phi i32 [ 1, %decl ], [ 0, %if.end ], [ 1, %loop.cond ], [ 0, %loop.body ]
ret i32 %merge
if.end: ; preds = %decl
%1 = srem i32 %x, 2
%2 = icmp eq i32 %1, 0
br i1 %2, label %if.then, label %if.end4
if.end4: ; preds = %if.end
br label %loop.cond
loop.cond: ; preds = %if.end7, %if.end4
%idx.0 = phi i32 [ 3, %if.end4 ], [ %6, %if.end7 ]
%3 = icmp slt i32 %idx.0, %x
br i1 %3, label %loop.body, label %if.then
loop.body: ; preds = %loop.cond
%4 = srem i32 %x, %idx.0
%5 = icmp eq i32 %4, 0
br i1 %5, label %if.then, label %if.end7
if.end7: ; preds = %loop.body
%6 = add i32 %idx.0, 2
br label %loop.cond
}
; ModuleID = 'my_module'
define i32 @isprime(i32 %x) {
decl:
%0 = icmp sle i32 %x, 2
br i1 %0, label %if.then, label %if.end
if.then: ; preds = %loop.body, %loop.cond, %if.end, %decl
%merge = phi i32 [ 1, %decl ], [ 0, %if.end ], [ 1, %loop.cond ], [ 0, %loop.body ]
ret i32 %merge
if.end: ; preds = %decl
%1 = srem i32 %x, 2
%2 = icmp eq i32 %1, 0
br i1 %2, label %if.then, label %if.end4
if.end4: ; preds = %if.end
br label %loop.cond
loop.cond: ; preds = %if.end7, %if.end4
%idx.0 = phi i32 [ 3, %if.end4 ], [ %6, %if.end7 ]
%3 = icmp slt i32 %idx.0, %x
br i1 %3, label %loop.body, label %if.then
loop.body: ; preds = %loop.cond
%4 = srem i32 %x, %idx.0
%5 = icmp eq i32 %4, 0
br i1 %5, label %if.then, label %if.end7
if.end7: ; preds = %loop.body
%6 = add i32 %idx.0, 2
br label %loop.cond
}
```

View file

@ -0,0 +1,6 @@
set LLVMPY_DYNLINK=0
set INCLUDE=%LIBRARY_INC%
set LIBPATH=%LIBRARY_LIB%
set LIB=%LIBRARY_LIB%
%PYTHON% setup.py install
if errorlevel 1 exit 1

View file

@ -0,0 +1,13 @@
#!/bin/bash
if [[ (`uname` == Linux) && (`uname -m` != armv6l) ]]
then
export CC=gcc
#gcc44
export CXX=g++
#g++44
fi
export LLVMPY_DYNLINK=$DISTRO_BUILD
$PYTHON setup.py install

View file

@ -0,0 +1,28 @@
package:
name: llvmpy
version: 99.9.9
source:
git_url: git@github.com:llvmpy/llvmpy.git
# git_tag: 0.12.0
requirements:
build:
- llvm
- python
#- chrpath [linux]
run:
- llvm [unix]
- python
test:
imports:
- llvm
- llvmpy
- llvmpy._api
- llvmpy._capsule
- llpython
- llvm_array
- llvm_cbuilder

View file

@ -0,0 +1,22 @@
import sys
import platform
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()
print('target.triple=%r' % target.triple)
if sys.platform == 'darwin':
s = {'64bit': 'x86_64', '32bit': 'x86'}[platform.architecture()[0]]
assert target.triple.startswith(s + '-apple-darwin')
assert llvm.test(verbosity=2, run_isolated=False) == 0
#check_intrinsics.main()
print('llvm.__version__: %s' % llvm.__version__)
#assert llvm.__version__ == '0.12.0'

View file

@ -30,7 +30,7 @@ from subprocess import Popen, PIPE, CalledProcessError, check_call
pages_dir = 'gh-pages'
html_dir = '_build/html'
pdf_dir = '_build/latex'
pages_repo = 'git@github.com:llvmpy/llvmpy-doc.git'
pages_repo = 'https://github.com/llvmpy/llvmpy-doc.git'
#-----------------------------------------------------------------------------
# Functions

View file

@ -11,12 +11,23 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
import sys, os, glob
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
#sys.path.insert(0, os.path.abspath('../..'))
# Support sphinx.ext.autodoc to extract docstrings from modules without installing
# complete package.
# The python modules depend on _core, so we must build entire package first though.
built_lib = glob.glob('../../build/lib.*-%d.%d/' % sys.version_info[:2])
if not built_lib:
sys.stderr.write("WARNING: To build complete documentation you must build "
"package first\n")
else:
# lib dir has platform suffix
sys.path.insert(0, os.path.abspath(built_lib[0]))
# -- General configuration -----------------------------------------------------
@ -25,7 +36,7 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.mathjax']
extensions = ['sphinx.ext.mathjax', 'sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -41,16 +52,22 @@ master_doc = 'index'
# General information about the project.
project = u'llvmpy'
copyright = u'2012, Mahadevan R (2008-2010), Continuum Analytics (2012)'
copyright = u'2013, Mahadevan R (2008-2010), Continuum Analytics (2012-2013)'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
try:
import llvm
version_strs = llvm.__version__.split('.')
# The short X.Y version.
version = '0.8'
version = '.'.join(version_strs[:2])
# The full version, including alpha/beta/rc tags.
release = '0.8.2'
release = '%s.%s' % (version, '-'.join(version_strs[2].split('-')[:2]))
except ImportError:
version = 'unknown-version'
release = 'unknown-release'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

9
docs/source/doc/core.rst Normal file
View file

@ -0,0 +1,9 @@
********************************
llvm.core
********************************
.. toctree::
:titlesonly:
:glob:
llvm.core.*

View file

@ -1,5 +1,5 @@
A More Complicated Function
====================
===========================
.. code-block:: python

View file

@ -26,7 +26,7 @@ Both LLVM and llvmpy are distributed under (different) permissive open
source licenses. llvmpy uses the `new BSD
license <http://opensource.org/licenses/bsd-license.php>`_. More
information is available
`here <https://github.com/numba/llvmpy/blob/master/LICENSE>`_.
`here <https://github.com/llvmpy/llvmpy/blob/master/LICENSE>`_.
Platforms
---------
@ -38,12 +38,11 @@ supported, for a variety of reasons.
Versions
--------
llvmpy 0.8.2 requires version 3.1 of LLVM. It may not work with
llvmpy 0.11.2 uses LLVM 3.2 (or at least 3.1). It may not work with
previous versions.
llvmpy has been built and tested with Python 2.7. It should work with
earlier versions. It has not been tried with Python 3.x (patches
welcome).
llvmpy has been built and tested with Python 2.7 and 3.2. It should work with
earlier versions.
Installation
@ -66,22 +65,6 @@ It does not matter which compiler LLVM itself was built with (``g++``,
``llvm-g++`` or any other); llvmpy can be built with any compiler. It
has been tried only with gcc/g++ though.
LLVM and ``--enable-pic``
-------------------------
The result of an LLVM build is a set of static libraries and object
files. The llvmpy contains an extension package that is built into a
shared object (\_core.so) which links to these static libraries and
object files. It is therefore required that the LLVM libraries and
object files be built with the ``-fPIC`` option (generate position
independent code). Be sure to use the ``--enable-pic`` option while
configuring LLVM (default is no PIC), like this:
.. code-block:: bash
$ ~/llvm ./configure --enable-pic --enable-optimized
llvm-config
-----------
@ -99,13 +82,34 @@ is different from that of 'root', so even if ``llvm-config`` is in your
Steps
-----
Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to
LLVM's 'configure'.
1. Get and extract LLVM 3.2 source tarball from
`llvm.org <http://llvm.org/releases/download.html#3.2>`_. Then, ``cd`` into
the extracted directory.
Get llvmpy and install it:
2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``.
**Note**: Without the ``--enable-optimized`` flag, debug build will be
selected. Unless you are developing LLVM or llvmpy, it is recommended
that the flag is used to reduce build time and binary size.
.. code-block:: bash
**Note**: Use prefix to select the installation path. It is recommended
to separate your custom build from the default system package. Please
replace ``LLVM_INSTALL_PATH`` with your own path.
$ git clone git@github.com:numba/llvmpy.git
$ cd llvmpy $ python setup.py install
3. Run ``REQUIRES_RTTI=1 make`` to build.
**Note**: With LLVM 3.2, the default build configuration has C++ RTTI
disabled. However, llvmpy requires RTTI.
4. Get llvm-py and install it::
$ git clone git@github.com:llvmpy/llvmpy.git
$ cd llvmpy
$ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install
Run the tests::
$ python -c "import llvm; llvm.test()"
5. See documentation at 'http://www.llvmpy.org' and examples
under 'test'.

View file

@ -6,7 +6,7 @@ Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
Shawabkeh <http://max99x.com>`_
Introduction
=========
============
Welcome to the "Implementing a language with LLVM" tutorial. This
tutorial runs through the implementation of a simple language, showing
@ -115,13 +115,13 @@ following simple example computes `Fibonacci
numbers <http://en.wikipedia.org/wiki/Fibonacci_number>`_:
.. code-block:: python
.. code-block:: text
# Compute the x'th fibonacci number.
def fib(x):
if x < 3:
def fib(x)
if x < 3
return 1
else:
else
return fib(x-1)+fib(x-2)
# This expression will compute the 40th number.
@ -226,7 +226,7 @@ the line.
# Regular expressions that tokens and comments of our language.
REGEX_NUMBER = re.compile('[0-9]+(?:.[0-9]+)?')
REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]\ *')
REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]*')
REGEX_COMMENT = re.compile('#.*')

View file

@ -217,7 +217,8 @@ Kaleidoscope looks something like this:
br i1 %ifcond, label %then, label %else
then: ; preds = %entry
%calltmp1 = call double @bar()
%calltmp = call double @foo()
br label %ifcont
else: ; preds = %entry
%calltmp1 = call double @bar()

View file

@ -133,11 +133,11 @@ instruction <http://www.llvm.org/docs/LangRef.html#i_alloca>`_:
define i32 @example() {
entry:
%X = alloca i32 ; type of %X is i32 *.
%X = alloca i32 ; type of %X is i32*
...
%tmp = load i32* %X ; load the stack value %X from the stack.
%tmp2 = add i32 %tmp, 1 ; increment it store i32 %tmp2,
i32* %X ; store it back
%tmp = load i32* %X ; load the stack value %X from the stack
%tmp2 = add i32 %tmp, 1 ; increment it
store i32 %tmp2, i32* %X ; store it back
...
@ -295,7 +295,7 @@ variables is a useful thing regardless of whether you will be mutating
them. Here's a motivating example that shows how we could use these:
.. code-block::
.. code-block:: none
# Define ':' for sequencing: as a low-precedence operator that ignores operands
# and just returns the RHS.
@ -352,7 +352,7 @@ function that ensures that the allocas are created in the entry block of
the function:
.. code-block::
.. code-block:: python
# Creates an alloca instruction in the entry block of the function. This is used
# for mutable variables.
@ -475,7 +475,7 @@ It is interesting to see what the code looks like before and after the
mem2reg optimization runs. For example, this is the before/after code
for our recursive fib function. Before the optimization:
.. code-block::
.. code-block:: llvm
define double @fib(double %x) {
entry:
@ -515,7 +515,7 @@ still just make the PHI.
Here is the code after the mem2reg pass runs:
.. code-block::
.. code-block:: llvm
define double @fib(double %x) {
entry:
@ -651,7 +651,7 @@ Now that we have an assignment operator, we can mutate loop variables
and arguments. For example, we can now run code like this:
.. code-block::
.. code-block:: none
# Function to print a double.
extern printd(x)

View file

@ -1,6 +1,6 @@
*************************************************
***************************************************
Chapter 8: Conclusion and other useful LLVM tidbits
*************************************************
***************************************************
Written by Chris Lattner
@ -106,7 +106,7 @@ generating LLVM IR. These are some of the more subtle things that may not be obv
but are very useful if you want to take advantage of LLVM's capabilities.
Properties of the LLVM IR
========================
=========================
We have a couple common questions about code in the LLVM IR form - let's
just get these out of the way right now, shall we?
@ -164,7 +164,7 @@ This can make sense for specialized domains such as an in-kernel language.
--------------
Safety Guarantees
----------------
-----------------
Many of the languages above are also "safe" languages: it is
impossible for a program written in Java to corrupt its address space and
@ -236,7 +236,7 @@ you desire in your front-end, on the language-specific AST.
--------------
Tips and Tricks
==============
===============
There is a variety of useful tips and tricks that you come to
know after working on/with LLVM that aren't obvious at first glance.

View file

@ -0,0 +1,10 @@
LLPython Articles
=================
.. toctree::
:titlesonly:
:maxdepth: 1
intro_llpython.rst
nobitey_dev.rst
ctmp_in_llpython.rst

View file

@ -0,0 +1,5 @@
Compile-time Metaprogramming in LLPython
========================================
In this article, we discuss how LLPython supports compile-time
metaprogramming.

View file

@ -0,0 +1,9 @@
LLPython Documentation
======================
.. toctree::
:titlesonly:
:maxdepth: 2
articles.rst
reference.rst

View file

@ -0,0 +1,46 @@
====================
Introducing LLPython
====================
In this article, we introduce the llpython package. The primary goal
of the llpython package is to provide a Python dialect/subset that
maps directly to LLVM code. LLPython differs from its originating
LLVM translator, Numba, in the following aspects:
* LLPython code is not intended to work in Python if not translated
and wrapped.
* The LLPython translator only uses LLVM types.
* LLPython is explicitly typed, and does not support type inference.
LLPython does not support implicit casts, all casts must be explicit.
* LLPython supports code that directly calls the C API, the Python C
API, and the llvm.core.Builder methods.
Additionally, we designed the sub-package to have the following
engineering properties:
* Usable from Python 2.7, and 3.X. At the time of writing, we plan
to support Python 2.6.
* Clean from Numba dependencies (other than llvmpy), and can be used
as a standalone code generator without a full Numba installation.
* Provides a series of Python bytecode passes that can be easily
used by other projects.
LLPython Origins
================
We developed LLPython with the initial goal of simplifying writing
LLVM code.
LLPython Internals
==================
In this section, we describe the various passes performed by the
LLPython translator.
Conclusions
===========
LLPython is neat.

View file

@ -0,0 +1,6 @@
=====================
llpython.byte_control
=====================
.. automodule:: llpython.byte_control
:members:

View file

@ -0,0 +1,6 @@
==================
llpython.byte_flow
==================
.. automodule:: llpython.byte_flow
:members:

View file

@ -0,0 +1,6 @@
========================
llpython.byte_translator
========================
.. automodule:: llpython.byte_translator
:members:

View file

@ -0,0 +1,6 @@
=========================
llpython.bytecode_visitor
=========================
.. automodule:: llpython.bytecode_visitor
:members:

View file

@ -0,0 +1,6 @@
=================
llpython.bytetype
=================
.. automodule:: llpython.bytetype
:members:

View file

@ -0,0 +1,6 @@
=====================
llpython.control_flow
=====================
.. automodule:: llpython.control_flow
:members:

View file

@ -0,0 +1,6 @@
=============================
llpython.gen_bytecode_visitor
=============================
.. automodule:: llpython.gen_bytecode_visitor
:members:

View file

@ -0,0 +1,6 @@
================
llpython.nobitey
================
.. automodule:: llpython.nobitey
:members:

View file

@ -0,0 +1,6 @@
====================
llpython.opcode_util
====================
.. automodule:: llpython.opcode_util
:members:

View file

@ -0,0 +1,6 @@
=====================
llpython.phi_injector
=====================
.. automodule:: llpython.phi_injector
:members:

View file

@ -0,0 +1,6 @@
==================
llpython.pyaddfunc
==================
.. automodule:: llpython.pyaddfunc
:members:

View file

@ -0,0 +1,6 @@
========
llpython
========
.. automodule:: llpython
:members:

View file

@ -0,0 +1,5 @@
nobitey: Using ctypes and llvmpy to Bypass ctypes
=================================================
In this article, we show how nobitey uses llvmpy to eliminate the
ctypes call overhead.

View file

@ -0,0 +1,21 @@
LLPython Module Reference
=========================
Contents:
.. toctree::
:titlesonly:
:maxdepth: 2
llpython.rst
llpython.bytecode_visitor.rst
llpython.byte_control.rst
llpython.byte_flow.rst
llpython.byte_translator.rst
llpython.bytetype.rst
llpython.control_flow.rst
llpython.gen_bytecode_visitor.rst
llpython.nobitey.rst
llpython.opcode_util.rst
llpython.phi_injector.rst
llpython.pyaddfunc.rst

View file

@ -56,3 +56,10 @@ Add an attribute ``attr`` to the argument, from the set listed above.
~~~~~~~~~~~~~~~~~~~~~~~~~~
Remove the attribute ``attr`` of the argument.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Argument
:members:
:undoc-members:

View file

@ -28,3 +28,10 @@ A ``Type`` object representing the type of the element of the array.
[read-only]
The number of elements in the array.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.ArrayType
:members:
:undoc-members:

View file

@ -42,3 +42,10 @@ The parent function of this basicblock.
~~~~~~~~~~~~~~~~
A list of instructions in this basicblock.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.BasicBlock
:members:
:undoc-members:

View file

@ -409,3 +409,10 @@ positioned.
~~~~~~~~~
Deprecated. Same as ``basic_block``
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Builder
:members:
:undoc-members:

View file

@ -4,6 +4,9 @@
| title: Constant (llvm.core) |
+-------------------------------+
llvm.core.Constant
==================
``Constant``-s represents constants that appear within the code. The
values of such objects are known at creation time. Constants can be
created from Python constants. A constant expression is also a constant
@ -23,14 +26,15 @@ some examples:
tr = Type.float()
r1 = Constant.real(tr, "3.141592") # create from a string r2 =
Constant.real(tr, 1.61803399) # create from a Python float {%
endhighlight %}
r1 = Constant.real(tr, "3.141592") # create from a string
r2 = Constant.real(tr, 1.61803399) # create from a Python float
# llvm.core.Constant
- This will become a table of contents (this text will be scraped).
{:toc}
Static factory methods
----------------------
@ -351,3 +355,9 @@ some examples:
assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray)
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Constant
:members:
:undoc-members:

View file

@ -149,3 +149,10 @@ function bodies.
Verifies the function. See `LLVM
docs <http://llvm.org/docs/Passes.html#verify>`_.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Function
:members:
:undoc-members:

View file

@ -46,3 +46,10 @@ the function. Used like this:
Type.int(), Type.int() ] ) for arg in func_type.args: assert arg.kind
== TYPE_INTEGER assert arg == Type.int() assert func_type.arg_count
== len(func_type.args)
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.FunctionType
:members:
:undoc-members:

View file

@ -95,3 +95,9 @@ A power-of-2 integer indicating the boundary to align to.
The module object to which this global belongs to.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.GlobalValue
:members:
:undoc-members:

View file

@ -4,6 +4,9 @@
| title: GlobalVariable (llvm.core) |
+-------------------------------------+
llvm.core.GlobalVariable
========================
Global variables (``llvm.core.GlobalVariable``) are subclasses of
`llvm.core.GlobalValue <llvm.core.GlobalValue.html>`_ and represent
module-level variables. These can have optional initializers and can be
@ -37,3 +40,10 @@ class, or by using the static method ``GlobalVariable.new``.
# list all global variables in a module
for gv in module_obj.global_variables: print gv.name, "of type",
gv.type
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.GlobalVariable
:members:
:undoc-members:

View file

@ -240,3 +240,10 @@ Properties
The predicate of the compare instruction, one of the ``ICMP_*`` or
``FCMP_*`` constants.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Instruction
:members:
:undoc-members:

View file

@ -21,3 +21,10 @@ Properties
[read-only]
The width of the integer type, in number of bits.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.IntegerType
:members:
:undoc-members:

View file

@ -4,16 +4,26 @@
| title: Module (llvm.core) |
+-----------------------------+
llvm.core.Module
================
Modules are top-level container objects. You need to create a module
object first, before you can add global variables, aliases or functions.
Modules are created using the static method ``Module.new``:
.. code-block:: python
#!/usr/bin/env python
from llvm import \* from llvm.core import \*
from llvm import *
from llvm.core import *
# create a module
my_module = Module.new('my_module')
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Module
:members:
:undoc-members:

View file

@ -29,3 +29,10 @@ The address space of the pointer.
A `Type <llvm.core.Type.html>`_ object representing the type of the
value pointed to.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.PointerType
:members:
:undoc-members:

View file

@ -0,0 +1,8 @@
llvm.core.StructType
====================
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.StructType
:members:
:undoc-members:

View file

@ -126,3 +126,10 @@ Example:
assert Type.int().kind == TYPE_INTEGER assert
Type.void().kind == TYPE_VOID
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Type
:members:
:undoc-members:

View file

@ -37,3 +37,10 @@ The list of operands (values, of type
The number of operands that this value referes to. Same as
``len(uses.operands)`` but faster if you just want the count.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.User
:members:
:undoc-members:

View file

@ -63,3 +63,10 @@ representation.
``Value`` objects can be compared for equality. Internally, this
converts both arguments into their LLVM assembly representations and
compares the resultant strings.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.Value
:members:
:undoc-members:

View file

@ -29,3 +29,10 @@ element of the vector.
[read-only]
The number of elements in the vector.
Automatically Generated Documentation
-------------------------------------
.. autoclass:: llvm.core.VectorType
:members:
:undoc-members:

View file

@ -0,0 +1,12 @@
llvm_cbuilder
=============
llvm_cbuilder is a set of Python-contexts you can use to write C-like
constructs in Python which generates llvmpy code directly.
Similar to llpython it allows you to build llvm IR without using the
llvmpy interface directly.
Look in the llvm_cbuilder tests directory for examples of use.

View file

@ -28,6 +28,7 @@ follow these steps:
- add a *basic block* to the function
- using a helper object called an *instruction builder*, add two
instructions into the basic block:
- an instruction to add the two
arguments and store the result into a temporary variable
- a return

View file

@ -0,0 +1,9 @@
********************************
llvm.core
********************************
.. toctree::
:titlesonly:
:glob:
llvm.core.*

View file

@ -0,0 +1,9 @@
********************************
llvm.ee
********************************
.. toctree::
:titlesonly:
:glob:
llvm.ee.*

View file

@ -0,0 +1,9 @@
********************************
llvm.passes
********************************
.. toctree::
:titlesonly:
:glob:
llvm.passes.*

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:
@ -13,11 +13,16 @@ Contents:
:maxdepth: 2
doc/userguide.rst
doc/llvm_cbuilder.rst
doc/llpython/index.rst
doc/examples.rst
doc/llvmcore.rst
doc/llvmee.rst
doc/llvmpasses.rst
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()

0
llpython/__init__.py Normal file
View file

125
llpython/byte_control.py Normal file
View file

@ -0,0 +1,125 @@
# ______________________________________________________________________
from __future__ import absolute_import
import opcode
from . import opcode_util
import pprint
from .bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin
from .control_flow import ControlFlowGraph
# ______________________________________________________________________
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
'''Visitor responsible for traversing a bytecode basic block map and
building a control flow graph (CFG).
The primary purpose of this transformation is to create a CFG,
which is used by later transformers for dataflow analysis.
'''
def visit (self, flow, nargs = 0, *args, **kws):
'''Given a bytecode flow, and an optional number of arguments,
return a :py:class:`llpython.control_flow.ControlFlowGraph`
instance describing the full control flow of the bytecode
flow.'''
self.nargs = nargs
ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws)
del self.nargs
return ret_val
def enter_blocks (self, blocks):
super(ControlFlowBuilder, self).enter_blocks(blocks)
self.blocks = blocks
self.block_list = list(blocks.keys())
self.block_list.sort()
self.cfg = ControlFlowGraph()
self.loop_stack = []
for block in self.block_list:
self.cfg.add_block(block, blocks[block])
def exit_blocks (self, blocks):
super(ControlFlowBuilder, self).exit_blocks(blocks)
assert self.blocks == blocks
self.cfg.compute_dataflow()
self.cfg.update_for_ssa()
ret_val = self.cfg
del self.loop_stack
del self.cfg
del self.block_list
del self.blocks
return ret_val
def enter_block (self, block):
self.block = block
assert block in self.cfg.blocks
if block == 0:
for local_index in range(self.nargs):
self.op_STORE_FAST(0, opcode.opmap['STORE_FAST'], local_index)
return True
def _get_next_block (self, block):
return self.block_list[self.block_list.index(block) + 1]
def exit_block (self, block):
assert block == self.block
del self.block
i, op, arg = self.blocks[block][-1]
opname = opcode.opname[op]
if op in opcode.hasjabs:
self.cfg.add_edge(block, arg)
elif op in opcode.hasjrel:
self.cfg.add_edge(block, i + arg + 3)
elif opname == 'BREAK_LOOP':
loop_i, _, loop_arg = self.loop_stack[-1]
self.cfg.add_edge(block, loop_i + loop_arg + 3)
elif opname != 'RETURN_VALUE':
self.cfg.add_edge(block, self._get_next_block(block))
if op in opcode_util.hascbranch:
self.cfg.add_edge(block, self._get_next_block(block))
def op_LOAD_FAST (self, i, op, arg, *args, **kws):
self.cfg.blocks_reads[self.block].add(arg)
return super(ControlFlowBuilder, self).op_LOAD_FAST(i, op, arg, *args,
**kws)
def op_STORE_FAST (self, i, op, arg, *args, **kws):
self.cfg.writes_local(self.block, i, arg)
return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args,
**kws)
def op_SETUP_LOOP (self, i, op, arg, *args, **kws):
self.loop_stack.append((i, op, arg))
return super(ControlFlowBuilder, self).op_SETUP_LOOP(i, op, arg, *args,
**kws)
def op_POP_BLOCK (self, i, op, arg, *args, **kws):
self.loop_stack.pop()
return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args,
**kws)
# ______________________________________________________________________
def build_cfg (func):
'''Given a Python function, create a bytecode flow, visit the flow
object, and return a control flow graph.'''
co_obj = opcode_util.get_code_object(func)
return ControlFlowBuilder().visit(opcode_util.build_basic_blocks(co_obj),
co_obj.co_argcount)
# ______________________________________________________________________
# Main (self-test) routine
def main (*args, **kws):
from tests import llfuncs
if not args:
args = ('doslice',)
for arg in args:
build_cfg(getattr(llfuncs, arg)).pprint()
# ______________________________________________________________________
if __name__ == "__main__":
import sys
main(*sys.argv[1:])
# ______________________________________________________________________
# End of byte_control.py

266
llpython/byte_flow.py Normal file
View file

@ -0,0 +1,266 @@
# ______________________________________________________________________
from __future__ import absolute_import
import dis
import opcode
from .bytecode_visitor import BasicBlockVisitor
from . import opcode_util
# ______________________________________________________________________
class BytecodeFlowBuilder (BasicBlockVisitor):
'''Transforms a CFG into a bytecode "flow tree".
The flow tree is a Python dictionary, described loosely by the
following set of productions:
* `flow_tree` ``:=`` ``{`` `blocks` ``*`` ``}``
* `blocks` ``:=`` `block_index` ``:`` ``[`` `bytecode_tree` ``*`` ``]``
* `bytecode_tree` ``:=`` ``(`` `opcode_index` ``,`` `opcode` ``,``
`opname` ``,`` `arg` ``,`` ``[`` `bytecode_tree` ``*`` ``]`` ``)``
The primary purpose of this transformation is to simulate the
value stack, removing it and any stack-specific opcodes.'''
def __init__ (self, *args, **kws):
super(BytecodeFlowBuilder, self).__init__(*args, **kws)
om_items = opcode_util.OPCODE_MAP.items()
self.opmap = dict((opcode.opmap[opname], (opname, pops, pushes, stmt))
for opname, (pops, pushes, stmt) in om_items
if opname in opcode.opmap)
def _visit_op (self, i, op, arg, opname, pops, pushes, appends):
assert pops is not None, ('%s not well defined in opcode_util.'
'OPCODE_MAP' % opname)
if pops:
if pops < 0:
pops = arg - pops - 1
assert pops <= len(self.stack), ("Stack underflow at instruction "
"%d (%s)!" % (i, opname))
stk_args = self.stack[-pops:]
del self.stack[-pops:]
else:
stk_args = []
ret_val = (i, op, opname, arg, stk_args)
if pushes:
self.stack.append(ret_val)
if appends:
self.block.append(ret_val)
return ret_val
def _op (self, i, op, arg):
opname, pops, pushes, appends = self.opmap[op]
return self._visit_op(i, op, arg, opname, pops, pushes, appends)
def visit_cfg (self, cfg):
self.cfg = cfg
ret_val = self.visit(cfg.blocks)
del self.cfg
return ret_val
def enter_blocks (self, blocks):
labels = list(blocks.keys())
labels.sort()
self.blocks = dict((index, [])
for index in labels)
self.loop_stack = []
self.stacks = {}
def exit_blocks (self, blocks):
ret_val = self.blocks
del self.stacks
del self.loop_stack
del self.blocks
return ret_val
def enter_block (self, block):
self.block_no = block
self.block = self.blocks[block]
in_blocks = self.cfg.blocks_in[block]
if len(in_blocks) == 0:
self.stack = []
else:
pred_stack = None
for pred in in_blocks:
if pred in self.stacks:
pred_stack = self.stacks[pred]
break
if pred_stack is not None:
self.stack = pred_stack[:]
else:
raise NotImplementedError()
def exit_block (self, block):
assert self.block_no == block
self.stacks[block] = self.stack
del self.stack
del self.block
del self.block_no
op_BINARY_ADD = _op
op_BINARY_AND = _op
op_BINARY_DIVIDE = _op
op_BINARY_FLOOR_DIVIDE = _op
op_BINARY_LSHIFT = _op
op_BINARY_MODULO = _op
op_BINARY_MULTIPLY = _op
op_BINARY_OR = _op
op_BINARY_POWER = _op
op_BINARY_RSHIFT = _op
op_BINARY_SUBSCR = _op
op_BINARY_SUBTRACT = _op
op_BINARY_TRUE_DIVIDE = _op
op_BINARY_XOR = _op
def op_BREAK_LOOP (self, i, op, arg):
loop_i, _, loop_arg = self.loop_stack[-1]
assert arg is None
return self._op(i, op, loop_i + loop_arg + 3)
#op_BUILD_CLASS = _op
op_BUILD_LIST = _op
op_BUILD_MAP = _op
op_BUILD_SLICE = _op
op_BUILD_TUPLE = _op
op_CALL_FUNCTION = _op
op_CALL_FUNCTION_KW = _op
op_CALL_FUNCTION_VAR = _op
op_CALL_FUNCTION_VAR_KW = _op
op_COMPARE_OP = _op
#op_CONTINUE_LOOP = _op
op_DELETE_ATTR = _op
op_DELETE_FAST = _op
op_DELETE_GLOBAL = _op
op_DELETE_NAME = _op
op_DELETE_SLICE = _op
op_DELETE_SUBSCR = _op
def op_DUP_TOP (self, i, op, arg):
self.stack.append(self.stack[-1])
def op_DUP_TOPX (self, i, op, arg):
self.stack += self.stack[-arg:]
#op_END_FINALLY = _op
op_EXEC_STMT = _op
#op_EXTENDED_ARG = _op
op_FOR_ITER = _op
op_GET_ITER = _op
op_IMPORT_FROM = _op
op_IMPORT_NAME = _op
op_IMPORT_STAR = _op
op_INPLACE_ADD = _op
op_INPLACE_AND = _op
op_INPLACE_DIVIDE = _op
op_INPLACE_FLOOR_DIVIDE = _op
op_INPLACE_LSHIFT = _op
op_INPLACE_MODULO = _op
op_INPLACE_MULTIPLY = _op
op_INPLACE_OR = _op
op_INPLACE_POWER = _op
op_INPLACE_RSHIFT = _op
op_INPLACE_SUBTRACT = _op
op_INPLACE_TRUE_DIVIDE = _op
op_INPLACE_XOR = _op
op_JUMP_ABSOLUTE = _op
op_JUMP_FORWARD = _op
def op_JUMP_IF_FALSE (self, i, op, arg):
opname, _, _, _ = self.opmap[op]
ret_val = (i, op, opname, arg, [self.stack[-1]])
self.block.append(ret_val)
return ret_val
op_JUMP_IF_TRUE = op_JUMP_IF_FALSE
op_LIST_APPEND = _op
op_LOAD_ATTR = _op
op_LOAD_CLOSURE = _op
op_LOAD_CONST = _op
op_LOAD_DEREF = _op
op_LOAD_FAST = _op
op_LOAD_GLOBAL = _op
op_LOAD_LOCALS = _op
op_LOAD_NAME = _op
op_MAKE_CLOSURE = _op
op_MAKE_FUNCTION = _op
op_NOP = _op
def op_POP_BLOCK (self, i, op, arg):
self.loop_stack.pop()
return self._op(i, op, arg)
op_POP_JUMP_IF_FALSE = _op
op_POP_JUMP_IF_TRUE = _op
op_POP_TOP = _op
op_PRINT_EXPR = _op
op_PRINT_ITEM = _op
op_PRINT_ITEM_TO = _op
op_PRINT_NEWLINE = _op
op_PRINT_NEWLINE_TO = _op
op_RAISE_VARARGS = _op
op_RETURN_VALUE = _op
def op_ROT_FOUR (self, i, op, arg):
self.stack[-4:] = (self.stack[-1], self.stack[-4], self.stack[-3],
self.stack[-2])
def op_ROT_THREE (self, i, op, arg):
self.stack[-3:] = (self.stack[-1], self.stack[-3], self.stack[-2])
def op_ROT_TWO (self, i, op, arg):
self.stack[-2:] = (self.stack[-1], self.stack[-2])
#op_SETUP_EXCEPT = _op
#op_SETUP_FINALLY = _op
def op_SETUP_LOOP (self, i, op, arg):
self.loop_stack.append((i, op, arg))
self.block.append((i, op, self.opnames[op], arg, []))
op_SLICE = _op
#op_STOP_CODE = _op
op_STORE_ATTR = _op
op_STORE_DEREF = _op
op_STORE_FAST = _op
op_STORE_GLOBAL = _op
op_STORE_MAP = _op
op_STORE_NAME = _op
op_STORE_SLICE = _op
op_STORE_SUBSCR = _op
op_UNARY_CONVERT = _op
op_UNARY_INVERT = _op
op_UNARY_NEGATIVE = _op
op_UNARY_NOT = _op
op_UNARY_POSITIVE = _op
op_UNPACK_SEQUENCE = _op
#op_WITH_CLEANUP = _op
op_YIELD_VALUE = _op
# ______________________________________________________________________
def build_flow (func):
'''Given a Python function, return a bytecode flow tree for that
function.'''
import byte_control
cfg = byte_control.build_cfg(func)
return BytecodeFlowBuilder().visit_cfg(cfg)
# ______________________________________________________________________
# Main (self-test) routine
def main (*args):
import pprint
from tests import llfuncs
if not args:
args = ('doslice',)
for arg in args:
pprint.pprint(build_flow(getattr(llfuncs, arg)))
# ______________________________________________________________________
if __name__ == '__main__':
import sys
main(*sys.argv[1:])
# ______________________________________________________________________
# End of byte_flow.py

612
llpython/byte_translator.py Normal file
View file

@ -0,0 +1,612 @@
# ______________________________________________________________________
'''Defines a bytecode based LLVM translator for llpython code.
'''
# ______________________________________________________________________
# Module imports
from __future__ import absolute_import
import opcode
import types
import logging
import llvm.core as lc
from . import opcode_util
from . import bytetype
from .bytecode_visitor import BytecodeFlowVisitor
from .byte_flow import BytecodeFlowBuilder
from .byte_control import ControlFlowBuilder
from .phi_injector import PhiInjector, synthetic_opname
# ______________________________________________________________________
# Module data
logger = logging.getLogger(__name__)
# XXX Stolen from numba.translate:
_compare_mapping_float = {'>':lc.FCMP_OGT,
'<':lc.FCMP_OLT,
'==':lc.FCMP_OEQ,
'>=':lc.FCMP_OGE,
'<=':lc.FCMP_OLE,
'!=':lc.FCMP_ONE}
_compare_mapping_sint = {'>':lc.ICMP_SGT,
'<':lc.ICMP_SLT,
'==':lc.ICMP_EQ,
'>=':lc.ICMP_SGE,
'<=':lc.ICMP_SLE,
'!=':lc.ICMP_NE}
# XXX Stolen from numba.llvm_types:
class LLVMCaster (object):
def build_pointer_cast(_, builder, lval1, lty2):
return builder.bitcast(lval1, lty2)
def build_int_cast(_, builder, lval1, lty2, unsigned = False):
width1 = lval1.type.width
width2 = lty2.width
ret_val = lval1
if width2 > width1:
if unsigned:
ret_val = builder.zext(lval1, lty2)
else:
ret_val = builder.sext(lval1, lty2)
elif width2 < width1:
ret_val = builder.trunc(lval1, lty2)
return ret_val
def build_float_ext(_, builder, lval1, lty2):
return builder.fpext(lval1, lty2)
def build_float_trunc(_, builder, lval1, lty2):
return builder.fptrunc(lval1, lty2)
def build_int_to_float_cast(_, builder, lval1, lty2, unsigned = False):
ret_val = None
if unsigned:
ret_val = builder.uitofp(lval1, lty2)
else:
ret_val = builder.sitofp(lval1, lty2)
return ret_val
def build_int_to_ptr_cast(_, builder, lval1, lty2):
return builder.inttoptr(lval1, lty2)
def build_float_to_int_cast(_, builder, lval1, lty2, unsigned = False):
ret_val = None
if unsigned:
ret_val = builder.fptoui(lval1, lty2)
else:
ret_val = builder.fptosi(lval1, lty2)
return ret_val
CAST_MAP = {
lc.TYPE_POINTER : build_pointer_cast,
lc.TYPE_INTEGER: build_int_cast,
(lc.TYPE_FLOAT, lc.TYPE_DOUBLE) : build_float_ext,
(lc.TYPE_DOUBLE, lc.TYPE_FLOAT) : build_float_trunc,
(lc.TYPE_INTEGER, lc.TYPE_FLOAT) : build_int_to_float_cast,
(lc.TYPE_INTEGER, lc.TYPE_DOUBLE) : build_int_to_float_cast,
(lc.TYPE_INTEGER, lc.TYPE_POINTER) : build_int_to_ptr_cast,
(lc.TYPE_FLOAT, lc.TYPE_INTEGER) : build_float_to_int_cast,
(lc.TYPE_DOUBLE, lc.TYPE_INTEGER) : build_float_to_int_cast,
}
@classmethod
def build_cast(cls, builder, lval1, lty2, *args, **kws):
ret_val = lval1
lty1 = lval1.type
lkind1 = lty1.kind
lkind2 = lty2.kind
if lkind1 == lkind2:
if lkind1 in cls.CAST_MAP:
ret_val = cls.CAST_MAP[lkind1](cls, builder, lval1, lty2,
*args, **kws)
else:
raise NotImplementedError(lkind1)
else:
map_index = (lkind1, lkind2)
if map_index in cls.CAST_MAP:
ret_val = cls.CAST_MAP[map_index](cls, builder, lval1, lty2,
*args, **kws)
else:
raise NotImplementedError(lkind1, lkind2)
return ret_val
# ______________________________________________________________________
# Class definitions
class LLVMTranslator (BytecodeFlowVisitor):
'''Transformer responsible for visiting a set of bytecode flow
trees, emitting LLVM code.
Unlike other translators in :py:mod:`llpython`, this
incorporates the full transformation chain, starting with
:py:class:`llpython.byte_flow.BytecodeFlowBuilder`, then
:py:class:`llpython.byte_control.ControlFlowBuilder`, and
then :py:class:`llpython.phi_injector.PhiInjector`.'''
def __init__ (self, llvm_module = None, *args, **kws):
'''Constructor for LLVMTranslator.'''
super(LLVMTranslator, self).__init__(*args, **kws)
if llvm_module is None:
llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),))
self.llvm_module = llvm_module
self.bytecode_flow_builder = BytecodeFlowBuilder()
self.control_flow_builder = ControlFlowBuilder()
self.phi_injector = PhiInjector()
def translate (self, function, llvm_type = None, llvm_function = None,
env = None):
'''Translate a function to the given LLVM function type.
If no type is given, then assume the function is of LLVM type
"void ()".
The optional env parameter allows extension of the global
environment.'''
if llvm_type is None:
if llvm_function is None:
llvm_type = lc.Type.function(bytetype.lvoid, ())
else:
llvm_type = llvm_function.type.pointee
if env is None:
env = {}
else:
env = env.copy()
env.update((name, method)
for name, method in lc.Builder.__dict__.items()
if not name.startswith('_'))
env.update((name, value)
for name, value in bytetype.__dict__.items()
if not name.startswith('_'))
self.loop_stack = []
self.llvm_type = llvm_type
self.target_function_name = env.get('target_function_name',
function.__name__)
self.function = function
self.code_obj = opcode_util.get_code_object(function)
func_globals = getattr(function, 'func_globals',
getattr(function, '__globals__', {})).copy()
func_globals.update(env)
self.globals = func_globals
nargs = self.code_obj.co_argcount
self.cfg = self.control_flow_builder.visit(
opcode_util.build_basic_blocks(self.code_obj), nargs)
self.cfg.blocks = self.bytecode_flow_builder.visit_cfg(self.cfg)
self.llvm_function = llvm_function
flow = self.phi_injector.visit_cfg(self.cfg, nargs)
ret_val = self.visit(flow)
del self.cfg
del self.globals
del self.code_obj
del self.target_function_name
del self.function
del self.llvm_type
del self.loop_stack
return ret_val
def enter_flow_object (self, flow):
super(LLVMTranslator, self).enter_flow_object(flow)
if self.llvm_function is None:
self.llvm_function = self.llvm_module.add_function(
self.llvm_type, self.target_function_name)
self.llvm_blocks = {}
self.llvm_definitions = {}
self.pending_phis = {}
for block in self.block_list:
if 0 in self.cfg.blocks_reaching[block]:
bb = self.llvm_function.append_basic_block(
'BLOCK_%d' % (block,))
self.llvm_blocks[block] = bb
def exit_flow_object (self, flow):
super(LLVMTranslator, self).exit_flow_object(flow)
ret_val = self.llvm_function
del self.pending_phis
del self.llvm_definitions
del self.llvm_blocks
if __debug__ and logger.getEffectiveLevel() < logging.DEBUG:
logger.debug(str(ret_val))
return ret_val
def enter_block (self, block):
ret_val = False
if block in self.llvm_blocks:
self.llvm_block = self.llvm_blocks[block]
self.builder = lc.Builder.new(self.llvm_block)
ret_val = True
return ret_val
def exit_block (self, block):
bb_instrs = self.llvm_block.instructions
if ((len(bb_instrs) == 0) or
(not bb_instrs[-1].is_terminator)):
out_blocks = list(self.cfg.blocks_out[block])
assert len(out_blocks) == 1
self.builder.branch(self.llvm_blocks[out_blocks[0]])
del self.llvm_block
del self.builder
def visit_synthetic_op (self, i, op, arg, *args, **kws):
method = getattr(self, 'op_%s' % (synthetic_opname[op],))
return method(i, op, arg, *args, **kws)
def op_REF_ARG (self, i, op, arg, *args, **kws):
return [self.llvm_function.args[arg]]
def op_BUILD_PHI (self, i, op, arg, *args, **kws):
phi_type = None
incoming = []
pending = []
for child_arg in arg:
child_block, _, child_opname, child_arg, _ = child_arg
assert child_opname == 'REF_DEF'
if child_arg in self.llvm_definitions:
child_def = self.llvm_definitions[child_arg]
if phi_type is None:
phi_type = child_def.type
incoming.append((child_block, child_def))
else:
pending.append((child_arg, child_block))
phi = self.builder.phi(phi_type)
for block_index, defn in incoming:
phi.add_incoming(defn, self.llvm_blocks[block_index])
for defn_index, block_index in pending:
if defn_index not in self.pending_phis:
self.pending_phis[defn_index] = []
self.pending_phis[defn_index].append((phi, block_index))
return [phi]
def op_DEFINITION (self, i, op, def_index, *args, **kws):
assert len(args) == 1
arg = args[0]
if def_index in self.pending_phis:
for phi, block_index in self.pending_phis[def_index]:
phi.add_incoming(arg, self.llvm_blocks[block_index])
self.llvm_definitions[def_index] = arg
return args
def op_REF_DEF (self, i, op, arg, *args, **kws):
return [self.llvm_definitions[arg]]
def op_BINARY_ADD (self, i, op, arg, *args, **kws):
arg1, arg2 = args
if arg1.type.kind == lc.TYPE_INTEGER:
ret_val = [self.builder.add(arg1, arg2)]
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.fadd(arg1, arg2)]
elif arg1.type.kind == lc.TYPE_POINTER:
ret_val = [self.builder.gep(arg1, [arg2])]
else:
raise NotImplementedError("LLVMTranslator.op_BINARY_ADD for %r" %
(args,))
return ret_val
def op_BINARY_AND (self, i, op, arg, *args, **kws):
return [self.builder.and_(args[0], args[1])]
def op_BINARY_DIVIDE (self, i, op, arg, *args, **kws):
arg1, arg2 = args
if arg1.type.kind == lc.TYPE_INTEGER:
ret_val = [self.builder.sdiv(arg1, arg2)]
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.fdiv(arg1, arg2)]
else:
raise NotImplementedError("LLVMTranslator.op_BINARY_DIVIDE for %r"
% (args,))
return ret_val
def op_BINARY_FLOOR_DIVIDE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_BINARY_FLOOR_DIVIDE")
def op_BINARY_LSHIFT (self, i, op, arg, *args, **kws):
return [self.builder.shl(args[0], args[1])]
def op_BINARY_MODULO (self, i, op, arg, *args, **kws):
arg1, arg2 = args
if arg1.type.kind == lc.TYPE_INTEGER:
ret_val = [self.builder.srem(arg1, arg2)]
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.frem(arg1, arg2)]
else:
raise NotImplementedError("LLVMTranslator.op_BINARY_MODULO for %r"
% (args,))
return ret_val
def op_BINARY_MULTIPLY (self, i, op, arg, *args, **kws):
arg1, arg2 = args
if arg1.type.kind == lc.TYPE_INTEGER:
ret_val = [self.builder.mul(arg1, arg2)]
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.fmul(arg1, arg2)]
else:
raise NotImplementedError("LLVMTranslator.op_BINARY_MULTIPLY for "
"%r" % (args,))
return ret_val
def op_BINARY_OR (self, i, op, arg, *args, **kws):
return [self.builder.or_(args[0], args[1])]
def op_BINARY_POWER (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_BINARY_POWER")
def op_BINARY_RSHIFT (self, i, op, arg, *args, **kws):
return [self.builder.lshr(args[0], args[1])]
def op_BINARY_SUBSCR (self, i, op, arg, *args, **kws):
arr_val = args[0]
index_vals = args[1:]
ret_val = gep_result = self.builder.gep(arr_val, index_vals)
if (gep_result.type.kind == lc.TYPE_POINTER and
gep_result.type.pointee.kind != lc.TYPE_POINTER):
ret_val = self.builder.load(gep_result)
return [ret_val]
def op_BINARY_SUBTRACT (self, i, op, arg, *args, **kws):
arg1, arg2 = args
if arg1.type.kind == lc.TYPE_INTEGER:
ret_val = [self.builder.sub(arg1, arg2)]
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.fsub(arg1, arg2)]
else:
raise NotImplementedError("LLVMTranslator.op_BINARY_SUBTRACT for "
"%r" % (args,))
return ret_val
op_BINARY_TRUE_DIVIDE = op_BINARY_DIVIDE
def op_BINARY_XOR (self, i, op, arg, *args, **kws):
return [self.builder.xor(args[0], args[1])]
def op_BREAK_LOOP (self, i, op, arg, *args, **kws):
return [self.builder.branch(self.llvm_blocks[arg])]
def op_BUILD_SLICE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_BUILD_SLICE")
def op_BUILD_TUPLE (self, i, op, arg, *args, **kws):
return args
def op_CALL_FUNCTION (self, i, op, arg, *args, **kws):
fn = args[0]
args = args[1:]
fn_name = getattr(fn, '__name__', None)
if isinstance(fn, (types.FunctionType, types.MethodType)):
ret_val = [fn(self.builder, *args)]
elif isinstance(fn, lc.Value):
ret_val = [self.builder.call(fn, args)]
elif isinstance(fn, lc.Type):
if isinstance(fn, lc.FunctionType):
ret_val = [self.builder.call(
self.llvm_module.get_or_insert_function(fn, fn_name),
args)]
else:
assert len(args) == 1
ret_val = [LLVMCaster.build_cast(self.builder, args[0], fn)]
else:
raise NotImplementedError("Don't know how to call %s() (%r @ %d)!"
% (fn_name, fn, i))
return ret_val
def op_CALL_FUNCTION_KW (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_KW")
def op_CALL_FUNCTION_VAR (self, i, op, arg, *args, **kws):
args = list(args)
var_args = list(args.pop())
args.extend(var_args)
return self.op_CALL_FUNCTION(i, op, arg, *args, **kws)
def op_CALL_FUNCTION_VAR_KW (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_VAR_KW")
def op_COMPARE_OP (self, i, op, arg, *args, **kws):
arg1, arg2 = args
cmp_kind = opcode.cmp_op[arg]
if isinstance(arg1.type, lc.IntegerType):
ret_val = [self.builder.icmp(_compare_mapping_sint[cmp_kind],
arg1, arg2)]
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.fcmp(_compare_mapping_float[cmp_kind],
arg1, arg2)]
else:
raise NotImplementedError('Comparison of type %r' % (arg1.type,))
return ret_val
def op_CONTINUE_LOOP (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_CONTINUE_LOOP")
def op_DELETE_ATTR (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_DELETE_ATTR")
def op_DELETE_SLICE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_DELETE_SLICE")
def op_FOR_ITER (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_FOR_ITER")
def op_GET_ITER (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_GET_ITER")
op_INPLACE_ADD = op_BINARY_ADD
op_INPLACE_AND = op_BINARY_AND
op_INPLACE_DIVIDE = op_BINARY_DIVIDE
op_INPLACE_FLOOR_DIVIDE = op_BINARY_FLOOR_DIVIDE
op_INPLACE_LSHIFT = op_BINARY_LSHIFT
op_INPLACE_MODULO = op_BINARY_MODULO
op_INPLACE_MULTIPLY = op_BINARY_MULTIPLY
op_INPLACE_OR = op_BINARY_OR
op_INPLACE_POWER = op_BINARY_POWER
op_INPLACE_RSHIFT = op_BINARY_RSHIFT
op_INPLACE_SUBTRACT = op_BINARY_SUBTRACT
op_INPLACE_TRUE_DIVIDE = op_BINARY_TRUE_DIVIDE
op_INPLACE_XOR = op_BINARY_XOR
def op_JUMP_ABSOLUTE (self, i, op, arg, *args, **kws):
return [self.builder.branch(self.llvm_blocks[arg])]
def op_JUMP_FORWARD (self, i, op, arg, *args, **kws):
return [self.builder.branch(self.llvm_blocks[i + arg + 3])]
def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws):
cond = args[0]
block_false = self.llvm_blocks[i + 3 + arg]
block_true = self.llvm_blocks[i + 3]
return [self.builder.cbranch(cond, block_true, block_false)]
# raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE")
def op_JUMP_IF_FALSE_OR_POP (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP")
def op_JUMP_IF_TRUE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE")
def op_JUMP_IF_TRUE_OR_POP (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE_OR_POP")
def op_LOAD_ATTR (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_LOAD_ATTR")
def op_LOAD_CONST (self, i, op, arg, *args, **kws):
py_val = self.code_obj.co_consts[arg]
if isinstance(py_val, int):
ret_val = [lc.Constant.int(bytetype.lc_int, py_val)]
elif isinstance(py_val, float):
ret_val = [lc.Constant.double(py_val)]
elif py_val == None:
ret_val = [None]
else:
raise NotImplementedError('Constant converstion for %r' %
(py_val,))
return ret_val
def op_LOAD_DEREF (self, i, op, arg, *args, **kws):
name = self.code_obj.co_freevars[arg]
ret_val = self.globals[name]
if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'):
ret_val.__name__ = name
return [ret_val]
def op_LOAD_GLOBAL (self, i, op, arg, *args, **kws):
name = self.code_obj.co_names[arg]
ret_val = self.globals[name]
if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'):
ret_val.__name__ = name
return [ret_val]
def op_POP_BLOCK (self, i, op, arg, *args, **kws):
self.loop_stack.pop()
return [self.builder.branch(self.llvm_blocks[i + 1])]
def op_POP_JUMP_IF_FALSE (self, i, op, arg, *args, **kws):
return [self.builder.cbranch(args[0], self.llvm_blocks[i + 3],
self.llvm_blocks[arg])]
def op_POP_JUMP_IF_TRUE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_POP_JUMP_IF_TRUE")
def op_POP_TOP (self, i, op, arg, *args, **kws):
return args
def op_RETURN_VALUE (self, i, op, arg, *args, **kws):
if args[0] is None:
ret_val = [self.builder.ret_void()]
else:
ret_val = [self.builder.ret(args[0])]
return ret_val
def op_SETUP_LOOP (self, i, op, arg, *args, **kws):
self.loop_stack.append((i, arg))
return [self.builder.branch(self.llvm_blocks[i + 3])]
def op_SLICE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_SLICE")
def op_STORE_ATTR (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_STORE_ATTR")
def op_STORE_SLICE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_STORE_SLICE")
def op_STORE_SUBSCR (self, i, op, arg, *args, **kws):
store_val, arr_val, index_val = args
dest_addr = self.builder.gep(arr_val, [index_val])
return [self.builder.store(store_val, dest_addr)]
def op_UNARY_CONVERT (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_CONVERT")
def op_UNARY_INVERT (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_INVERT")
def op_UNARY_NEGATIVE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_NEGATIVE")
def op_UNARY_NOT (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_NOT")
def op_UNARY_POSITIVE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_POSITIVE")
# ______________________________________________________________________
def translate_function (func, lltype, llvm_module = None, **kws):
'''Given a function and an LLVM function type, emit LLVM code for
that function using a new LLVMTranslator instance.'''
translator = LLVMTranslator(llvm_module)
ret_val = translator.translate(func, lltype, env = kws)
return ret_val
# ______________________________________________________________________
def translate_into_function (py_function, llvm_function, **kws):
translator = LLVMTranslator(llvm_function.module)
ret_val = translator.translate(py_function, llvm_function = llvm_function,
env = kws)
return ret_val
# ______________________________________________________________________
def llpython (lltype, llvm_module = None, **kws):
'''Decorator version of translate_function().'''
def _llpython (func):
return translate_function(func, lltype, llvm_module, **kws)
return _llpython
# ______________________________________________________________________
def llpython_into (llvm_function, **kws):
def _llpython_into (func):
return translate_into_function(llvm_function, func, **kws)
return _llpython_into
# ______________________________________________________________________
# Main (self-test) routine
def main (*args):
from tests import llfuncs, llfunctys
if not args:
args = ('doslice',)
elif 'all' in args:
args = [llfunc
for llfunc in dir(llfuncs) if not llfunc.startswith('_')]
llvm_module = lc.Module.new('test_module')
for arg in args:
translate_function(getattr(llfuncs, arg), getattr(llfunctys, arg),
llvm_module)
print(llvm_module)
# ______________________________________________________________________
if __name__ == '__main__':
import sys
main(*sys.argv[1:])
# ______________________________________________________________________
# End of byte_translator.py

View file

@ -0,0 +1,360 @@
# ______________________________________________________________________
from __future__ import absolute_import
import itertools
import opcode
from .opcode_util import itercode
# ______________________________________________________________________
class BytecodeVisitor (object):
opnames = [name.split('+')[0] for name in opcode.opname]
def visit_op (self, i, op, arg, *args, **kws):
if op < 0:
ret_val = self.visit_synthetic_op(i, op, arg, *args, **kws)
else:
method = getattr(self, 'op_' + self.opnames[op])
ret_val = method(i, op, arg, *args, **kws)
return ret_val
def visit_synthetic_op (self, i, op, arg, *args, **kws):
raise NotImplementedError(
'BytecodeVisitor.visit_synthetic_op() must be overloaded if using '
'synthetic opcodes.')
def _not_implemented (self, i, op, arg, *args, **kws):
raise NotImplementedError("BytecodeVisitor.op_%s (@ bytecode index %d)"
% (self.opnames[op], i))
op_BINARY_ADD = _not_implemented
op_BINARY_AND = _not_implemented
op_BINARY_DIVIDE = _not_implemented
op_BINARY_FLOOR_DIVIDE = _not_implemented
op_BINARY_LSHIFT = _not_implemented
op_BINARY_MODULO = _not_implemented
op_BINARY_MULTIPLY = _not_implemented
op_BINARY_OR = _not_implemented
op_BINARY_POWER = _not_implemented
op_BINARY_RSHIFT = _not_implemented
op_BINARY_SUBSCR = _not_implemented
op_BINARY_SUBTRACT = _not_implemented
op_BINARY_TRUE_DIVIDE = _not_implemented
op_BINARY_XOR = _not_implemented
op_BREAK_LOOP = _not_implemented
op_BUILD_CLASS = _not_implemented
op_BUILD_LIST = _not_implemented
op_BUILD_MAP = _not_implemented
op_BUILD_SET = _not_implemented
op_BUILD_SLICE = _not_implemented
op_BUILD_TUPLE = _not_implemented
op_CALL_FUNCTION = _not_implemented
op_CALL_FUNCTION_KW = _not_implemented
op_CALL_FUNCTION_VAR = _not_implemented
op_CALL_FUNCTION_VAR_KW = _not_implemented
op_COMPARE_OP = _not_implemented
op_CONTINUE_LOOP = _not_implemented
op_DELETE_ATTR = _not_implemented
op_DELETE_DEREF = _not_implemented
op_DELETE_FAST = _not_implemented
op_DELETE_GLOBAL = _not_implemented
op_DELETE_NAME = _not_implemented
op_DELETE_SLICE = _not_implemented
op_DELETE_SUBSCR = _not_implemented
op_DUP_TOP = _not_implemented
op_DUP_TOPX = _not_implemented
op_DUP_TOP_TWO = _not_implemented
op_END_FINALLY = _not_implemented
op_EXEC_STMT = _not_implemented
op_EXTENDED_ARG = _not_implemented
op_FOR_ITER = _not_implemented
op_GET_ITER = _not_implemented
op_IMPORT_FROM = _not_implemented
op_IMPORT_NAME = _not_implemented
op_IMPORT_STAR = _not_implemented
op_INPLACE_ADD = _not_implemented
op_INPLACE_AND = _not_implemented
op_INPLACE_DIVIDE = _not_implemented
op_INPLACE_FLOOR_DIVIDE = _not_implemented
op_INPLACE_LSHIFT = _not_implemented
op_INPLACE_MODULO = _not_implemented
op_INPLACE_MULTIPLY = _not_implemented
op_INPLACE_OR = _not_implemented
op_INPLACE_POWER = _not_implemented
op_INPLACE_RSHIFT = _not_implemented
op_INPLACE_SUBTRACT = _not_implemented
op_INPLACE_TRUE_DIVIDE = _not_implemented
op_INPLACE_XOR = _not_implemented
op_JUMP_ABSOLUTE = _not_implemented
op_JUMP_FORWARD = _not_implemented
op_JUMP_IF_FALSE = _not_implemented
op_JUMP_IF_FALSE_OR_POP = _not_implemented
op_JUMP_IF_TRUE = _not_implemented
op_JUMP_IF_TRUE_OR_POP = _not_implemented
op_LIST_APPEND = _not_implemented
op_LOAD_ATTR = _not_implemented
op_LOAD_BUILD_CLASS = _not_implemented
op_LOAD_CLOSURE = _not_implemented
op_LOAD_CONST = _not_implemented
op_LOAD_DEREF = _not_implemented
op_LOAD_FAST = _not_implemented
op_LOAD_GLOBAL = _not_implemented
op_LOAD_LOCALS = _not_implemented
op_LOAD_NAME = _not_implemented
op_MAKE_CLOSURE = _not_implemented
op_MAKE_FUNCTION = _not_implemented
op_MAP_ADD = _not_implemented
op_NOP = _not_implemented
op_POP_BLOCK = _not_implemented
op_POP_EXCEPT = _not_implemented
op_POP_JUMP_IF_FALSE = _not_implemented
op_POP_JUMP_IF_TRUE = _not_implemented
op_POP_TOP = _not_implemented
op_PRINT_EXPR = _not_implemented
op_PRINT_ITEM = _not_implemented
op_PRINT_ITEM_TO = _not_implemented
op_PRINT_NEWLINE = _not_implemented
op_PRINT_NEWLINE_TO = _not_implemented
op_RAISE_VARARGS = _not_implemented
op_RETURN_VALUE = _not_implemented
op_ROT_FOUR = _not_implemented
op_ROT_THREE = _not_implemented
op_ROT_TWO = _not_implemented
op_SETUP_EXCEPT = _not_implemented
op_SETUP_FINALLY = _not_implemented
op_SETUP_LOOP = _not_implemented
op_SETUP_WITH = _not_implemented
op_SET_ADD = _not_implemented
op_SLICE = _not_implemented
op_STOP_CODE = _not_implemented
op_STORE_ATTR = _not_implemented
op_STORE_DEREF = _not_implemented
op_STORE_FAST = _not_implemented
op_STORE_GLOBAL = _not_implemented
op_STORE_LOCALS = _not_implemented
op_STORE_MAP = _not_implemented
op_STORE_NAME = _not_implemented
op_STORE_SLICE = _not_implemented
op_STORE_SUBSCR = _not_implemented
op_UNARY_CONVERT = _not_implemented
op_UNARY_INVERT = _not_implemented
op_UNARY_NEGATIVE = _not_implemented
op_UNARY_NOT = _not_implemented
op_UNARY_POSITIVE = _not_implemented
op_UNPACK_EX = _not_implemented
op_UNPACK_SEQUENCE = _not_implemented
op_WITH_CLEANUP = _not_implemented
op_YIELD_VALUE = _not_implemented
# ______________________________________________________________________
class BytecodeIterVisitor (BytecodeVisitor):
def visit (self, co_obj):
self.enter_code_object(co_obj)
for i, op, arg in itercode(co_obj.co_code):
self.visit_op(i, op, arg)
return self.exit_code_object(co_obj)
def enter_code_object (self, co_obj):
pass
def exit_code_object (self, co_obj):
pass
# ______________________________________________________________________
class BasicBlockVisitor (BytecodeVisitor):
def visit (self, blocks):
self.enter_blocks(blocks)
block_indices = list(blocks.keys())
block_indices.sort()
for block_index in block_indices:
self.enter_block(block_index)
for i, op, arg in blocks[block_index]:
self.visit_op(i, op, arg)
self.exit_block(block_index)
return self.exit_blocks(blocks)
def enter_blocks (self, blocks):
pass
def exit_blocks (self, blocks):
pass
def enter_block (self, block_index):
pass
def exit_block (self, block_index):
pass
# ______________________________________________________________________
class BytecodeFlowVisitor (BytecodeVisitor):
def visit (self, flow):
self.block_list = list(flow.keys())
self.block_list.sort()
self.enter_flow_object(flow)
for block in self.block_list:
prelude = self.enter_block(block)
prelude_isa_list = isinstance(prelude, list)
if prelude or prelude_isa_list:
if not prelude_isa_list:
prelude = []
new_stmts = list(self.visit_op(i, op, arg, *args)
for i, op, _, arg, args in flow[block])
self.new_flow[block] = list(itertools.chain(
prelude, *new_stmts))
self.exit_block(block)
del self.block_list
return self.exit_flow_object(flow)
def visit_op (self, i, op, arg, *args, **kws):
new_args = []
for child_i, child_op, _, child_arg, child_args in args:
new_args.extend(self.visit_op(child_i, child_op, child_arg,
*child_args))
ret_val = super(BytecodeFlowVisitor, self).visit_op(i, op, arg,
*new_args)
return ret_val
def enter_flow_object (self, flow):
self.new_flow = {}
def exit_flow_object (self, flow):
ret_val = self.new_flow
del self.new_flow
return ret_val
def enter_block (self, block):
pass
def exit_block (self, block):
pass
# ______________________________________________________________________
class BenignBytecodeVisitorMixin (object):
def _do_nothing (self, i, op, arg, *args, **kws):
return [(i, op, self.opnames[op], arg, args)]
op_BINARY_ADD = _do_nothing
op_BINARY_AND = _do_nothing
op_BINARY_DIVIDE = _do_nothing
op_BINARY_FLOOR_DIVIDE = _do_nothing
op_BINARY_LSHIFT = _do_nothing
op_BINARY_MODULO = _do_nothing
op_BINARY_MULTIPLY = _do_nothing
op_BINARY_OR = _do_nothing
op_BINARY_POWER = _do_nothing
op_BINARY_RSHIFT = _do_nothing
op_BINARY_SUBSCR = _do_nothing
op_BINARY_SUBTRACT = _do_nothing
op_BINARY_TRUE_DIVIDE = _do_nothing
op_BINARY_XOR = _do_nothing
op_BREAK_LOOP = _do_nothing
op_BUILD_CLASS = _do_nothing
op_BUILD_LIST = _do_nothing
op_BUILD_MAP = _do_nothing
op_BUILD_SET = _do_nothing
op_BUILD_SLICE = _do_nothing
op_BUILD_TUPLE = _do_nothing
op_CALL_FUNCTION = _do_nothing
op_CALL_FUNCTION_KW = _do_nothing
op_CALL_FUNCTION_VAR = _do_nothing
op_CALL_FUNCTION_VAR_KW = _do_nothing
op_COMPARE_OP = _do_nothing
op_CONTINUE_LOOP = _do_nothing
op_DELETE_ATTR = _do_nothing
op_DELETE_DEREF = _do_nothing
op_DELETE_FAST = _do_nothing
op_DELETE_GLOBAL = _do_nothing
op_DELETE_NAME = _do_nothing
op_DELETE_SLICE = _do_nothing
op_DELETE_SUBSCR = _do_nothing
op_DUP_TOP = _do_nothing
op_DUP_TOPX = _do_nothing
op_DUP_TOP_TWO = _do_nothing
op_END_FINALLY = _do_nothing
op_EXEC_STMT = _do_nothing
op_EXTENDED_ARG = _do_nothing
op_FOR_ITER = _do_nothing
op_GET_ITER = _do_nothing
op_IMPORT_FROM = _do_nothing
op_IMPORT_NAME = _do_nothing
op_IMPORT_STAR = _do_nothing
op_INPLACE_ADD = _do_nothing
op_INPLACE_AND = _do_nothing
op_INPLACE_DIVIDE = _do_nothing
op_INPLACE_FLOOR_DIVIDE = _do_nothing
op_INPLACE_LSHIFT = _do_nothing
op_INPLACE_MODULO = _do_nothing
op_INPLACE_MULTIPLY = _do_nothing
op_INPLACE_OR = _do_nothing
op_INPLACE_POWER = _do_nothing
op_INPLACE_RSHIFT = _do_nothing
op_INPLACE_SUBTRACT = _do_nothing
op_INPLACE_TRUE_DIVIDE = _do_nothing
op_INPLACE_XOR = _do_nothing
op_JUMP_ABSOLUTE = _do_nothing
op_JUMP_FORWARD = _do_nothing
op_JUMP_IF_FALSE = _do_nothing
op_JUMP_IF_FALSE_OR_POP = _do_nothing
op_JUMP_IF_TRUE = _do_nothing
op_JUMP_IF_TRUE_OR_POP = _do_nothing
op_LIST_APPEND = _do_nothing
op_LOAD_ATTR = _do_nothing
op_LOAD_BUILD_CLASS = _do_nothing
op_LOAD_CLOSURE = _do_nothing
op_LOAD_CONST = _do_nothing
op_LOAD_DEREF = _do_nothing
op_LOAD_FAST = _do_nothing
op_LOAD_GLOBAL = _do_nothing
op_LOAD_LOCALS = _do_nothing
op_LOAD_NAME = _do_nothing
op_MAKE_CLOSURE = _do_nothing
op_MAKE_FUNCTION = _do_nothing
op_MAP_ADD = _do_nothing
op_NOP = _do_nothing
op_POP_BLOCK = _do_nothing
op_POP_EXCEPT = _do_nothing
op_POP_JUMP_IF_FALSE = _do_nothing
op_POP_JUMP_IF_TRUE = _do_nothing
op_POP_TOP = _do_nothing
op_PRINT_EXPR = _do_nothing
op_PRINT_ITEM = _do_nothing
op_PRINT_ITEM_TO = _do_nothing
op_PRINT_NEWLINE = _do_nothing
op_PRINT_NEWLINE_TO = _do_nothing
op_RAISE_VARARGS = _do_nothing
op_RETURN_VALUE = _do_nothing
op_ROT_FOUR = _do_nothing
op_ROT_THREE = _do_nothing
op_ROT_TWO = _do_nothing
op_SETUP_EXCEPT = _do_nothing
op_SETUP_FINALLY = _do_nothing
op_SETUP_LOOP = _do_nothing
op_SETUP_WITH = _do_nothing
op_SET_ADD = _do_nothing
op_SLICE = _do_nothing
op_STOP_CODE = _do_nothing
op_STORE_ATTR = _do_nothing
op_STORE_DEREF = _do_nothing
op_STORE_FAST = _do_nothing
op_STORE_GLOBAL = _do_nothing
op_STORE_LOCALS = _do_nothing
op_STORE_MAP = _do_nothing
op_STORE_NAME = _do_nothing
op_STORE_SLICE = _do_nothing
op_STORE_SUBSCR = _do_nothing
op_UNARY_CONVERT = _do_nothing
op_UNARY_INVERT = _do_nothing
op_UNARY_NEGATIVE = _do_nothing
op_UNARY_NOT = _do_nothing
op_UNARY_POSITIVE = _do_nothing
op_UNPACK_EX = _do_nothing
op_UNPACK_SEQUENCE = _do_nothing
op_WITH_CLEANUP = _do_nothing
op_YIELD_VALUE = _do_nothing
# ______________________________________________________________________
# End of bytecode_visitor.py

42
llpython/bytetype.py Normal file
View file

@ -0,0 +1,42 @@
# ______________________________________________________________________
import ctypes
import llvm.core as lc
# ______________________________________________________________________
lvoid = lc.Type.void()
li1 = lc.Type.int(1)
li8 = lc.Type.int(8)
li16 = lc.Type.int(16)
li32 = lc.Type.int(32)
li64 = lc.Type.int(64)
liptr = lc.Type.int(ctypes.sizeof(ctypes.c_void_p) * 8)
lc_size_t = lc.Type.int(ctypes.sizeof(
getattr(ctypes, 'c_ssize_t', getattr(ctypes, 'c_size_t'))) * 8)
lfloat = lc.Type.float()
ldouble = lc.Type.double()
li8_ptr = lc.Type.pointer(li8)
lc_int = lc.Type.int(ctypes.sizeof(ctypes.c_int) * 8)
lc_long = lc.Type.int(ctypes.sizeof(ctypes.c_long) * 8)
l_pyobject_head = [lc_size_t, lc.Type.pointer(li32)]
l_pyobject_head_struct = lc.Type.struct(l_pyobject_head)
l_pyobj_p = l_pyobject_head_struct_p = lc.Type.pointer(l_pyobject_head_struct)
l_pyfunc = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
strlen = lc.Type.function(lc_size_t, (li8_ptr,))
strncpy = lc.Type.function(li8_ptr, (li8_ptr, li8_ptr, lc_size_t))
strndup = lc.Type.function(li8_ptr, (li8_ptr, lc_size_t))
malloc = lc.Type.function(li8_ptr, (lc_size_t,))
free = lc.Type.function(lvoid, (li8_ptr,))
Py_BuildValue = lc.Type.function(l_pyobj_p, [li8_ptr], True)
PyArg_ParseTuple = lc.Type.function(lc_int, [l_pyobj_p, li8_ptr], True)
PyEval_SaveThread = lc.Type.function(li8_ptr, [])
PyEval_RestoreThread = lc.Type.function(lc.Type.void(), [li8_ptr])
# ______________________________________________________________________
# End of bytetype.py

217
llpython/control_flow.py Normal file
View file

@ -0,0 +1,217 @@
# ______________________________________________________________________
import pprint
# ______________________________________________________________________
class ControlFlowGraph (object):
def __init__ (self):
self.blocks = {}
self.blocks_in = {}
self.blocks_out = {}
self.blocks_reads = {}
self.blocks_writes = {}
self.blocks_writer = {}
self.blocks_dom = {}
self.blocks_reaching = {}
def add_block (self, key, value = None):
self.blocks[key] = value
if key not in self.blocks_in:
self.blocks_in[key] = set()
self.blocks_out[key] = set()
self.blocks_reads[key] = set()
self.blocks_writes[key] = set()
self.blocks_writer[key] = {}
def add_edge (self, from_block, to_block):
self.blocks_out[from_block].add(to_block)
self.blocks_in[to_block].add(from_block)
def unlink_unreachables (self):
changed = True
next_blocks = self.blocks.keys()
next_blocks.remove(0)
while changed:
changed = False
blocks = next_blocks
next_blocks = blocks[:]
for block in blocks:
if len(self.blocks_in[block]) == 0:
blocks_out = self.blocks_out[block]
for out_edge in blocks_out:
self.blocks_in[out_edge].discard(block)
blocks_out.clear()
next_blocks.remove(block)
changed = True
def compute_dataflow (self):
'''Compute the dominator and reaching dataflow relationships
in the CFG.'''
blocks = set(self.blocks.keys())
nonentry_blocks = blocks.copy()
for block in blocks:
self.blocks_dom[block] = blocks
self.blocks_reaching[block] = set((block,))
if len(self.blocks_in[block]) == 0:
self.blocks_dom[block] = set((block,))
nonentry_blocks.remove(block)
changed = True
while changed:
changed = False
for block in nonentry_blocks:
olddom = self.blocks_dom[block]
newdom = set.intersection(*[self.blocks_dom[pred]
for pred in self.blocks_in[block]])
newdom.add(block)
if newdom != olddom:
changed = True
self.blocks_dom[block] = newdom
oldreaching = self.blocks_reaching[block]
newreaching = set.union(
*[self.blocks_reaching[pred]
for pred in self.blocks_in[block]])
newreaching.add(block)
if newreaching != oldreaching:
changed = True
self.blocks_reaching[block] = newreaching
return self.blocks_dom, self.blocks_reaching
def update_for_ssa (self):
'''Modify the blocks_writes map to reflect phi nodes inserted
for static single assignment representations.'''
joins = [block for block in self.blocks.keys()
if len(self.blocks_in[block]) > 1]
changed = True
while changed:
changed = False
for block in joins:
phis_needed = self.phi_needed(block)
for affected_local in phis_needed:
if affected_local not in self.blocks_writes[block]:
changed = True
# NOTE: For this to work, we assume that basic
# blocks are indexed by their instruction
# index in the VM bytecode.
self.writes_local(block, block, affected_local)
if changed:
# Any modifications have invalidated the reaching
# definitions, so delete any memoized results.
if hasattr(self, 'reaching_definitions'):
del self.reaching_definitions
def idom (self, block):
'''Compute the immediate dominator (idom) of the given block
key. Returns None if the block has no in edges.
Note that in the case where there are multiple immediate
dominators (a join after a non-loop branch), this returns one
of the predecessors, but is not guaranteed to reliably select
one over the others (depends on the ordering of the set type
iterator).'''
preds = self.blocks_in[block]
npreds = len(preds)
if npreds == 0:
ret_val = None
elif npreds == 1:
ret_val = tuple(preds)[0]
else:
ret_val = [pred for pred in preds
if block not in self.blocks_dom[pred]][0]
return ret_val
def block_writes_to_writer_map (self, block):
ret_val = {}
for local in self.blocks_writes[block]:
ret_val[local] = block
return ret_val
def get_reaching_definitions (self, block):
'''Return a nested map for the given block
s.t. ret_val[pred][local] equals the block key for the
definition of local that reaches the argument block via that
predecessor.
Useful for actually populating phi nodes, once you know you
need them.'''
has_memoized = hasattr(self, 'reaching_definitions')
if has_memoized and block in self.reaching_definitions:
ret_val = self.reaching_definitions[block]
else:
preds = self.blocks_in[block]
ret_val = {}
for pred in preds:
ret_val[pred] = self.block_writes_to_writer_map(pred)
crnt = self.idom(pred)
while crnt != None:
crnt_writer_map = self.block_writes_to_writer_map(crnt)
# This order of update favors the first definitions
# encountered in the traversal since the traversal
# visits blocks in reverse execution order.
crnt_writer_map.update(ret_val[pred])
ret_val[pred] = crnt_writer_map
crnt = self.idom(crnt)
if not has_memoized:
self.reaching_definitions = {}
self.reaching_definitions[block] = ret_val
return ret_val
def nreaches (self, block):
'''For each local, find the number of unique reaching
definitions the current block has.'''
reaching_definitions = self.get_reaching_definitions(block)
definition_map = {}
for pred in self.blocks_in[block]:
reaching_from_pred = reaching_definitions[pred]
for local in reaching_from_pred.keys():
if local not in definition_map:
definition_map[local] = set()
definition_map[local].add(reaching_from_pred[local])
ret_val = {}
for local in definition_map.keys():
ret_val[local] = len(definition_map[local])
return ret_val
def writes_local (self, block, write_instr_index, local_index):
self.blocks_writes[block].add(local_index)
block_writers = self.blocks_writer[block]
old_index = block_writers.get(local_index, -1)
# This checks for a corner case that would impact
# numba.translate.Translate.build_phi_nodes().
assert old_index != write_instr_index, (
"Found corner case for STORE_FAST at a CFG join!")
block_writers[local_index] = max(write_instr_index, old_index)
def phi_needed (self, join):
'''Return the set of locals that will require a phi node to be
generated at the given join.'''
nreaches = self.nreaches(join)
return set([local for local in nreaches.keys()
if nreaches[local] > 1])
def pprint (self, *args, **kws):
pprint.pprint(self.__dict__, *args, **kws)
def pformat (self, *args, **kws):
return pprint.pformat(self.__dict__, *args, **kws)
def to_dot (self, graph_name = None):
'''Return a dot (digraph visualizer in Graphviz) graph
description as a string.'''
if graph_name is None:
graph_name = 'CFG_%d' % id(self)
lines_out = []
for block_index in self.blocks:
lines_out.append(
'BLOCK_%r [shape=box, label="BLOCK_%r\\nr: %r, w: %r"];' %
(block_index, block_index,
tuple(self.blocks_reads[block_index]),
tuple(self.blocks_writes[block_index])))
for block_index in self.blocks:
for out_edge in self.blocks_out[block_index]:
lines_out.append('BLOCK_%r -> BLOCK_%r;' %
(block_index, out_edge))
return 'digraph %s {\n%s\n}\n' % (graph_name, '\n'.join(lines_out))
# ______________________________________________________________________
# End of control_flow.py

View file

@ -0,0 +1,26 @@
# ______________________________________________________________________
from __future__ import absolute_import
from . import opcode_util
# ______________________________________________________________________
def generate_bytecode_visitor (classname = 'BytecodeVisitor',
baseclass = 'object'):
opnames = list(set((opname.split('+')[0]
for opname in opcode_util.OPCODE_MAP.keys())))
opnames.sort()
return 'class %s (%s):\n%s\n' % (
classname, baseclass,
'\n\n'.join((' def op_%s (self, i, op, arg):\n'
' raise NotImplementedError("%s.op_%s")' %
(opname, classname, opname)
for opname in opnames)))
# ______________________________________________________________________
if __name__ == "__main__":
import sys
print(generate_bytecode_visitor(*sys.argv[1:]))
# ______________________________________________________________________
# End of gen_bytecode_visitor.py

367
llpython/nobitey.py Normal file
View file

@ -0,0 +1,367 @@
# ______________________________________________________________________
from __future__ import absolute_import
import sys
import os.path
import imp
import io
import types
import llvm.core as lc
import llvm.ee as le
from . import bytetype, byte_translator
from .pyaddfunc import pyaddfunc
LLVM_TO_INT_PARSE_STR_MAP = {
8 : 'b',
16 : 'h',
32 : 'i', # Note that on 32-bit systems sizeof(int) == sizeof(long)
64 : 'L', # Seeing sizeof(long long) == 8 on both 32 and 64-bit platforms
}
LLVM_TO_PARSE_STR_MAP = {
lc.TYPE_FLOAT : 'f',
lc.TYPE_DOUBLE : 'd',
}
# ______________________________________________________________________
# XXX Stolen from numba.translate
def get_string_constant (module, const_str):
const_name = "__STR_%x" % (hash(const_str),)
try:
ret_val = module.get_global_variable_named(const_name)
except:
lconst_str = lc.Constant.stringz(const_str)
ret_val = module.add_global_variable(lconst_str.type, const_name)
ret_val.initializer = lconst_str
ret_val.linkage = lc.LINKAGE_INTERNAL
return ret_val
# ______________________________________________________________________
class NoBitey (object):
def __init__ (self, target_module = None, type_annotations = None):
if target_module is None:
target_module = lc.Module.new('NoBitey_%d' % id(self))
if type_annotations is None:
type_annotations = {}
self.target_module = target_module
self.type_aliases = type_annotations # Reserved for future use.
def _build_parse_string (self, llvm_type):
kind = llvm_type.kind
if kind == lc.TYPE_INTEGER:
ret_val = LLVM_TO_INT_PARSE_STR_MAP[llvm_type.width]
elif kind in LLVM_TO_PARSE_STR_MAP:
ret_val = LLVM_TO_PARSE_STR_MAP[kind]
else:
raise TypeError('Unsupported LLVM type: %s' % str(llvm_type))
return ret_val
def build_parse_string (self, llvm_tys):
"""Given a set of LLVM types, return a string for parsing
them via PyArg_ParseTuple."""
return ''.join((self._build_parse_string(ty)
for ty in llvm_tys))
def handle_abi_casts (self, builder, result):
if result.type.kind == lc.TYPE_FLOAT:
# NOTE: The C ABI apparently casts floats to doubles when
# an argument must be pushed on the stack, as is the case
# when calling a variable argument function.
# XXX Is there documentation on this where I can find all
# coercion rules? Do we still need some libffi
# integration?
result = builder.fpext(result, bytetype.ldouble)
return result
def build_wrapper_function (self, llvm_function, engine = None):
arg_types = llvm_function.type.pointee.args
return_type = llvm_function.type.pointee.return_type
li32_0 = lc.Constant.int(bytetype.li32, 0)
def get_llvm_function (builder):
if self.target_module != llvm_function.module:
llvm_function_ptr = self.target_module.add_global_variable(
llvm_function.type, llvm_function.name)
llvm_function_ptr.initializer = lc.Constant.inttoptr(
lc.Constant.int(
bytetype.liptr,
engine.get_pointer_to_function(llvm_function)),
llvm_function.type)
llvm_function_ptr.linkage = lc.LINKAGE_INTERNAL
ret_val = builder.load(llvm_function_ptr)
else:
ret_val = llvm_function
return ret_val
def build_parse_args (builder):
return [builder.alloca(arg_type) for arg_type in arg_types]
def build_parse_string (builder):
parse_str = get_string_constant(
self.target_module, self.build_parse_string(arg_types))
return builder.gep(parse_str, (li32_0, li32_0))
def load_target_args (builder, args):
return [builder.load(arg) for arg in args]
def build_build_string (builder):
build_str = get_string_constant(
self.target_module, self._build_parse_string(return_type))
return builder.gep(build_str, (li32_0, li32_0))
handle_abi_casts = self.handle_abi_casts
target_function_name = llvm_function.name + "_wrapper"
# __________________________________________________
@byte_translator.llpython(bytetype.l_pyfunc, self.target_module,
**locals())
def _wrapper (self, args):
ret_val = l_pyobj_p(0)
parse_args = build_parse_args()
parse_result = PyArg_ParseTuple(args, build_parse_string(),
*parse_args)
if parse_result != li32(0):
thread_state = PyEval_SaveThread()
target_args = load_target_args(parse_args)
llresult = handle_abi_casts(get_llvm_function()(*target_args))
PyEval_RestoreThread(thread_state)
ret_val = Py_BuildValue(build_build_string(), llresult)
return ret_val
# __________________________________________________
return _wrapper
def wrap_llvm_module (self, llvm_module, engine = None, py_module = None):
'''
Shamefully adapted from bitey.bind.wrap_llvm_module().
'''
functions = [func for func in llvm_module.functions
if not func.name.startswith("_")
and not func.is_declaration
and func.linkage == lc.LINKAGE_EXTERNAL]
if engine is None:
engine = le.ExecutionEngine.new(llvm_module)
wrappers = [self.build_wrapper_function(func, engine)
for func in functions]
if __debug__: print(self.target_module)
if self.target_module != llvm_module:
engine.add_module(self.target_module)
py_wrappers = [pyaddfunc(wrapper.name,
engine.get_pointer_to_function(wrapper))
for wrapper in wrappers]
if py_module:
for py_wrapper in py_wrappers:
setattr(py_module, py_wrapper.__name__[:-8], py_wrapper)
setattr(py_module, '_llvm_module', llvm_module)
setattr(py_module, '_llvm_engine', engine)
if self.target_module != llvm_module:
setattr(py_module, '_llvm_wrappers', self.target_module)
return engine, py_wrappers
def wrap_llvm_module_in_python (self, llvm_module, py_module = None):
'''
Mildly reworked and abstracted bitey.bind.wrap_llvm_bitcode().
Abstracted to accept any existing LLVM Module object, and
return a Python wrapper module (even if one wasn't originally
specified).
'''
if py_module is None:
py_module = types.ModuleType(str(llvm_module.id))
engine = le.ExecutionEngine.new(llvm_module)
self.wrap_llvm_module(llvm_module, engine, py_module)
return py_module
def wrap_llvm_bitcode (self, bitcode, py_module = None):
'''
Intended to be drop-in replacement of
bitey.bind.wrap_llvm_bitcode().
'''
return self.wrap_llvm_module_in_python(
lc.Module.from_bitcode(io.BytesIO(bitcode)), py_module)
def wrap_llvm_assembly (self, llvm_asm, py_module = None):
return self.wrap_llvm_module_in_python(
lc.Module.from_assembly(io.BytesIO(llvm_asm)), py_module)
# ______________________________________________________________________
class NoBiteyLoader(object):
"""
Load LLVM compiled bitcode and autogenerate a ctypes binding.
Initially copied and adapted from bitey.loader module.
"""
def __init__(self, pkg, name, source, preload, postload):
self.package = pkg
self.name = name
self.fullname = '.'.join((pkg,name))
self.source = source
self.preload = preload
self.postload = postload
@classmethod
def _check_magic(cls, filename):
if os.path.exists(filename):
magic = open(filename,"rb").read(4)
if magic == b'\xde\xc0\x17\x0b':
return True
elif magic[:2] == b'\x42\x43':
return True
else:
return False
else:
return False
@classmethod
def build_module(cls, fullname, source_path, source_data, preload=None,
postload=None):
name = fullname.split(".")[-1]
mod = imp.new_module(name)
if preload:
exec(preload, mod.__dict__, mod.__dict__)
type_annotations = getattr(mod, '_type_annotations', None)
nb = NoBitey(type_annotations = type_annotations)
if source_path.endswith(('.o', '.bc')):
nb.wrap_llvm_bitcode(source_data, mod)
elif source_path.endswith('.s'):
nb.wrap_llvm_assembly(source_data, mod)
if postload:
exec(postload, mod.__dict__, mod.__dict__)
return mod
@classmethod
def find_module(cls, fullname, paths = None):
if paths is None:
paths = sys.path
names = fullname.split('.')
modname = names[-1]
source_paths = None
for f in paths:
path = os.path.join(os.path.realpath(f), modname)
source = path + '.o'
if cls._check_magic(source):
source_paths = path, source
break
source = path + '.bc'
if os.path.exists(source):
source_paths = path, source
break
source = path + '.s'
if os.path.exists(source):
source_paths = path, source
break
if source_paths:
path, source = source_paths
return cls('.'.join(names[:-1]), modname, source,
path + ".pre.py", path + ".post.py")
def get_code(self, module):
pass
def get_data(self, module):
pass
def get_filename(self, name):
return self.source
def get_source(self, name):
with open(self.source, 'rb') as f:
return f.read()
def is_package(self, *args, **kw):
return False
def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
preload = None
postload = None
# Get the preload file (if any)
if os.path.exists(self.preload):
with open(self.preload) as f:
preload = f.read()
# Get the source
with open(self.source, 'rb') as f:
source_data = f.read()
# Get the postload file (if any)
if os.path.exists(self.postload):
with open(self.postload) as f:
postload = f.read()
mod = self.build_module(fullname, self.get_filename(None), source_data,
preload, postload)
sys.modules[fullname] = mod
mod.__loader__ = self
mod.__file__ = self.source
return mod
@classmethod
def install(cls):
if cls not in sys.meta_path:
sys.meta_path.append(cls)
@classmethod
def remove(cls):
sys.meta_path.remove(cls)
# ______________________________________________________________________
def _mk_add_42 (llvm_module, at_type = bytetype.lc_long):
f = llvm_module.add_function(
lc.Type.function(at_type, [at_type]), 'add_42_%s' % str(at_type))
block = f.append_basic_block('entry')
builder = lc.Builder.new(block)
if at_type.kind == lc.TYPE_INTEGER:
const_42 = lc.Constant.int(at_type, 42)
add = builder.add
elif at_type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
const_42 = lc.Constant.real(at_type, 42.)
add = builder.fadd
else:
raise TypeError('Unsupported type: %s' % str(at_type))
builder.ret(add(f.args[0], const_42))
return f
# ______________________________________________________________________
def build_test_module ():
llvm_module = lc.Module.new('nobitey_test')
for ty in (bytetype.li32, bytetype.li64, bytetype.lfloat,
bytetype.ldouble):
fn = _mk_add_42(llvm_module, ty)
return llvm_module
# ______________________________________________________________________
def test_wrap_module (arg = None):
# Build up a module.
m = build_test_module()
if arg and arg.lower() == 'separated':
wrap_module = NoBitey().wrap_llvm_module_in_python(m)
else:
wrap_module = NoBitey(m).wrap_llvm_module_in_python(m)
# Now try running the generated wrappers.
for py_wf_name in ('add_42_i32', 'add_42_i64', 'add_42_float',
'add_42_double'):
py_wf = getattr(wrap_module, py_wf_name)
for i in range(42):
result = py_wf(i)
expected = i + 42
assert result == expected, "%r != %r in %r" % (
result, expected, py_wf)
return wrap_module
# ______________________________________________________________________
def main (*args):
if args:
for arg in args:
test_wrap_module(arg)
else:
test_wrap_module()
if __name__ == "__main__":
main(*sys.argv[1:])
# ______________________________________________________________________
# End of nobitey.py

225
llpython/opcode_util.py Normal file
View file

@ -0,0 +1,225 @@
# ______________________________________________________________________
import dis
import opcode
# ______________________________________________________________________
# Module data
hasjump = opcode.hasjrel + opcode.hasjabs
hascbranch = [op for op in hasjump
if 'IF' in opcode.opname[op]
or opcode.opname[op] in ('FOR_ITER', 'SETUP_LOOP')]
# Since the actual opcode value may change, manage opcode abstraction
# data by opcode name.
OPCODE_MAP = {
'BINARY_ADD': (2, 1, None),
'BINARY_AND': (2, 1, None),
'BINARY_DIVIDE': (2, 1, None),
'BINARY_FLOOR_DIVIDE': (2, 1, None),
'BINARY_LSHIFT': (2, 1, None),
'BINARY_MODULO': (2, 1, None),
'BINARY_MULTIPLY': (2, 1, None),
'BINARY_OR': (2, 1, None),
'BINARY_POWER': (2, 1, None),
'BINARY_RSHIFT': (2, 1, None),
'BINARY_SUBSCR': (2, 1, None),
'BINARY_SUBTRACT': (2, 1, None),
'BINARY_TRUE_DIVIDE': (2, 1, None),
'BINARY_XOR': (2, 1, None),
'BREAK_LOOP': (0, None, 1),
'BUILD_CLASS': (None, None, None),
'BUILD_LIST': (-1, 1, None),
'BUILD_MAP': (None, None, None),
'BUILD_SET': (None, None, None),
'BUILD_SLICE': (None, None, None),
'BUILD_TUPLE': (-1, 1, None),
'CALL_FUNCTION': (-2, 1, None),
'CALL_FUNCTION_KW': (-3, 1, None),
'CALL_FUNCTION_VAR': (-3, 1, None),
'CALL_FUNCTION_VAR_KW': (-4, 1, None),
'COMPARE_OP': (2, 1, None),
'CONTINUE_LOOP': (None, None, None),
'DELETE_ATTR': (1, None, 1),
'DELETE_DEREF': (None, None, None),
'DELETE_FAST': (0, None, 1),
'DELETE_GLOBAL': (0, None, 1),
'DELETE_NAME': (0, None, 1),
'DELETE_SLICE+0': (1, None, 1),
'DELETE_SLICE+1': (2, None, 1),
'DELETE_SLICE+2': (2, None, 1),
'DELETE_SLICE+3': (3, None, 1),
'DELETE_SUBSCR': (2, None, 1),
'DUP_TOP': (None, None, None),
'DUP_TOPX': (None, None, None),
'DUP_TOP_TWO': (None, None, None),
'END_FINALLY': (None, None, None),
'EXEC_STMT': (None, None, None),
'EXTENDED_ARG': (None, None, None),
'FOR_ITER': (1, 1, 1),
'GET_ITER': (1, 1, None),
'IMPORT_FROM': (None, None, None),
'IMPORT_NAME': (None, None, None),
'IMPORT_STAR': (1, None, 1),
'INPLACE_ADD': (2, 1, None),
'INPLACE_AND': (2, 1, None),
'INPLACE_DIVIDE': (2, 1, None),
'INPLACE_FLOOR_DIVIDE': (2, 1, None),
'INPLACE_LSHIFT': (2, 1, None),
'INPLACE_MODULO': (2, 1, None),
'INPLACE_MULTIPLY': (2, 1, None),
'INPLACE_OR': (2, 1, None),
'INPLACE_POWER': (2, 1, None),
'INPLACE_RSHIFT': (2, 1, None),
'INPLACE_SUBTRACT': (2, 1, None),
'INPLACE_TRUE_DIVIDE': (2, 1, None),
'INPLACE_XOR': (2, 1, None),
'JUMP_ABSOLUTE': (0, None, 1),
'JUMP_FORWARD': (0, None, 1),
'JUMP_IF_FALSE': (1, 1, 1),
'JUMP_IF_FALSE_OR_POP': (None, None, None),
'JUMP_IF_TRUE': (1, 1, 1),
'JUMP_IF_TRUE_OR_POP': (None, None, None),
'LIST_APPEND': (2, 0, 1),
'LOAD_ATTR': (1, 1, None),
'LOAD_BUILD_CLASS': (None, None, None),
'LOAD_CLOSURE': (None, None, None),
'LOAD_CONST': (0, 1, None),
'LOAD_DEREF': (0, 1, None),
'LOAD_FAST': (0, 1, None),
'LOAD_GLOBAL': (0, 1, None),
'LOAD_LOCALS': (None, None, None),
'LOAD_NAME': (0, 1, None),
'MAKE_CLOSURE': (None, None, None),
'MAKE_FUNCTION': (-2, 1, None),
'MAP_ADD': (None, None, None),
'NOP': (0, None, None),
'POP_BLOCK': (0, None, 1),
'POP_EXCEPT': (None, None, None),
'POP_JUMP_IF_FALSE': (1, None, 1),
'POP_JUMP_IF_TRUE': (1, None, 1),
'POP_TOP': (1, None, 1),
'PRINT_EXPR': (1, None, 1),
'PRINT_ITEM': (1, None, 1),
'PRINT_ITEM_TO': (2, None, 1),
'PRINT_NEWLINE': (0, None, 1),
'PRINT_NEWLINE_TO': (1, None, 1),
'RAISE_VARARGS': (None, None, None),
'RETURN_VALUE': (1, None, 1),
'ROT_FOUR': (None, None, None),
'ROT_THREE': (None, None, None),
'ROT_TWO': (None, None, None),
'SETUP_EXCEPT': (None, None, None),
'SETUP_FINALLY': (None, None, None),
'SETUP_LOOP': (None, None, None),
'SETUP_WITH': (None, None, None),
'SET_ADD': (None, None, None),
'SLICE+0': (1, 1, None),
'SLICE+1': (2, 1, None),
'SLICE+2': (2, 1, None),
'SLICE+3': (3, 1, None),
'STOP_CODE': (None, None, None),
'STORE_ATTR': (2, None, 1),
'STORE_DEREF': (1, 0, 1),
'STORE_FAST': (1, None, 1),
'STORE_GLOBAL': (1, None, 1),
'STORE_LOCALS': (None, None, None),
'STORE_MAP': (1, None, 1),
'STORE_NAME': (1, None, 1),
'STORE_SLICE+0': (1, None, 1),
'STORE_SLICE+1': (2, None, 1),
'STORE_SLICE+2': (2, None, 1),
'STORE_SLICE+3': (3, None, 1),
'STORE_SUBSCR': (3, None, 1),
'UNARY_CONVERT': (1, 1, None),
'UNARY_INVERT': (1, 1, None),
'UNARY_NEGATIVE': (1, 1, None),
'UNARY_NOT': (1, 1, None),
'UNARY_POSITIVE': (1, 1, None),
'UNPACK_EX': (None, None, None),
'UNPACK_SEQUENCE': (None, None, None),
'WITH_CLEANUP': (None, None, None),
'YIELD_VALUE': (1, None, 1),
}
# ______________________________________________________________________
# Module functions
def itercode(code, start = 0):
"""Return a generator of byte-offset, opcode, and argument
from a byte-code-string
"""
i = 0
extended_arg = 0
if isinstance(code[0], str):
code = [ord(c) for c in code]
n = len(code)
while i < n:
op = code[i]
num = i + start
i = i + 1
oparg = None
if op >= opcode.HAVE_ARGUMENT:
oparg = code[i] + (code[i + 1] * 256) + extended_arg
extended_arg = 0
i = i + 2
if op == opcode.EXTENDED_ARG:
extended_arg = oparg * 65536
delta = yield num, op, oparg
if delta is not None:
abs_rel, dst = delta
assert abs_rel == 'abs' or abs_rel == 'rel'
i = dst if abs_rel == 'abs' else i + dst
# ______________________________________________________________________
def extendlabels(code, labels = None):
"""Extend the set of jump target labels to account for the
passthrough targets of conditional branches.
This allows us to create a control flow graph where there is at
most one branch per basic block.
"""
if labels is None:
labels = []
if isinstance(code[0], str):
code = [ord(c) for c in code]
n = len(code)
i = 0
while i < n:
op = code[i]
i += 1
if op >= dis.HAVE_ARGUMENT:
i += 2
label = -1
if op in hasjump:
label = i
if label >= 0:
if label not in labels:
labels.append(label)
elif op == opcode.opmap['BREAK_LOOP']:
if i not in labels:
labels.append(i)
return labels
# ______________________________________________________________________
def get_code_object (func):
return getattr(func, '__code__', getattr(func, 'func_code', None))
# ______________________________________________________________________
def build_basic_blocks (co_obj):
co_code = co_obj.co_code
labels = extendlabels(co_code, dis.findlabels(co_code))
labels.sort()
blocks = dict((index, list(itercode(co_code[index:next_index], index)))
for index, next_index in zip([0] + labels,
labels + [len(co_code)]))
return blocks
# ______________________________________________________________________
# End of opcode_util.py

153
llpython/phi_injector.py Normal file
View file

@ -0,0 +1,153 @@
# ______________________________________________________________________
from .bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin
# ______________________________________________________________________
synthetic_opname = []
synthetic_opmap = {}
def def_synth_op (opname):
global synthetic_opname, synthetic_opmap
ret_val = -(len(synthetic_opname) + 1)
synthetic_opname.insert(0, opname)
synthetic_opmap[opname] = ret_val
return ret_val
REF_ARG = def_synth_op('REF_ARG')
BUILD_PHI = def_synth_op('BUILD_PHI')
DEFINITION = def_synth_op('DEFINITION')
REF_DEF = def_synth_op('REF_DEF')
# ______________________________________________________________________
class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
'''Transformer responsible for modifying a bytecode flow, removing
LOAD_FAST and STORE_FAST opcodes, and replacing them with a static
single assignment (SSA) representation.
In order to support SSA, PhiInjector adds the following synthetic
opcodes to transformed flows:
* REF_ARG: Specifically reference an incomming argument value.
* BUILD_PHI: Build a phi node to disambiguate between several
possible definitions at a control flow join.
* DEFINITION: Unique value definition indexed by the "arg" field
in the tuple.
* REF_DEF: Reference a specific value definition.'''
def visit_cfg (self, cfg, nargs = 0, *args, **kws):
self.cfg = cfg
ret_val = self.visit(cfg.blocks, nargs)
del self.cfg
return ret_val
def visit (self, flow, nargs = 0, *args, **kws):
self.nargs = nargs
self.definitions = []
self.phis = []
self.prev_blocks = []
self.blocks_locals = dict((block, {})
for block in self.cfg.blocks.keys())
ret_val = super(PhiInjector, self).visit(flow, *args, **kws)
for block, _, _, args, _ in self.phis:
local = args.pop()
reaching_definitions = self.cfg.reaching_definitions[block]
for prev in reaching_definitions.keys():
if 0 in self.cfg.blocks_reaching[prev]:
args.append((prev, REF_DEF, 'REF_DEF',
self.blocks_locals[prev][local], ()))
args.sort()
del self.blocks_locals
del self.prev_blocks
del self.phis
del self.definitions
del self.nargs
return ret_val
def add_definition (self, index, local, arg):
definition_index = len(self.definitions)
definition = (index, DEFINITION, 'DEFINITION', definition_index,
(arg,))
self.definitions.append(definition)
self.blocks_locals[self.block][local] = definition_index
return definition
def add_phi (self, index, local):
ret_val = (index, BUILD_PHI, 'BUILD_PHI', [local], ())
self.phis.append(ret_val)
return ret_val
def enter_block (self, block):
ret_val = False
self.block = block
if block == 0:
if self.nargs > 0:
ret_val = [self.add_definition(-1, arg,
(-1, REF_ARG, 'REF_ARG', arg,
()))
for arg in range(self.nargs)]
else:
ret_val = True
elif 0 in self.cfg.blocks_reaching[block]:
ret_val = True
prev_block_locals = None
for pred_block in self.cfg.blocks_in[block]:
if pred_block in self.prev_blocks:
prev_block_locals = self.blocks_locals[pred_block]
break
assert prev_block_locals is not None, "Internal translation error"
self.blocks_locals[block] = prev_block_locals.copy()
phis_needed = self.cfg.phi_needed(block)
if phis_needed:
ret_val = [self.add_definition(block, local,
self.add_phi(block, local))
for local in phis_needed]
return ret_val
def exit_block (self, block):
if 0 in self.cfg.blocks_reaching[block]:
self.prev_blocks.append(block)
del self.block
def op_STORE_FAST (self, i, op, arg, *args, **kws):
assert len(args) == 1
return [self.add_definition(i, arg, args[0])]
def op_LOAD_FAST (self, i, op, arg, *args, **kws):
return [(i, REF_DEF, 'REF_DEF', self.blocks_locals[self.block][arg],
args)]
# ______________________________________________________________________
def inject_phis (func):
'''Given a Python function, return a bytecode flow object that has
been transformed by a fresh PhiInjector instance.'''
import byte_control, byte_flow
argcount = byte_control.opcode_util.get_code_object(func).co_argcount
cfg = byte_control.build_cfg(func)
cfg.blocks = byte_flow.BytecodeFlowBuilder().visit_cfg(cfg)
return PhiInjector().visit_cfg(cfg, argcount)
# ______________________________________________________________________
# Main (self-test) routine
def main (*args):
import pprint
from tests import llfuncs
if not args:
args = ('doslice',)
for arg in args:
pprint.pprint(inject_phis(getattr(llfuncs, arg)))
# ______________________________________________________________________
if __name__ == "__main__":
import sys
main(*sys.argv[1:])
# ______________________________________________________________________
# End of phi_injector.py

40
llpython/pyaddfunc.py Normal file
View file

@ -0,0 +1,40 @@
# ______________________________________________________________________
import ctypes
# ______________________________________________________________________
class PyMethodDef (ctypes.Structure):
_fields_ = [
('ml_name', ctypes.c_char_p),
('ml_meth', ctypes.c_void_p),
('ml_flags', ctypes.c_int),
('ml_doc', ctypes.c_char_p),
]
PyCFunction_NewEx = ctypes.pythonapi.PyCFunction_NewEx
PyCFunction_NewEx.argtypes = (ctypes.POINTER(PyMethodDef),
ctypes.c_void_p,
ctypes.c_void_p)
PyCFunction_NewEx.restype = ctypes.py_object
cache = {} # Unsure if this is necessary to keep the PyMethodDef
# structures from being garbage collected. Assuming so...
def pyaddfunc (func_name, func_ptr, func_doc = None):
global cache
if bytes != str:
func_name = bytes(ord(ch) for ch in func_name)
key = (func_name, func_ptr)
if key in cache:
_, ret_val = cache[key]
else:
mdef = PyMethodDef(bytes(func_name),
func_ptr,
1, # == METH_VARARGS (hopefully remains so...)
func_doc)
ret_val = PyCFunction_NewEx(ctypes.byref(mdef), 0, 0)
cache[key] = (mdef, ret_val)
return ret_val
# ______________________________________________________________________
# End of pyaddfunc.py

View file

41
llpython/tests/llfuncs.py Normal file
View file

@ -0,0 +1,41 @@
# ______________________________________________________________________
def doslice (in_string, lower, upper):
l = strlen(in_string)
if lower < lc_size_t(0):
lower += l
if upper < lc_size_t(0):
upper += l
temp_len = upper - lower
if temp_len < lc_size_t(0):
temp_len = lc_size_t(0)
ret_val = alloca_array(li8, temp_len + lc_size_t(1))
strncpy(ret_val, in_string + lower, temp_len)
ret_val[temp_len] = li8(0)
return ret_val
def ipow (val, exp):
ret_val = 1
temp = val
w = exp
while w > 0:
if (w & 1) != 0:
ret_val *= temp
# TODO: Overflow check on ret_val
w >>= 1
if w == 0: break
temp *= temp
# TODO: Overflow check on temp
return ret_val
def pymod (arg1, arg2):
ret_val = arg1 % arg2
if ret_val < 0:
if arg2 > 0:
ret_val += arg2
elif arg2 < 0:
ret_val += arg2
return ret_val
# ______________________________________________________________________
# End of llfuncs.py

View file

@ -0,0 +1,19 @@
# ______________________________________________________________________
import llvm.core as lc
from llpython import bytetype
# ______________________________________________________________________
doslice = lc.Type.function(bytetype.li8_ptr, (
bytetype.li8_ptr, bytetype.lc_size_t, bytetype.lc_size_t))
ipow = lc.Type.function(bytetype.li32, (bytetype.li32,
bytetype.li32))
pymod = lc.Type.function(bytetype.li32, (bytetype.li32,
bytetype.li32))
# ______________________________________________________________________
# End of llfunctys.py

22
llrtc/Makefile Normal file
View file

@ -0,0 +1,22 @@
all:
make -C lib
ir:
make -C lib ir
test:
make -C lib test
clean-test:
make -C lib clean-test
clean-temp:
make -C lib clean-temp
clean:
make -C lib clean
install: ir
cp llrt_*.ll ../llvm/llrt
make -C lib clean-temp

25
llrtc/README.md Normal file
View file

@ -0,0 +1,25 @@
# LLRT: Low Level Runtime
## Why?
The same reason for LLVM compiler-rt. LLVM generates libgcc symbols, such as
__divdi3 for 64-bit division on 32-bit platform. They are not also available.
We need to ship compiler-rt but it is not Windows ready.
This subproject aims to provide a small portable subset of compiler-rt.
Start small and add only the things we really needed.
Performance is not crucial but should not be terrible.
Functionality and usefullness should be more important than performance.
## Developer Instructions
LLRT implements some functionalities in compiler-rt in ANSI C.
The C files are compiled using clang to produce LLVM IR which are shipped.
The IR files are committed in the repository.
So, remember to build the IR files commit them after modifying the C files.
## Build Requirement
- Make
- Clang
- Python

4
llrtc/lib/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.o
*.run
*.out
*.ll

66
llrtc/lib/Makefile Normal file
View file

@ -0,0 +1,66 @@
OUTPUT = llrt
SOURCES = udivmod64.c sdivmod64.c div64.c mod64.c
TESTS = test_udivmod64.c test_sdivmod64.c
CLANG = clang
LLVM_LINK = llvm-link
CF = -Wall -ansi
CF_TEST = $(CF) -ftrapv
CF_BUILD = $(CF) -O0 -emit-llvm
OUTDIR = ..
STRIPPER = ../tools/striptriple.py
all: ir
ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll
$(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc)
$(LLVM_LINK) -S $+ -o $@
python $(STRIPPER) $@
$(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc)
$(LLVM_LINK) -S $+ -o $@
python $(STRIPPER) $@
build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run)
lib$(OUTPUT).a: $(SOURCES:.c=.o)
$(CLANG) -static $+ -o $@
test: $(TESTS:.c=.run)
for src in $+; do \
echo "testing $${src}"; \
python $${src%.*}.py > $${src%.*}.out; \
done;
clean-test:
rm -f *.out
rm -f *.o
rm -f *.run
clean-dist: clean-temp
rm -f *.ll
clean-temp:
rm -f *.bc
rm -f *.o
rm -f *.out
clean: clean-test clean-dist
%.c: llrt.h
%_x86.bc: %.c
$(CLANG) -m32 $(CF_BUILD) -c $< -o $@
%_x86_64.bc: %.c
$(CLANG) -m64 $(CF_BUILD) -c $< -o $@
%.o: %.c
$(CLANG) $(CF_TEST) -c $<
%.run: %.c
$(CLANG) $(CF_TEST) -o $@ $+
test_udivmod64.run: udivmod64.o
test_sdivmod64.run: udivmod64.o sdivmod64.o

11
llrtc/lib/div64.c Normal file
View file

@ -0,0 +1,11 @@
#include "llrt.h"
uint64_t udiv64(uint64_t dividend, uint64_t divisor)
{
return udivmod64(dividend, divisor, NULL);
}
int64_t sdiv64(int64_t dividend, int64_t divisor)
{
return sdivmod64(dividend, divisor, NULL);
}

19
llrtc/lib/llrt.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef LLRT_H_
#define LLRT_H_
#include <stdint.h>
#define NULL 0
#define BITS_PER_BYTE 8
uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder);
int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder);
uint64_t udiv64(uint64_t dividend, uint64_t divisor);
int64_t sdiv64(int64_t dividend, int64_t divisor);
uint64_t umod64(uint64_t dividend, uint64_t divisor);
int64_t smod64(int64_t dividend, int64_t divisor);
#endif /* LLRT_H_ */

15
llrtc/lib/mod64.c Normal file
View file

@ -0,0 +1,15 @@
#include "llrt.h"
uint64_t umod64(uint64_t dividend, uint64_t divisor)
{
uint64_t rem;
udivmod64(dividend, divisor, &rem);
return rem;
}
int64_t smod64(int64_t dividend, int64_t divisor)
{
int64_t rem;
sdivmod64(dividend, divisor, &rem);
return rem;
}

40
llrtc/lib/sdivmod64.c Normal file
View file

@ -0,0 +1,40 @@
#include "llrt.h"
#include <stdio.h>
/*
Calls to udivmod64 internally.
Note: remainder uses sign of divisor.
*/
int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder)
{
int signbitidx = BITS_PER_BYTE * sizeof(dividend) - 1;
int signed_dividend = dividend < 0;
int signed_divisor = divisor < 0;
int signed_result = signed_divisor ^ signed_dividend;
int64_t quotient;
uint64_t udvd, udvr, uquotient, uremainder;
udvd = signed_dividend ? -dividend : dividend;
udvr = signed_divisor ? -divisor : divisor;
uquotient = udivmod64(udvd, udvr, &uremainder);
if (signed_result){
if (uremainder) {
quotient = -(int64_t)uquotient - 1;
} else {
quotient = -(int64_t)uquotient;
}
if (remainder) {
/* if signed, there could be unsigned overflow
causing undefined behavior */
*remainder = (uint64_t)dividend - (uint64_t)quotient * (uint64_t)divisor;
}
} else {
quotient = (int64_t)uquotient;
if (remainder) {
*remainder = signed_divisor ? -uremainder : uremainder;
}
}
return quotient;
}

View file

@ -0,0 +1,21 @@
#include <stdio.h>
#include <stdint.h>
#include "llrt.h"
int main(int argc, char * argv[]){
int64_t n, d, q, r;
if (argc != 3) {
printf("invalid argument: %s dividend divisor", argv[0]);
return 1;
}
sscanf(argv[1], "%lld", &n);
sscanf(argv[2], "%lld", &d);
q = sdivmod64(n, d, &r);
printf("%lld\n", q);
printf("%lld\n", r);
return 0;
}

View file

@ -0,0 +1,56 @@
import math
import os
import subprocess
udt = os.path.join('.', 'test_sdivmod64.run')
def testcase(dividend, divisor):
print 'divmod64(%d, %d)' % (dividend, divisor)
procargs = ('%s %s %s' % (udt, dividend, divisor)).split()
result = subprocess.check_output(procargs)
gotQ, gotR = map(int, result.splitlines())
expectQ = dividend // divisor
expectR = dividend % divisor
print 'Q = %d, R = %d' % (gotQ, gotR)
if expectQ != gotQ:
raise ValueError("invalid quotient: got=%d but expect=%d" %
(gotQ, expectQ))
if expectR != gotR:
raise ValueError("invalid remainder: got=%d but expect=%d" %
(gotR, expectR))
print 'OK'
def testsequence():
subjects = [
(0, 1),
(0, 0xffffffff),
(1, 2),
(1, 983219),
(2, 2),
(3, 2),
(1024, 2),
(2048, 512),
(21321, 512),
(9329189, 1031),
(0xffffffff, 2),
(0xffffffff, 0xffff),
(0x1ffffffff, 2),
(0x1ffffffff, 0xffff),
(0xffff, 0xffffffff),
(0x0fffffffffffffff, 0xffff),
(0x7fffffffffffffff, 0x7fffffffffffffff),
(0x7fffffffffffffff, 0x7ffffffffffffff0),
(0x7fffffffffffffff, 87655678587161901),
]
for dvd, dvr in subjects:
testcase(dvd, dvr)
testcase(dvd, -dvr)
testcase(-dvd, dvr)
testcase(-dvd, -dvr)
if __name__ == '__main__':
testsequence()

View file

@ -0,0 +1,20 @@
#include <stdio.h>
#include <stdint.h>
#include "llrt.h"
int main(int argc, char * argv[]){
uint64_t n, d, q, r;
if (argc != 3) {
printf("invalid argument: %s dividend divisor", argv[0]);
return 1;
}
sscanf(argv[1], "%llu", &n);
sscanf(argv[2], "%llu", &d);
q = udivmod64(n, d, &r);
printf("%llu\n", q);
printf("%llu\n", r);
return 0;
}

View file

@ -0,0 +1,53 @@
import math
import os
import subprocess
udt = os.path.join('.', 'test_udivmod64.run')
def testcase(dividend, divisor):
print 'divmod64(%d, %d)' % (dividend, divisor)
procargs = ('%s %s %s' % (udt, dividend, divisor)).split()
result = subprocess.check_output(procargs)
gotQ, gotR = map(int, result.splitlines())
expectQ = dividend // divisor
expectR = dividend % divisor
print 'Q = %d, R = %d' % (gotQ, gotR)
if expectQ != gotQ:
raise ValueError("invalid quotient: got=%d but expect=%d" %
(gotQ, expectQ))
if expectR != gotR:
raise ValueError("invalid remainder: got=%d but expect=%d" %
(gotR, expectR))
print 'OK'
def testsequence():
subjects = [
(0, 1),
(0, 0xffffffffffffffff),
(1, 2),
(1, 983219),
(2, 2),
(3, 2),
(1024, 2),
(2048, 512),
(21321, 512),
(9329189, 1031),
(0xffffffff, 2),
(0xffffffff, 0xffff),
(0x1ffffffff, 2),
(0x1ffffffff, 0xffff),
(0xffff, 0xffffffff),
(0xffffffffffffffff, 0xffff),
(0xffffffffffffffff, 0x7fffffffffffffff),
(0xffffffffffffffff, 0xfffffffffffffff0),
(0xffffffffffffffff, 87655678587161901),
]
for dvd, dvr in subjects:
testcase(dvd, dvr)
if __name__ == '__main__':
testsequence()

84
llrtc/lib/udivmod64.c Normal file
View file

@ -0,0 +1,84 @@
/*
Implements unsigned divmod using for platform missing 64-bit division and/or
modulo functions.
*/
#include "llrt.h"
/*
count left zero for 64-bit words
*/
static
int clz64(uint64_t x)
{
const int total_bits = sizeof(x) * BITS_PER_BYTE;
int zc = 0;
while (zc < total_bits && ((x >> (total_bits - zc - 1)) & 1) == 0) {
++zc;
}
return zc;
}
typedef struct div_state_
{
uint64_t tmp, dvd;
} div_state;
/*
Left shift div_state by 1 bit
*/
static
void div_state_lshift(div_state *state)
{
state->tmp = (state->tmp << 1) | (state->dvd >> 63);
state->dvd = state->dvd << 1;
}
/*
Division of unsigned 64-bit word using 64-bit addition and subtration following
the shift-restore division algorithm.
For those interested in 32-bit implementation,
mapping of 64-bit addition and subtraction to 32-bit should be trivial.
Reference:
- IBM. The PowerPC Compiler Writer's Guide
- LLVM compiler-rt
Assumptions:
- all operands and results are positive
- unsigned wrapped around
*/
uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder)
{
div_state state = {0, dividend};
uint64_t quotient = 0;
int i;
int skipahead;
if (divisor == 0) {
return 1 / 0; /* intentionally div by zero */
}
/*
skipahead to reduce iteration
*/
skipahead = clz64(dividend);
for (i = 0; i < skipahead; ++i) {
div_state_lshift(&state);
}
/*
division loop
*/
for (i = skipahead; i < 64; ++i) {
div_state_lshift(&state);
if (state.tmp >= divisor) {
state.tmp = state.tmp - divisor;
quotient |= 1ull << (63 - i);
}
}
if (remainder) *remainder = state.tmp;
return quotient;
}

View file

@ -0,0 +1,15 @@
import sys
import re
buf = []
with open(sys.argv[1], 'r') as fin:
tripleline = re.compile('^target\s+triple\s+=\s+')
for line in fin.readlines():
if not tripleline.match(line):
buf.append(line)
with open(sys.argv[1], 'w') as fout:
for line in buf:
fout.write(line)

View file

@ -1,76 +1,88 @@
import sys, os
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
def find_path_of(filename, envvar='PATH'):
"""Finds the path from $PATH where the file exists, returns None if not found."""
pathlist = os.getenv(envvar).split(os.pathsep)
for path in pathlist:
if os.path.exists(os.path.join(path, filename)):
return os.path.abspath(path)
return None
if sys.argv[1] == '--version':
cmd = 'llvm-tblgen --version'
# Hardcoded extraction, only tested on llvm 3.1
result = os.popen(cmd).read().split('\n')[1].strip().split(' ')[2]
print result
elif sys.argv[1] == '--libs':
def find_llvm_tblgen():
path = find_executable('llvm-tblgen')
if path is None:
sys.exit('Error: could not locate llvm-tblgen')
return path
def find_llvm_prefix():
return abspath(dirname(dirname(find_llvm_tblgen())))
def ensure_file(path):
if not isfile(path):
sys.exit('Error: no file: %r' % path)
def get_llvm_version():
args = [find_llvm_tblgen(), '--version']
p = Popen(args, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
if stderr:
sys.exit("Error: %r stderr is:\n%s" % (args, stderr.decode()))
out = stdout.decode().strip()
pat = re.compile(r'llvm\s+version\s+(\d+\.\d+\S*)', re.I)
m = pat.search(out)
if m is None:
sys.exit('Error: could not parse version in:' + out)
return m.group(1)
def libs_options():
# NOTE: instead of actually looking at the components requested,
# we just spit out a bunch of libs
# we just print out a bunch of libs
for lib in """
LLVMAnalysis
LLVMAsmParser
LLVMAsmPrinter
LLVMBitReader
LLVMBitWriter
LLVMCodeGen
LLVMCore
LLVMExecutionEngine
LLVMInstCombine
LLVMInstrumentation
LLVMInterpreter
LLVMipa
LLVMipo
LLVMJIT
LLVMLinker
LLVMMC
LLVMMCParser
LLVMScalarOpts
LLVMSelectionDAG
LLVMSupport
LLVMTarget
LLVMTransformUtils
LLVMVectorize
LLVMX86AsmParser
LLVMX86AsmPrinter
LLVMX86CodeGen
LLVMX86Desc
LLVMX86Info
LLVMX86Utils
Advapi32
Shell32
""".split():
print('-l%s' % lib)
# Look for the PTX .lib in %LIBPATH%
if find_path_of('LLVMPTXCodeGen.lib', 'LIBPATH') != None:
print('-lLLVMPTXAsmPrinter')
print('-lLLVMPTXCodeGen')
print('-lLLVMPTXDesc')
print('-lLLVMPTXInfo')
elif sys.argv[1] == '--includedir':
llvmbin = find_path_of('llvm-tblgen.exe')
if llvmbin is None:
raise RuntimeError('Could not find LLVM')
incdir = os.path.abspath(os.path.join(llvmbin, '../include'))
if not os.path.exists(os.path.join(incdir, 'llvm/BasicBlock.h')):
raise RuntimeError('Could not find LLVM include dir')
print incdir
elif sys.argv[1] == '--libdir':
llvmbin = find_path_of('llvm-tblgen.exe')
if llvmbin is None:
raise RuntimeError('Could not find LLVM')
libdir = os.path.abspath(os.path.join(llvmbin, '../lib'))
if not os.path.exists(os.path.join(libdir, 'LLVMCore.lib')):
raise RuntimeError('Could not find LLVM lib dir')
print libdir
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:
option = sys.argv[1]
except IndexError:
sys.exit('Error: option missing')
if option == '--version':
print(get_llvm_version())
elif option == '--targets-built':
print('X86') # just do X86
elif option == '--libs':
libs_options()
elif option == '--includedir':
incdir = join(find_llvm_prefix(), 'include')
ensure_file(join(incdir, 'llvm' , 'Linker.h'))
print(incdir)
elif option == '--libdir':
libdir = join(find_llvm_prefix(), 'lib')
ensure_file(join(libdir, 'LLVMCore.lib'))
print(libdir)
elif option in ('--ldflags', '--components'):
pass
else:
raise RuntimeError('Unrecognized llvm-config command %s' % sys.argv[1])
sys.exit('Error: Unrecognized llvm-config option %r' % option)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load diff

View file

@ -1,140 +1,47 @@
"""
Common classes related to LLVM.
"""
__version__ = '0.8.3'
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
from weakref import WeakValueDictionary
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
@property
def _ptr(self):
try:
return self.__ptr
except AttributeError:
raise AttributeError("_ptr resource has been removed")
@_ptr.deleter
def _ptr(self):
del self.__ptr
#===----------------------------------------------------------------------===
# Exceptions
#===----------------------------------------------------------------------===
def _extract_ptrs(objs):
return [(x._ptr if x is not None else None)
for x in objs]
class LLVMException(Exception):
"""Generic LLVM exception."""
def __init__(self, msg=""):
Exception.__init__(self, msg)
#===----------------------------------------------------------------------===
# Ownables
#===----------------------------------------------------------------------===
class Ownable(object):
"""Objects that can be owned.
Modules and Module Providers can be owned, i.e., the responsibility of
destruction of ownable objects can be handed over to other objects. The
llvm.Ownable class represents objects that can be so owned. This class
is NOT intended for public use.
"""
def __init__(self, ptr, del_fn):
self.ptr = ptr
self.owner = None
self.del_fn = del_fn
def _own(self, owner):
if self.owner:
raise LLVMException("object already owned")
self.owner = owner
def _disown(self):
if not self.owner:
raise LLVMException("not owned")
self.owner = None
def __del__(self):
if not self.owner:
self.del_fn(self.ptr)
#===----------------------------------------------------------------------===
# Dummy owner, will not delete ownee. Be careful.
#===----------------------------------------------------------------------===
class DummyOwner(object):
pass
#===----------------------------------------------------------------------===
# A metaclass to prevent aliasing. It stores a (weak) reference to objects
# constructed based on a PyCObject. If an object is constructed based on a
# PyCObject with the same underlying pointer as a previous object, a reference
# to the previous object is returned rather than a new one.
#===----------------------------------------------------------------------===
class _ObjectCache(type):
"""A metaclass to prevent aliasing.
Classes using 'ObjectCache' as a metaclass must have constructors
that take a PyCObject as their first argument. When the class is
called (to create a new instance of the class), the value of the
pointer wrapped by the PyCObj is checked:
If no previous object has been created based on the same
underlying pointer (note that different PyCObject objects can
wrap the same pointer), the object will be initialized as
usual and returned.
If a previous has been created based on the same pointer,
then a reference to that object will be returned, and no
object initialization is performed.
"""
__instances = WeakValueDictionary()
def __call__(cls, ptr, *args, **kwargs):
objid = _core.PyCObjectVoidPtrToPyLong(ptr)
key = "%s:%d" % (cls.__name__, objid)
obj = _ObjectCache.__instances.get(key)
if obj is None:
obj = super(_ObjectCache, cls).__call__(ptr, *args, **kwargs)
_ObjectCache.__instances[key] = obj
return obj
@staticmethod
def forget(obj):
objid = _core.PyCObjectVoidPtrToPyLong(obj.ptr)
key = "%s:%d" % (type(obj).__name__, objid)
if key in _ObjectCache.__instances:
del _ObjectCache.__instances[key]
#===----------------------------------------------------------------------===
# Cacheables
#===----------------------------------------------------------------------===
# version 2/3 compatibility help
# version 2 metaclass
# class Cacheable(object):
# __metaclass__ = _ObjectCache # Doing nothing for version 3
#
# version 3 metaclass
# class Cacheable(metaclass=_ObjectCache):
#
# Reference: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/#using-the-metaclass-in-python-3-x
ObjectCache = _ObjectCache('ObjectCache', (object, ), {})
class Cacheable(ObjectCache):
"""Objects that can be cached.
Objects that wrap a PyCObject are cached to avoid "aliasing", i.e.,
two Python objects each containing a PyCObject which internally points
to the same C pointer."""
def forget(self):
ObjectCache.forget(self)
def test(verbosity=1):
def test(verbosity=3, run_isolated=True):
"""test(verbosity=1) -> TextTestResult
Run self-test, and return unittest.runner.TextTestResult object.
Run self-test, and return the number of failures + errors
"""
from llvm.test_llvmpy import run
from llvm.tests import run
return run(verbosity=verbosity)
result = run(verbosity=verbosity, run_isolated=run_isolated)
errct = len(result.failures) + len(result.errors)
return errct

File diff suppressed because it is too large Load diff

View file

@ -1,103 +0,0 @@
#
# Copyright (c) 2008-10, Mahadevan R All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of this software, nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""Utility functions and classes.
Used only in other modules, not for public use."""
import llvm
import llvm._core as _core # for PyCObjectVoidPtrToPyLong
#===----------------------------------------------------------------------===
# A set of helpers to check various things. Raises exceptions on
# failures.
#===----------------------------------------------------------------------===
def check_gen(obj, typ):
if not isinstance(obj, typ):
typ_str = typ.__name__
msg = "argument not an instance of llvm.core.%s" % typ_str
raise TypeError(msg)
def check_is_unowned(ownable):
if ownable.owner:
raise llvm.LLVMException("object is already owned")
#===----------------------------------------------------------------------===
# A set of helpers to unpack a list of Python wrapper objects
# into a list of PyCObject wrapped objects, checking types along
# the way.
#===----------------------------------------------------------------------===
def unpack_gen(objlist, check_fn):
for obj in objlist: check_fn(obj)
return [ obj.ptr for obj in objlist ]
def unpack_gen_allow_none(objlist, check_fn):
for obj in objlist:
if obj is not None:
check_fn(obj)
return [ (obj.ptr if obj is not None else None) for obj in objlist ]
#===----------------------------------------------------------------------===
# Helper to wrap over iterables (LLVMFirstXXX, LLVMNextXXX). This used
# to be a generator, but that loses subscriptability of the result, so
# we now return a list.
#===----------------------------------------------------------------------===
def wrapiter(first, next, container, wrapper):
ret = []
ptr = first(container)
while ptr:
ret.append(wrapper(ptr))
ptr = next(ptr)
return ret
#===----------------------------------------------------------------------===
# Py2/3 compatibility string check
#===----------------------------------------------------------------------===
def _isstring_py2(x):
return isinstance(x, basestring)
def _isstring_py3(x):
return isinstance(x, str)
def _isstring_choose():
try:
basestring
return _isstring_py2
except:
return _isstring_py3
isstring = _isstring_choose()

193
llvm/_version.py Normal file
View file

@ -0,0 +1,193 @@
IN_LONG_VERSION_PY = True
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by github's download-from-tag
# feature). Distribution tarballs (build by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.7+ (https://github.com/warner/python-versioneer)
# these strings will be replaced by git during git-archive
git_refnames = "$Format:%d$"
git_full = "$Format:%H$"
GIT = "git"
import subprocess
import sys
def run_command(args, cwd=None, verbose=False):
try:
# remember shell=False, so use git.cmd on windows, not just git
p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
except EnvironmentError:
e = sys.exc_info()[1]
if verbose:
print("unable to run %s" % args[0])
print(e)
return None
stdout = p.communicate()[0].strip()
if sys.version >= '3':
stdout = stdout.decode()
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % args[0])
return None
return stdout
import sys
import re
import os.path
def get_expanded_variables(versionfile_source):
# the code embedded in _version.py can just fetch the value of these
# variables. When used from setup.py, we don't want to import
# _version.py, so we do it with a regexp instead. This function is not
# used from _version.py.
variables = {}
try:
for line in open(versionfile_source,"r").readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
variables["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
variables["full"] = mo.group(1)
except EnvironmentError:
pass
return variables
def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
refnames = variables["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
print("variables are unexpanded, not using")
return {} # unexpanded, so not in an unpacked git-archive tarball
refs = set([r.strip() for r in refnames.strip("()").split(",")])
for ref in list(refs):
if not re.search(r'\d', ref):
if verbose:
print("discarding '%s', no digits" % ref)
refs.discard(ref)
# Assume all version tags have a digit. git's %d expansion
# behaves like git log --decorate=short and strips out the
# refs/heads/ and refs/tags/ prefixes that would let us
# distinguish between branches and tags. By ignoring refnames
# without digits, we filter out many common branch names like
# "release" and "stabilization", as well as "HEAD" and "master".
if verbose:
print("remaining refs: %s" % ",".join(sorted(refs)))
for ref in sorted(refs):
# sorting will prefer e.g. "2.0" over "2.0rc1"
if ref.startswith(tag_prefix):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
return { "version": r,
"full": variables["full"].strip() }
# no suitable tags, so we use the full revision id
if verbose:
print("no suitable tags, using full revision id")
return { "version": variables["full"].strip(),
"full": variables["full"].strip() }
def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
# this runs 'git' from the root of the source tree. That either means
# someone ran a setup.py command (and this code is in versioneer.py, so
# IN_LONG_VERSION_PY=False, thus the containing directory is the root of
# the source tree), or someone ran a project-specific entry point (and
# this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the
# containing directory is somewhere deeper in the source tree). This only
# gets called if the git-archive 'subst' variables were *not* expanded,
# and _version.py hasn't already been rewritten with a short version
# string, meaning we're inside a checked out source tree.
try:
here = os.path.abspath(__file__)
except NameError:
# some py2exe/bbfreeze/non-CPython implementations don't do __file__
return {} # not always correct
# versionfile_source is the relative path from the top of the source tree
# (where the .git directory might live) to this file. Invert this to find
# the root from __file__.
root = here
if IN_LONG_VERSION_PY:
for i in range(len(versionfile_source.split("/"))):
root = os.path.dirname(root)
else:
root = os.path.dirname(here)
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
return {}
stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
cwd=root)
if stdout is None:
return {}
if not stdout.startswith(tag_prefix):
if verbose:
print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix))
return {}
tag = stdout[len(tag_prefix):]
stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)
if stdout is None:
return {}
full = stdout.strip()
if tag.endswith("-dirty"):
full += "-dirty"
return {"version": tag, "full": full}
def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):
if IN_LONG_VERSION_PY:
# We're running from _version.py. If it's from a source tree
# (execute-in-place), we can work upwards to find the root of the
# tree, and then check the parent directory for a version string. If
# it's in an installed application, there's no hope.
try:
here = os.path.abspath(__file__)
except NameError:
# py2exe/bbfreeze/non-CPython don't have __file__
return {} # without __file__, we have no hope
# versionfile_source is the relative path from the top of the source
# tree to _version.py. Invert this to find the root from __file__.
root = here
for i in range(len(versionfile_source.split("/"))):
root = os.path.dirname(root)
else:
# we're running from versioneer.py, which means we're running from
# the setup.py in a source tree. sys.argv[0] is setup.py in the root.
here = os.path.abspath(sys.argv[0])
root = os.path.dirname(here)
# Source tarballs conventionally unpack into a directory that includes
# both the project name and a version string.
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" %
(root, dirname, parentdir_prefix))
return None
return {"version": dirname[len(parentdir_prefix):], "full": ""}
tag_prefix = ""
parentdir_prefix = "llvmpy-"
versionfile_source = "llvm/_version.py"
def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
variables = { "refnames": git_refnames, "full": git_full }
ver = versions_from_expanded_variables(variables, tag_prefix, verbose)
if not ver:
ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)
if not ver:
ver = versions_from_parentdir(parentdir_prefix, versionfile_source,
verbose)
if not ver:
ver = default
return ver

View file

@ -1,134 +0,0 @@
#ifndef __CAPSULETHUNK_H
#define __CAPSULETHUNK_H
#if ( (PY_VERSION_HEX < 0x02070000) \
|| ((PY_VERSION_HEX >= 0x03000000) \
&& (PY_VERSION_HEX < 0x03010000)) )
#define __PyCapsule_GetField(capsule, field, default_value) \
( PyCapsule_CheckExact(capsule) \
? (((PyCObject *)capsule)->field) \
: (default_value) \
) \
#define __PyCapsule_SetField(capsule, field, value) \
( PyCapsule_CheckExact(capsule) \
? (((PyCObject *)capsule)->field = value), 1 \
: 0 \
) \
#define PyCapsule_Type PyCObject_Type
#define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
#define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule))
#define PyCapsule_New(pointer, name, destructor) \
(PyCObject_FromVoidPtr(pointer, destructor))
#define PyCapsule_GetPointer(capsule, name) \
(PyCObject_AsVoidPtr(capsule))
/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */
#define PyCapsule_SetPointer(capsule, pointer) \
__PyCapsule_SetField(capsule, cobject, pointer)
#define PyCapsule_GetDestructor(capsule) \
__PyCapsule_GetField(capsule, destructor)
#define PyCapsule_SetDestructor(capsule, dtor) \
__PyCapsule_SetField(capsule, destructor, dtor)
/*
* Sorry, there's simply no place
* to store a Capsule "name" in a CObject.
*/
#define PyCapsule_GetName(capsule) NULL
static int
PyCapsule_SetName(PyObject *capsule, const char *unused)
{
unused = unused;
PyErr_SetString(PyExc_NotImplementedError,
"can't use PyCapsule_SetName with CObjects");
return 1;
}
#define PyCapsule_GetContext(capsule) \
__PyCapsule_GetField(capsule, descr)
#define PyCapsule_SetContext(capsule, context) \
__PyCapsule_SetField(capsule, descr, context)
static void *
PyCapsule_Import(const char *name, int no_block)
{
PyObject *object = NULL;
void *return_value = NULL;
char *trace;
size_t name_length = (strlen(name) + 1) * sizeof(char);
char *name_dup = (char *)PyMem_MALLOC(name_length);
if (!name_dup) {
return NULL;
}
memcpy(name_dup, name, name_length);
trace = name_dup;
while (trace) {
char *dot = strchr(trace, '.');
if (dot) {
*dot++ = '\0';
}
if (object == NULL) {
if (no_block) {
object = PyImport_ImportModuleNoBlock(trace);
} else {
object = PyImport_ImportModule(trace);
if (!object) {
PyErr_Format(PyExc_ImportError,
"PyCapsule_Import could not "
"import module \"%s\"", trace);
}
}
} else {
PyObject *object2 = PyObject_GetAttrString(object, trace);
Py_DECREF(object);
object = object2;
}
if (!object) {
goto EXIT;
}
trace = dot;
}
if (PyCObject_Check(object)) {
PyCObject *cobject = (PyCObject *)object;
return_value = cobject->cobject;
} else {
PyErr_Format(PyExc_AttributeError,
"PyCapsule_Import \"%s\" is not valid",
name);
}
EXIT:
Py_XDECREF(object);
if (name_dup) {
PyMem_FREE(name_dup);
}
return return_value;
}
#endif /* #if PY_VERSION_HEX < 0x02070000 */
#endif /* __CAPSULETHUNK_H */

File diff suppressed because it is too large Load diff

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