Compare commits

...
Sign in to create a new pull request.

355 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
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
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
250 changed files with 18055 additions and 13326 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)"

102
CHANGELOG
View file

@ -1,5 +1,70 @@
2014-04-28 0.12.5:
---------------------
* Fixes memory leaks (#92)
* Fixes tarball (#99)
0.10, 18-Jan-2013:
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).
@ -8,16 +73,16 @@
* Added llvm.passes.build_pass_managers as a simpler way to build PassManagers.
0.7, in progress:
in progress, 0.7:
-----------------
* Add llvm.core.Argument.alignment property.
* Migrate to LLVM 2.8.
* Fix ffi link issue on darwin (Albert Mietus) (Issue #29).
* LLVM tutorial ported (Max Shawabkeh) (Issue #33).
0.6, 31-Aug-2010:
2010-08-31 0.6:
-----------------
* Add and remove function attributes (Krzysztof Goj) (Issue #21).
* Wrap fadd,fsub,fmul (Aaron S Lav) (Issue #31).
* Migrate to LLVM 2.7.
@ -36,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).
@ -54,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.
@ -67,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
@ -88,7 +153,6 @@
* Lots of cleanup.
0.1, 10-May-2008:
* Initial release.
2008-05-10 0.1:
-----------------
* Initial release

View file

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

View file

@ -10,32 +10,54 @@ http://www.llvmpy.org
Versions
--------
This package has been tested with LLVM 3.1 and 3.2, Python 2.7 and Python 3.2.
Other Python versions should work.
This package has been tested with LLVM 3.2, Python 2.6, 2.7 and 3.3.
Other Python versions may work.
Quickstart
----------
1. Get 3.1 or 3.2 version of LLVM, build it. Make sure ``--enable-pic`` is
passed to LLVM's ``configure``.
For LLVM 3.2, make sure that environment variable ``REQUIRES_RTTI=1`` is
defined when running ``make``. Otherwise, you may see "undefined symbol:
_ZTIN4llvm24PassRegistrationListenerE". Please refer to
http://llvm.org/docs/Packaging.html#c-features for details.
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' 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
-------

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
@ -86,7 +86,7 @@ if __name__ == '__main__':
tag = sh2('git describe --exact-match')
except CalledProcessError:
tag = "dev" # Fallback
startdir = os.getcwdu()
if not os.path.exists(pages_dir):
# init the repo

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 -----------------------------------------------------
@ -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.
#
# The short X.Y version.
version = '0.9'
# The full version, including alpha/beta/rc tags.
release = '0.9.0'
try:
import llvm
version_strs = llvm.__version__.split('.')
# The short X.Y version.
version = '.'.join(version_strs[:2])
# The full version, including alpha/beta/rc tags.
release = '%s.%s' % (version, '-'.join(version_strs[2].split('-')[:2]))
except ImportError:
version = 'unknown-version'
release = 'unknown-release'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View file

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

View file

@ -38,7 +38,7 @@ supported, for a variety of reasons.
Versions
--------
llvmpy 0.9 requires version 3.1 of LLVM. It may not work with
llvmpy 0.11.2 uses LLVM 3.2 (or at least 3.1). It may not work with
previous versions.
llvmpy has been built and tested with Python 2.7 and 3.2. It should work with
@ -65,22 +65,6 @@ It does not matter which compiler LLVM itself was built with (``g++``,
``llvm-g++`` or any other); llvmpy can be built with any compiler. It
has been tried only with gcc/g++ though.
LLVM and ``--enable-pic``
-------------------------
The result of an LLVM build is a set of static libraries and object
files. The llvmpy contains an extension package that is built into a
shared object (\_core.so) which links to these static libraries and
object files. It is therefore required that the LLVM libraries and
object files be built with the ``-fPIC`` option (generate position
independent code). Be sure to use the ``--enable-pic`` option while
configuring LLVM (default is no PIC), like this:
.. code-block:: bash
$ ~/llvm ./configure --enable-pic --enable-optimized
llvm-config
-----------
@ -98,13 +82,34 @@ is different from that of 'root', so even if ``llvm-config`` is in your
Steps
-----
Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to
LLVM's 'configure'.
1. Get and extract LLVM 3.2 source tarball from
`llvm.org <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.
**Note**: Use prefix to select the installation path. It is recommended
to separate your custom build from the default system package. Please
replace ``LLVM_INSTALL_PATH`` with your own path.
.. code-block:: bash
3. Run ``REQUIRES_RTTI=1 make`` to build.
$ git clone git@github.com:numba/llvmpy.git
$ cd llvmpy $ python setup.py install
**Note**: With LLVM 3.2, the default build configuration has C++ RTTI
disabled. However, llvmpy requires RTTI.
4. Get llvm-py and install it::
$ git clone git@github.com:llvmpy/llvmpy.git
$ cd llvmpy
$ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install
Run the tests::
$ python -c "import llvm; llvm.test()"
5. See documentation at 'http://www.llvmpy.org' and examples
under 'test'.

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

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

@ -121,8 +121,8 @@ to talk about how LLVM represents stack variables.
In LLVM, all memory accesses are explicit with load/store instructions,
and it is carefully designed not to have (or need) an "address-of"
operator. Notice how the type of the @G/@H global variables is actually
"i32\ *" even though the variable is defined as "i32". What this means
is that @G defines* space* for an i32 in the global data area, but its
"i32\*" even though the variable is defined as "i32". What this means
is that @G defines *space* for an i32 in the global data area, but its
*name* actually refers to the address for that space. Stack variables
work the same way, except that instead of being declared with global
variable definitions, they are declared with the `LLVM alloca
@ -133,11 +133,11 @@ instruction <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

@ -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,331 +26,338 @@ some examples:
tr = Type.float()
r1 = Constant.real(tr, "3.141592") # create from a string r2 =
Constant.real(tr, 1.61803399) # create from a Python float {%
endhighlight %}
# llvm.core.Constant
- This will become a table of contents (this text will be scraped).
{:toc}
Static factory methods
----------------------
``null(ty)``
~~~~~~~~~~~~
A null value (all zeros) of type ``ty``
``all_ones(ty)``
~~~~~~~~~~~~~~~~
All 1's value of type ``ty``
``undef(ty)``
~~~~~~~~~~~~~
An undefined value of type ``ty``
``int(ty, value)``
~~~~~~~~~~~~~~~~~~
Integer of type ``ty``, with value ``value`` (a Python int or long)
``int_signextend(ty, value)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Integer of signed type ``ty`` (use for signed types)
``real(ty, value)``
~~~~~~~~~~~~~~~~~~~
Floating point value of type ``ty``, with value ``value`` (a Python
float)
``stringz(value)``
~~~~~~~~~~~~~~~~~~
A null-terminated string. ``value`` is a Python string
``string(value)``
~~~~~~~~~~~~~~~~~
As ``string(ty)``, but not null terminated
``array(ty, consts)``
~~~~~~~~~~~~~~~~~~~~~
Array of type ``ty``, initialized with ``consts`` (an iterable yielding
``Constant`` objects of the appropriate type)
``struct(ty, consts)``
~~~~~~~~~~~~~~~~~~~~~~
Struct (unpacked) of type ``ty``, initialized with ``consts`` (an
iterable yielding ``Constant`` objects of the appropriate type)
``packed_struct(ty, consts)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As ``struct(ty, consts)`` but packed
``vector(consts)``
~~~~~~~~~~~~~~~~~~
Vector, initialized with ``consts`` (an iterable yielding ``Constant``
objects of the appropriate type)
``sizeof(ty)``
~~~~~~~~~~~~~~
Constant value representing the sizeof the type ``ty``
Methods
-------
The following operations on constants are supported. For more details on
any operation, consult the `Constant
Expressions <http://www.llvm.org/docs/LangRef.html#constantexprs>`_
section of the LLVM Language Reference.
``k.neg()``
~~~~~~~~~~~
negation, same as ``0 - k``
``k.not_()``
~~~~~~~~~~~~
1's complement of ``k``. Note trailing underscore.
``k.add(k2)``
~~~~~~~~~~~~~
``k + k2``, where ``k`` and ``k2`` are integers.
``k.fadd(k2)``
~~~~~~~~~~~~~~
``k + k2``, where ``k`` and ``k2`` are floating-point.
``k.sub(k2)``
~~~~~~~~~~~~~
``k - k2``, where ``k`` and ``k2`` are integers.
``k.fsub(k2)``
~~~~~~~~~~~~~~
``k - k2``, where ``k`` and ``k2`` are floating-point.
``k.mul(k2)``
~~~~~~~~~~~~~
``k * k2``, where ``k`` and ``k2`` are integers.
``k.fmul(k2)``
~~~~~~~~~~~~~~
``k * k2``, where ``k`` and ``k2`` are floating-point.
``k.udiv(k2)``
~~~~~~~~~~~~~~
Quotient of unsigned division of ``k`` with ``k2``
``k.sdiv(k2)``
~~~~~~~~~~~~~~
Quotient of signed division of ``k`` with ``k2``
``k.fdiv(k2)``
~~~~~~~~~~~~~~
Quotient of floating point division of ``k`` with ``k2``
``k.urem(k2)``
~~~~~~~~~~~~~~
Reminder of unsigned division of ``k`` with ``k2``
``k.srem(k2)``
~~~~~~~~~~~~~~
Reminder of signed division of ``k`` with ``k2``
``k.frem(k2)``
~~~~~~~~~~~~~~
Reminder of floating point division of ``k`` with ``k2``
``k.and_(k2)``
~~~~~~~~~~~~~~
Bitwise and of ``k`` and ``k2``. Note trailing underscore.
``k.or_(k2)``
~~~~~~~~~~~~~
Bitwise or of ``k`` and ``k2``. Note trailing underscore.
``k.xor(k2)``
~~~~~~~~~~~~~
Bitwise exclusive-or of ``k`` and ``k2``.
``k.icmp(icmp, k2)``
~~~~~~~~~~~~~~~~~~~~
Compare ``k`` with ``k2`` using the predicate ``icmp``. See
`here <comparision.html#icmp>`_ for list of predicates for integer
operands.
``k.fcmp(fcmp, k2)``
~~~~~~~~~~~~~~~~~~~~
Compare ``k`` with ``k2`` using the predicate ``fcmp``. See
`here <comparision.html#fcmp>`_ for list of predicates for real
operands.
``k.shl(k2)``
~~~~~~~~~~~~~
Shift ``k`` left by ``k2`` bits.
``k.lshr(k2)``
~~~~~~~~~~~~~~
Shift ``k`` logically right by ``k2`` bits (new bits are 0s).
``k.ashr(k2)``
~~~~~~~~~~~~~~
Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as
previous sign bit).
``k.gep(indices)``
~~~~~~~~~~~~~~~~~~
GEP, see `LLVM docs <http://www.llvm.org/docs/GetElementPtr.html>`_.
``k.trunc(ty)``
~~~~~~~~~~~~~~~
Truncate ``k`` to a type ``ty`` of lower bitwidth.
``k.sext(ty)``
~~~~~~~~~~~~~~
Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending
the sign bit.
``k.zext(ty)``
~~~~~~~~~~~~~~
Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are
0s.
``k.fptrunc(ty)``
~~~~~~~~~~~~~~~~~
Truncate floating point constant ``k`` to floating point type ``ty`` of
lower size than k's.
``k.fpext(ty)``
~~~~~~~~~~~~~~~
Extend floating point constant ``k`` to floating point type ``ty`` of
higher size than k's.
``k.uitofp(ty)``
~~~~~~~~~~~~~~~~
Convert an unsigned integer constant ``k`` to floating point constant of
type ``ty``.
``k.sitofp(ty)``
~~~~~~~~~~~~~~~~
Convert a signed integer constant ``k`` to floating point constant of
type ``ty``.
``k.fptoui(ty)``
~~~~~~~~~~~~~~~~
Convert a floating point constant ``k`` to an unsigned integer constant
of type ``ty``.
``k.fptosi(ty)``
~~~~~~~~~~~~~~~~
Convert a floating point constant ``k`` to a signed integer constant of
type ``ty``.
``k.ptrtoint(ty)``
~~~~~~~~~~~~~~~~~~
Convert a pointer constant ``k`` to an integer constant of type ``ty``.
``k.inttoptr(ty)``
~~~~~~~~~~~~~~~~~~
Convert an integer constant ``k`` to a pointer constant of type ``ty``.
``k.bitcast(ty)``
~~~~~~~~~~~~~~~~~
Convert ``k`` to a (equal-width) constant of type ``ty``.
``k.select(cond,k2,k3)``
~~~~~~~~~~~~~~~~~~~~~~~~
Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1,
else with ``k3``.
``k.extract_element(idx)``
~~~~~~~~~~~~~~~~~~~~~~~~~~
Extract value at ``idx`` (integer constant) from a vector constant
``k``.
``k.insert_element(k2,idx)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Insert value ``k2`` (scalar constant) at index ``idx`` (integer
constant) of vector constant ``k``.
``k.shuffle_vector(k2,mask)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Shuffle vector constant ``k`` based on vector constants ``k2`` and
``mask``.
--------------
# Other Constant Classes
The following subclasses of ``Constant`` do not provide additional
methods, **they serve only to provide richer type information.**
Subclass \| LLVM C++ Class \| Remarks \|
---------\|----------------\|---------\| ``ConstantExpr`` \|
``llvmConstantExpr`` \| A constant expression \|
``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero
constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer
constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point
constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array
constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A
structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \|
A vector constant \| ``ConstantPointerNull``\ \|
``llvmConstantPointerNull``\ \| All-zero pointer constant \|
``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of
LLVM IR \|
These types are helpful in ``isinstance`` checks, like so:
{% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) #
int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = {
k1, k1 };
assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray)
r1 = Constant.real(tr, "3.141592") # create from a string
r2 = Constant.real(tr, 1.61803399) # create from a Python float
# llvm.core.Constant
- This will become a table of contents (this text will be scraped).
{:toc}
Static factory methods
----------------------
``null(ty)``
~~~~~~~~~~~~
A null value (all zeros) of type ``ty``
``all_ones(ty)``
~~~~~~~~~~~~~~~~
All 1's value of type ``ty``
``undef(ty)``
~~~~~~~~~~~~~
An undefined value of type ``ty``
``int(ty, value)``
~~~~~~~~~~~~~~~~~~
Integer of type ``ty``, with value ``value`` (a Python int or long)
``int_signextend(ty, value)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Integer of signed type ``ty`` (use for signed types)
``real(ty, value)``
~~~~~~~~~~~~~~~~~~~
Floating point value of type ``ty``, with value ``value`` (a Python
float)
``stringz(value)``
~~~~~~~~~~~~~~~~~~
A null-terminated string. ``value`` is a Python string
``string(value)``
~~~~~~~~~~~~~~~~~
As ``string(ty)``, but not null terminated
``array(ty, consts)``
~~~~~~~~~~~~~~~~~~~~~
Array of type ``ty``, initialized with ``consts`` (an iterable yielding
``Constant`` objects of the appropriate type)
``struct(ty, consts)``
~~~~~~~~~~~~~~~~~~~~~~
Struct (unpacked) of type ``ty``, initialized with ``consts`` (an
iterable yielding ``Constant`` objects of the appropriate type)
``packed_struct(ty, consts)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As ``struct(ty, consts)`` but packed
``vector(consts)``
~~~~~~~~~~~~~~~~~~
Vector, initialized with ``consts`` (an iterable yielding ``Constant``
objects of the appropriate type)
``sizeof(ty)``
~~~~~~~~~~~~~~
Constant value representing the sizeof the type ``ty``
Methods
-------
The following operations on constants are supported. For more details on
any operation, consult the `Constant
Expressions <http://www.llvm.org/docs/LangRef.html#constantexprs>`_
section of the LLVM Language Reference.
``k.neg()``
~~~~~~~~~~~
negation, same as ``0 - k``
``k.not_()``
~~~~~~~~~~~~
1's complement of ``k``. Note trailing underscore.
``k.add(k2)``
~~~~~~~~~~~~~
``k + k2``, where ``k`` and ``k2`` are integers.
``k.fadd(k2)``
~~~~~~~~~~~~~~
``k + k2``, where ``k`` and ``k2`` are floating-point.
``k.sub(k2)``
~~~~~~~~~~~~~
``k - k2``, where ``k`` and ``k2`` are integers.
``k.fsub(k2)``
~~~~~~~~~~~~~~
``k - k2``, where ``k`` and ``k2`` are floating-point.
``k.mul(k2)``
~~~~~~~~~~~~~
``k * k2``, where ``k`` and ``k2`` are integers.
``k.fmul(k2)``
~~~~~~~~~~~~~~
``k * k2``, where ``k`` and ``k2`` are floating-point.
``k.udiv(k2)``
~~~~~~~~~~~~~~
Quotient of unsigned division of ``k`` with ``k2``
``k.sdiv(k2)``
~~~~~~~~~~~~~~
Quotient of signed division of ``k`` with ``k2``
``k.fdiv(k2)``
~~~~~~~~~~~~~~
Quotient of floating point division of ``k`` with ``k2``
``k.urem(k2)``
~~~~~~~~~~~~~~
Reminder of unsigned division of ``k`` with ``k2``
``k.srem(k2)``
~~~~~~~~~~~~~~
Reminder of signed division of ``k`` with ``k2``
``k.frem(k2)``
~~~~~~~~~~~~~~
Reminder of floating point division of ``k`` with ``k2``
``k.and_(k2)``
~~~~~~~~~~~~~~
Bitwise and of ``k`` and ``k2``. Note trailing underscore.
``k.or_(k2)``
~~~~~~~~~~~~~
Bitwise or of ``k`` and ``k2``. Note trailing underscore.
``k.xor(k2)``
~~~~~~~~~~~~~
Bitwise exclusive-or of ``k`` and ``k2``.
``k.icmp(icmp, k2)``
~~~~~~~~~~~~~~~~~~~~
Compare ``k`` with ``k2`` using the predicate ``icmp``. See
`here <comparision.html#icmp>`_ for list of predicates for integer
operands.
``k.fcmp(fcmp, k2)``
~~~~~~~~~~~~~~~~~~~~
Compare ``k`` with ``k2`` using the predicate ``fcmp``. See
`here <comparision.html#fcmp>`_ for list of predicates for real
operands.
``k.shl(k2)``
~~~~~~~~~~~~~
Shift ``k`` left by ``k2`` bits.
``k.lshr(k2)``
~~~~~~~~~~~~~~
Shift ``k`` logically right by ``k2`` bits (new bits are 0s).
``k.ashr(k2)``
~~~~~~~~~~~~~~
Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as
previous sign bit).
``k.gep(indices)``
~~~~~~~~~~~~~~~~~~
GEP, see `LLVM docs <http://www.llvm.org/docs/GetElementPtr.html>`_.
``k.trunc(ty)``
~~~~~~~~~~~~~~~
Truncate ``k`` to a type ``ty`` of lower bitwidth.
``k.sext(ty)``
~~~~~~~~~~~~~~
Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending
the sign bit.
``k.zext(ty)``
~~~~~~~~~~~~~~
Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are
0s.
``k.fptrunc(ty)``
~~~~~~~~~~~~~~~~~
Truncate floating point constant ``k`` to floating point type ``ty`` of
lower size than k's.
``k.fpext(ty)``
~~~~~~~~~~~~~~~
Extend floating point constant ``k`` to floating point type ``ty`` of
higher size than k's.
``k.uitofp(ty)``
~~~~~~~~~~~~~~~~
Convert an unsigned integer constant ``k`` to floating point constant of
type ``ty``.
``k.sitofp(ty)``
~~~~~~~~~~~~~~~~
Convert a signed integer constant ``k`` to floating point constant of
type ``ty``.
``k.fptoui(ty)``
~~~~~~~~~~~~~~~~
Convert a floating point constant ``k`` to an unsigned integer constant
of type ``ty``.
``k.fptosi(ty)``
~~~~~~~~~~~~~~~~
Convert a floating point constant ``k`` to a signed integer constant of
type ``ty``.
``k.ptrtoint(ty)``
~~~~~~~~~~~~~~~~~~
Convert a pointer constant ``k`` to an integer constant of type ``ty``.
``k.inttoptr(ty)``
~~~~~~~~~~~~~~~~~~
Convert an integer constant ``k`` to a pointer constant of type ``ty``.
``k.bitcast(ty)``
~~~~~~~~~~~~~~~~~
Convert ``k`` to a (equal-width) constant of type ``ty``.
``k.select(cond,k2,k3)``
~~~~~~~~~~~~~~~~~~~~~~~~
Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1,
else with ``k3``.
``k.extract_element(idx)``
~~~~~~~~~~~~~~~~~~~~~~~~~~
Extract value at ``idx`` (integer constant) from a vector constant
``k``.
``k.insert_element(k2,idx)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Insert value ``k2`` (scalar constant) at index ``idx`` (integer
constant) of vector constant ``k``.
``k.shuffle_vector(k2,mask)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Shuffle vector constant ``k`` based on vector constants ``k2`` and
``mask``.
--------------
# Other Constant Classes
The following subclasses of ``Constant`` do not provide additional
methods, **they serve only to provide richer type information.**
Subclass \| LLVM C++ Class \| Remarks \|
---------\|----------------\|---------\| ``ConstantExpr`` \|
``llvmConstantExpr`` \| A constant expression \|
``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero
constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer
constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point
constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array
constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A
structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \|
A vector constant \| ``ConstantPointerNull``\ \|
``llvmConstantPointerNull``\ \| All-zero pointer constant \|
``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of
LLVM IR \|
These types are helpful in ``isinstance`` checks, like so:
{% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) #
int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = {
k1, k1 };
assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray)
Automatically Generated Documentation
-------------------------------------
.. 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

@ -1,5 +1,5 @@
llvm_cbuilder
=========
=============
llvm_cbuilder is a set of Python-contexts you can use to write C-like
constructs in Python which generates llvmpy code directly.

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

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

152
example/vector_instr.py Normal file
View file

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

View file

@ -1,17 +1,16 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import opcode
import opcode_util
from . import opcode_util
import pprint
from bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin
from control_flow import ControlFlowGraph
from .bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin
from .control_flow import ControlFlowGraph
# ______________________________________________________________________
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
'''Visitor responsible for traversing a bytecode flow object and
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
'''Visitor responsible for traversing a bytecode basic block map and
building a control flow graph (CFG).
The primary purpose of this transformation is to create a CFG,
@ -27,21 +26,26 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
del self.nargs
return ret_val
def enter_flow_object (self, flow):
super(ControlFlowBuilder, self).enter_flow_object(flow)
self.flow = flow
def enter_blocks (self, blocks):
super(ControlFlowBuilder, self).enter_blocks(blocks)
self.blocks = blocks
self.block_list = list(blocks.keys())
self.block_list.sort()
self.cfg = ControlFlowGraph()
for block in flow.keys():
self.cfg.add_block(block, flow[block])
self.loop_stack = []
for block in self.block_list:
self.cfg.add_block(block, blocks[block])
def exit_flow_object (self, flow):
super(ControlFlowBuilder, self).exit_flow_object(flow)
assert self.flow == flow
def exit_blocks (self, blocks):
super(ControlFlowBuilder, self).exit_blocks(blocks)
assert self.blocks == blocks
self.cfg.compute_dataflow()
self.cfg.update_for_ssa()
ret_val = self.cfg
del self.loop_stack
del self.cfg
del self.flow
del self.block_list
del self.blocks
return ret_val
def enter_block (self, block):
@ -58,13 +62,15 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
def exit_block (self, block):
assert block == self.block
del self.block
i, op, opname, arg, args = self.flow[block][-1]
i, op, arg = self.blocks[block][-1]
opname = opcode.opname[op]
if op in opcode.hasjabs:
self.cfg.add_edge(block, arg)
elif op in opcode.hasjrel:
self.cfg.add_edge(block, i + arg + 3)
elif opname == 'BREAK_LOOP':
self.cfg.add_edge(block, arg)
loop_i, _, loop_arg = self.loop_stack[-1]
self.cfg.add_edge(block, loop_i + loop_arg + 3)
elif opname != 'RETURN_VALUE':
self.cfg.add_edge(block, self._get_next_block(block))
if op in opcode_util.hascbranch:
@ -80,15 +86,24 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args,
**kws)
def op_SETUP_LOOP (self, i, op, arg, *args, **kws):
self.loop_stack.append((i, op, arg))
return super(ControlFlowBuilder, self).op_SETUP_LOOP(i, op, arg, *args,
**kws)
def op_POP_BLOCK (self, i, op, arg, *args, **kws):
self.loop_stack.pop()
return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args,
**kws)
# ______________________________________________________________________
def build_cfg (func):
'''Given a Python function, create a bytecode flow, visit the flow
object, and return a control flow graph.'''
import byte_flow
return ControlFlowBuilder().visit(
byte_flow.build_flow(func),
opcode_util.get_code_object(func).co_argcount)
co_obj = opcode_util.get_code_object(func)
return ControlFlowBuilder().visit(opcode_util.build_basic_blocks(co_obj),
co_obj.co_argcount)
# ______________________________________________________________________
# Main (self-test) routine

View file

@ -1,16 +1,15 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import dis
import opcode
from bytecode_visitor import BytecodeIterVisitor
import opcode_util
from .bytecode_visitor import BasicBlockVisitor
from . import opcode_util
# ______________________________________________________________________
class BytecodeFlowBuilder (BytecodeIterVisitor):
'''Transforms a bytecode vector into a bytecode "flow tree".
class BytecodeFlowBuilder (BasicBlockVisitor):
'''Transforms a CFG into a bytecode "flow tree".
The flow tree is a Python dictionary, described loosely by the
following set of productions:
@ -36,6 +35,8 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
if pops:
if pops < 0:
pops = arg - pops - 1
assert pops <= len(self.stack), ("Stack underflow at instruction "
"%d (%s)!" % (i, opname))
stk_args = self.stack[-pops:]
del self.stack[-pops:]
else:
@ -51,27 +52,50 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
opname, pops, pushes, appends = self.opmap[op]
return self._visit_op(i, op, arg, opname, pops, pushes, appends)
def enter_code_object (self, co_obj):
labels = dis.findlabels(co_obj.co_code)
labels = opcode_util.extendlabels(co_obj.co_code, labels)
def visit_cfg (self, cfg):
self.cfg = cfg
ret_val = self.visit(cfg.blocks)
del self.cfg
return ret_val
def enter_blocks (self, blocks):
labels = list(blocks.keys())
labels.sort()
self.blocks = dict((index, [])
for index in labels)
self.stack = []
self.loop_stack = []
self.blocks[0] = self.block = []
self.stacks = {}
def exit_code_object (self, co_obj):
def exit_blocks (self, blocks):
ret_val = self.blocks
del self.stack
del self.stacks
del self.loop_stack
del self.block
del self.blocks
return ret_val
def visit_op (self, i, op, arg):
if i in self.blocks:
self.block = self.blocks[i]
return super(BytecodeFlowBuilder, self).visit_op(i, op, arg)
def enter_block (self, block):
self.block_no = block
self.block = self.blocks[block]
in_blocks = self.cfg.blocks_in[block]
if len(in_blocks) == 0:
self.stack = []
else:
pred_stack = None
for pred in in_blocks:
if pred in self.stacks:
pred_stack = self.stacks[pred]
break
if pred_stack is not None:
self.stack = pred_stack[:]
else:
raise NotImplementedError()
def exit_block (self, block):
assert self.block_no == block
self.stacks[block] = self.stack
del self.stack
del self.block
del self.block_no
op_BINARY_ADD = _op
op_BINARY_AND = _op
@ -140,8 +164,14 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
op_INPLACE_XOR = _op
op_JUMP_ABSOLUTE = _op
op_JUMP_FORWARD = _op
op_JUMP_IF_FALSE = _op
op_JUMP_IF_TRUE = _op
def op_JUMP_IF_FALSE (self, i, op, arg):
opname, _, _, _ = self.opmap[op]
ret_val = (i, op, opname, arg, [self.stack[-1]])
self.block.append(ret_val)
return ret_val
op_JUMP_IF_TRUE = op_JUMP_IF_FALSE
op_LIST_APPEND = _op
op_LOAD_ATTR = _op
op_LOAD_CLOSURE = _op
@ -211,7 +241,9 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
def build_flow (func):
'''Given a Python function, return a bytecode flow tree for that
function.'''
return BytecodeFlowBuilder().visit(opcode_util.get_code_object(func))
import byte_control
cfg = byte_control.build_cfg(func)
return BytecodeFlowBuilder().visit_cfg(cfg)
# ______________________________________________________________________
# Main (self-test) routine

View file

@ -1,22 +1,21 @@
#! /usr/bin/env python
# ______________________________________________________________________
'''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
import opcode_util
import bytetype
from bytecode_visitor import BytecodeFlowVisitor
from byte_flow import BytecodeFlowBuilder
from byte_control import ControlFlowBuilder
from phi_injector import PhiInjector, synthetic_opname
from . import opcode_util
from . import bytetype
from .bytecode_visitor import BytecodeFlowVisitor
from .byte_flow import BytecodeFlowBuilder
from .byte_control import ControlFlowBuilder
from .phi_injector import PhiInjector, synthetic_opname
# ______________________________________________________________________
# Module data
@ -153,7 +152,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
environment.'''
if llvm_type is None:
if llvm_function is None:
llvm_type = lc.Type.function(lvoid, ())
llvm_type = lc.Type.function(bytetype.lvoid, ())
else:
llvm_type = llvm_function.type.pointee
if env is None:
@ -178,7 +177,8 @@ class LLVMTranslator (BytecodeFlowVisitor):
self.globals = func_globals
nargs = self.code_obj.co_argcount
self.cfg = self.control_flow_builder.visit(
self.bytecode_flow_builder.visit(self.code_obj), nargs)
opcode_util.build_basic_blocks(self.code_obj), nargs)
self.cfg.blocks = self.bytecode_flow_builder.visit_cfg(self.cfg)
self.llvm_function = llvm_function
flow = self.phi_injector.visit_cfg(self.cfg, nargs)
ret_val = self.visit(flow)
@ -224,6 +224,12 @@ class LLVMTranslator (BytecodeFlowVisitor):
return ret_val
def exit_block (self, block):
bb_instrs = self.llvm_block.instructions
if ((len(bb_instrs) == 0) or
(not bb_instrs[-1].is_terminator)):
out_blocks = list(self.cfg.blocks_out[block])
assert len(out_blocks) == 1
self.builder.branch(self.llvm_blocks[out_blocks[0]])
del self.llvm_block
del self.builder
@ -449,7 +455,11 @@ class LLVMTranslator (BytecodeFlowVisitor):
return [self.builder.branch(self.llvm_blocks[i + arg + 3])]
def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE")
cond = args[0]
block_false = self.llvm_blocks[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")

View file

@ -1,10 +1,9 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import itertools
import opcode
from opcode_util import itercode
from .opcode_util import itercode
# ______________________________________________________________________
@ -164,6 +163,32 @@ class BytecodeIterVisitor (BytecodeVisitor):
# ______________________________________________________________________
class BasicBlockVisitor (BytecodeVisitor):
def visit (self, blocks):
self.enter_blocks(blocks)
block_indices = list(blocks.keys())
block_indices.sort()
for block_index in block_indices:
self.enter_block(block_index)
for i, op, arg in blocks[block_index]:
self.visit_op(i, op, arg)
self.exit_block(block_index)
return self.exit_blocks(blocks)
def enter_blocks (self, blocks):
pass
def exit_blocks (self, blocks):
pass
def enter_block (self, block_index):
pass
def exit_block (self, block_index):
pass
# ______________________________________________________________________
class BytecodeFlowVisitor (BytecodeVisitor):
def visit (self, flow):
self.block_list = list(flow.keys())

View file

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

View file

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

View file

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

View file

@ -1,6 +1,5 @@
#! /usr/bin/env python
# ______________________________________________________________________
from __future__ import absolute_import
import sys
import os.path
import imp
@ -10,13 +9,12 @@ import types
import llvm.core as lc
import llvm.ee as le
import bytetype
import byte_translator
from pyaddfunc import pyaddfunc
from . import bytetype, byte_translator
from .pyaddfunc import pyaddfunc
LLVM_TO_INT_PARSE_STR_MAP = {
8 : 'b',
16 : 'h',
16 : 'h',
32 : 'i', # Note that on 32-bit systems sizeof(int) == sizeof(long)
64 : 'L', # Seeing sizeof(long long) == 8 on both 32 and 64-bit platforms
}

View file

@ -1,4 +1,3 @@
#! /usr/bin/env python
# ______________________________________________________________________
import dis
@ -79,9 +78,9 @@ OPCODE_MAP = {
'INPLACE_XOR': (2, 1, None),
'JUMP_ABSOLUTE': (0, None, 1),
'JUMP_FORWARD': (0, None, 1),
'JUMP_IF_FALSE': (1, None, 1),
'JUMP_IF_FALSE': (1, 1, 1),
'JUMP_IF_FALSE_OR_POP': (None, None, None),
'JUMP_IF_TRUE': (1, None, 1),
'JUMP_IF_TRUE': (1, 1, 1),
'JUMP_IF_TRUE_OR_POP': (None, None, None),
'LIST_APPEND': (2, 0, 1),
'LOAD_ATTR': (1, 1, None),
@ -148,7 +147,7 @@ OPCODE_MAP = {
# ______________________________________________________________________
# Module functions
def itercode(code):
def itercode(code, start = 0):
"""Return a generator of byte-offset, opcode, and argument
from a byte-code-string
"""
@ -159,7 +158,7 @@ def itercode(code):
n = len(code)
while i < n:
op = code[i]
num = i
num = i + start
i = i + 1
oparg = None
if op >= opcode.HAVE_ARGUMENT:
@ -211,5 +210,16 @@ def extendlabels(code, labels = None):
def get_code_object (func):
return getattr(func, '__code__', getattr(func, 'func_code', None))
# ______________________________________________________________________
def build_basic_blocks (co_obj):
co_code = co_obj.co_code
labels = extendlabels(co_code, dis.findlabels(co_code))
labels.sort()
blocks = dict((index, list(itercode(co_code[index:next_index], index)))
for index, next_index in zip([0] + labels,
labels + [len(co_code)]))
return blocks
# ______________________________________________________________________
# End of opcode_util.py

View file

@ -1,7 +1,6 @@
#! /usr/bin/env python
# ______________________________________________________________________
from bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin
from .bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin
# ______________________________________________________________________
@ -127,9 +126,10 @@ class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
def inject_phis (func):
'''Given a Python function, return a bytecode flow object that has
been transformed by a fresh PhiInjector instance.'''
import byte_control
import byte_control, byte_flow
argcount = byte_control.opcode_util.get_code_object(func).co_argcount
cfg = byte_control.build_cfg(func)
cfg.blocks = byte_flow.BytecodeFlowBuilder().visit_cfg(cfg)
return PhiInjector().visit_cfg(cfg, argcount)
# ______________________________________________________________________

View file

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

View file

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

View file

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

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,78 +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
LLVMObject
LLVMRuntimeDyld
LLVMScalarOpts
LLVMSelectionDAG
LLVMSupport
LLVMTarget
LLVMTransformUtils
LLVMVectorize
LLVMX86AsmParser
LLVMX86AsmPrinter
LLVMX86CodeGen
LLVMX86Desc
LLVMX86Info
LLVMX86Utils
Advapi32
Shell32
""".split():
print('-l%s' % lib)
llvmbin = find_path_of('llvm-tblgen.exe')
if os.path.exists(os.path.join(llvmbin, '../lib/LLVMPTXCodeGen.lib')):
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
else:
raise RuntimeError('Unrecognized llvm-config command %s' % sys.argv[1])
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:
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,152 +1,47 @@
"""
Common classes related to LLVM.
"""
__version__ = '0.10.0'
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
from weakref import WeakValueDictionary
import _core
from llvmpy import extra
#===----------------------------------------------------------------------===
# LLVM Version
#===----------------------------------------------------------------------===
version = extra.get_llvm_version()
del extra
version = _core.LLVMGetVersion()
class Wrapper(object):
__slots__ = '__ptr'
def require_version_at_least(major, minor):
'''Sentry to guard version requirement
'''
if version < (major, minor):
raise Exception(major, minor)
def __init__(self, ptr):
assert ptr
self.__ptr = ptr
#===----------------------------------------------------------------------===
# Exceptions
#===----------------------------------------------------------------------===
@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
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.
"""
from llvm.test_llvmpy import run
Run self-test, and return the number of failures + errors
"""
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,86 +0,0 @@
#include <Python.h>
#include <llvm/Support/Dwarf.h>
namespace llvmpy {
namespace dwarf {
using namespace llvm::dwarf;
const char *constant_names[] = {
"LLVMDebugVersion",
#define define(x) #x,
#include "_dwarf.h"
#undef define
};
int constant_values[] = {
llvm::LLVMDebugVersion,
#define define(x) x,
#include "_dwarf.h"
#undef define
};
enum enum_values {
__llvmpy_LLVMDebugVersion,
#define define(x) __llvmpy_##x,
#include "_dwarf.h"
#undef define
NVALUES /* Get the number of constants */
};
} // End namespace dwarf
int
set_dwarf_constants(PyObject *module)
{
int i;
for (i = 0; i < dwarf::NVALUES; i++) {
if (PyModule_AddIntConstant(module, dwarf::constant_names[i],
dwarf::constant_values[i]) > 0)
return -1;
}
return 0;
}
} // End namespace llvmpy
#if (PY_MAJOR_VERSION >= 3)
struct PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
"_dwarf",
NULL,
-1,
NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
#define INITERROR return NULL
PyObject *PyInit__dwarf(void)
#else
#define INITERROR return
PyMODINIT_FUNC init_dwarf(void)
#endif
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create( &module_def );
#else
PyObject *module = Py_InitModule("_dwarf", NULL);
#endif
if (module == NULL)
INITERROR;
if (llvmpy::set_dwarf_constants(module) < 0)
INITERROR;
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}

View file

@ -1,101 +0,0 @@
/* Dwarf constant wrapping. See include/llvm/Support/Dwarf.h */
define(DWARF_VERSION)
/* Dwarf tags */
define(DW_TAG_array_type)
define(DW_TAG_class_type)
define(DW_TAG_entry_point)
define(DW_TAG_enumeration_type)
define(DW_TAG_formal_parameter)
define(DW_TAG_imported_declaration)
define(DW_TAG_label)
define(DW_TAG_lexical_block)
define(DW_TAG_member)
define(DW_TAG_pointer_type)
define(DW_TAG_reference_type)
define(DW_TAG_compile_unit)
define(DW_TAG_string_type)
define(DW_TAG_structure_type)
define(DW_TAG_subroutine_type)
define(DW_TAG_typedef)
define(DW_TAG_union_type)
define(DW_TAG_unspecified_parameters)
define(DW_TAG_variant)
define(DW_TAG_common_block)
define(DW_TAG_common_inclusion)
define(DW_TAG_inheritance)
define(DW_TAG_inlined_subroutine)
define(DW_TAG_module)
define(DW_TAG_ptr_to_member_type)
define(DW_TAG_set_type)
define(DW_TAG_subrange_type)
define(DW_TAG_with_stmt)
define(DW_TAG_access_declaration)
define(DW_TAG_base_type)
define(DW_TAG_catch_block)
define(DW_TAG_const_type)
define(DW_TAG_constant)
define(DW_TAG_enumerator)
define(DW_TAG_file_type)
define(DW_TAG_friend)
define(DW_TAG_namelist)
define(DW_TAG_namelist_item)
define(DW_TAG_packed_type)
define(DW_TAG_subprogram)
define(DW_TAG_template_type_parameter)
define(DW_TAG_template_value_parameter)
define(DW_TAG_thrown_type)
define(DW_TAG_try_block)
define(DW_TAG_variant_part)
define(DW_TAG_variable)
define(DW_TAG_volatile_type)
define(DW_TAG_dwarf_procedure)
define(DW_TAG_restrict_type)
define(DW_TAG_interface_type)
define(DW_TAG_namespace)
define(DW_TAG_imported_module)
define(DW_TAG_unspecified_type)
define(DW_TAG_partial_unit)
define(DW_TAG_imported_unit)
define(DW_TAG_condition)
define(DW_TAG_shared_type)
define(DW_TAG_type_unit)
define(DW_TAG_rvalue_reference_type)
define(DW_TAG_template_alias)
define(DW_TAG_MIPS_loop)
define(DW_TAG_format_label)
define(DW_TAG_function_template)
define(DW_TAG_class_template)
define(DW_TAG_GNU_template_template_param)
define(DW_TAG_GNU_template_parameter_pack)
define(DW_TAG_GNU_formal_parameter_pack)
define(DW_TAG_lo_user)
define(DW_TAG_APPLE_property)
define(DW_TAG_hi_user)
/* Dwarf language constants */
define(DW_LANG_C89)
define(DW_LANG_C)
define(DW_LANG_Ada83)
define(DW_LANG_C_plus_plus)
define(DW_LANG_Cobol74)
define(DW_LANG_Cobol85)
define(DW_LANG_Fortran77)
define(DW_LANG_Fortran90)
define(DW_LANG_Pascal83)
define(DW_LANG_Modula2)
define(DW_LANG_Java)
define(DW_LANG_C99)
define(DW_LANG_Ada95)
define(DW_LANG_Fortran95)
define(DW_LANG_PLI)
define(DW_LANG_ObjC)
define(DW_LANG_ObjC_plus_plus)
define(DW_LANG_UPC)
define(DW_LANG_D)
define(DW_LANG_Python)
define(DW_LANG_lo_user)
define(DW_LANG_Mips_Assembler)
define(DW_LANG_hi_user)

View file

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

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

View file

@ -1,398 +0,0 @@
"""
Support for debug info metadata.
"""
import functools
import llvm.core
from llvm import _dwarf
#----------------------------------------------------------------------------
# Some types and type checking functions
#----------------------------------------------------------------------------
int32_t = llvm.core.Type.int(32)
bool_t = llvm.core.Type.int(1)
p_int32_t = llvm.core.Type.pointer(int32_t)
null = llvm.core.Constant.null(p_int32_t)
i32 = functools.partial(llvm.core.Constant.int, int32_t)
i1 = functools.partial(llvm.core.Constant.int, bool_t)
def is_md(value):
return isinstance(value, (llvm.core.MetaData, llvm.core.NamedMetaData,
llvm.core.Value))
def is_mdstr(value):
return isinstance(value, (llvm.core.MetaDataString, llvm.core.Value))
#----------------------------------------------------------------------------
# Callbacks for debug type descriptors
#----------------------------------------------------------------------------
def get_i32(llvm_module, value):
return i32(value)
def get_i1(llvm_module, value):
return i1(value)
def get_md(llvm_module, value):
if is_md(value):
return value
return value.get_metadata(llvm_module)
def get_mdstr(llvm_module, value):
if is_mdstr(value):
return value
return llvm.core.MetaDataString.get(llvm_module, value)
def get_mdlist(llvm_module, value):
if isinstance(value, list):
value = MDList([value])
return get_md(llvm_module, value)
def get_lfunc(llvm_module, lfunc):
assert lfunc.module is llvm_module
return lfunc
#----------------------------------------------------------------------------
# Debug descriptors that generate LLVM Metadata
#----------------------------------------------------------------------------
class desc(object):
"""
Descriptor of a debug field.
field_name:
name of the field (keyword argument name)
build_metadata:
metadata callback :: (llvm_module, Python value) -> LLVM Value
default:
default value for this field
"""
def __init__(self, field_name, build_metadata, default=None):
self.field_name = field_name
self.build_metadata = build_metadata
self.default = default
def build_operand_list(type_descriptors, idx2name, operands, kwargs):
"""
Build the list of operands from the positional and keyword arguments
to a DebugInfoDescriptor.
E.g. FileDescriptor("foo.c", "/path/to/file", compile_unit=compile_unit)
idx2name: {0 : 'source_filename',
1 : 'source_filedir',
2 : 'compile_unit' }
operands: ["foo.c", "/path/to/file"]
kwargs: { 'compile_unit' : compile_unit }
"""
for i in range(len(operands), len(type_descriptors)):
name = idx2name[i]
if name in kwargs:
op = kwargs[name]
else:
typedesc = type_descriptors[i]
assert typedesc.default is not None, (
"No value found for field %s" % typedesc.field_name)
op = typedesc.default
operands.append(op)
return operands
class DebugInfoDescriptor(object):
"""
Base class to describe a debug info descriptor.
See http://llvm.org/docs/SourceLevelDebugging.html
"""
type_descriptors = None # [desc(...)]
idx2name = None # { "field_idx" : field_name }
name2idx = None # { "field_name" : field_idx }
# Whether the debug descriptor is allowed to be incomplete
# The policy seems unclear ?
accept_optional_data = False
def __init__(self, *args, **kwargs):
self.class_init()
self.metadata_cache = {}
operands = list(args)
if kwargs or not self.accept_optional_data:
operands = build_operand_list(self.type_descriptors,
self.idx2name, operands, kwargs)
self.operands = operands
self.operands_dict = dict(
(typedesc.field_name, operand)
for typedesc, operand in zip(self.type_descriptors, operands))
@classmethod
def class_init(cls):
if cls.idx2name is None and cls.type_descriptors is not None:
cls.name2idx = {}
cls.idx2name = {}
for i, typedesc in enumerate(cls.type_descriptors):
cls.name2idx[typedesc.field_name] = i
cls.idx2name[i] = typedesc.field_name
def add_metadata(self, metadata_name, metadata):
"""
Replace a metadata value in the operand list.
"""
idx = self.name2idx[metadata_name]
self.operands[idx] = metadata
#------------------------------------------------------------------------
# Define metadata in a module
#------------------------------------------------------------------------
def get_metadata(self, llvm_module):
"""
Get an existing metadata node for the given LLVM module, or build
one from this instance.
"""
if llvm_module in self.metadata_cache:
node = self.metadata_cache[llvm_module]
else:
node = self.build_metadata(llvm_module)
self.metadata_cache[llvm_module] = node
return node
def build_metadata(self, llvm_module):
"Build a metadata node for the given LLVM module"
mdops = []
for type_desc, operand in zip(self.type_descriptors, self.operands):
try:
field_value = type_desc.build_metadata(llvm_module, operand)
except Exception, e:
if type_desc.build_metadata is get_md:
raise
raise ValueError("Invalid value for field %r: %s" % (
type_desc.field_name, e))
mdops.append(field_value)
return llvm.core.MetaData.get(llvm_module, mdops)
def define(self, llvm_module):
"""
Define this debug descriptor as named debug metadata for the module.
"""
md = self.get_metadata(llvm_module)
llvm.core.MetaData.add_named_operand(llvm_module, "dbg", md)
#----------------------------------------------------------------------------
# Convenience descriptors
#----------------------------------------------------------------------------
class MDList(DebugInfoDescriptor):
"""
[MetaData]
"""
def __init__(self, operands):
self.type_descriptors = [desc("op", get_md)] * len(operands)
super(MDList, self).__init__(*operands)
empty = MDList([])
#----------------------------------------------------------------------------
# Dwarf Debug descriptors
#----------------------------------------------------------------------------
class CompileUnitDescriptor(DebugInfoDescriptor):
"""
!0 = metadata !{
i32, ;; Tag = 17 + LLVMDebugVersion (DW_TAG_compile_unit)
i32, ;; Unused field.
i32, ;; DWARF language identifier (ex. DW_LANG_C89)
metadata, ;; Source file name
metadata, ;; Source file directory (includes trailing slash)
metadata ;; Producer (ex. "4.0.1 LLVM (LLVM research group)")
i1, ;; True if this is a main compile unit.
i1, ;; True if this is optimized.
metadata, ;; Flags
i32 ;; Runtime version
metadata ;; List of enums types
metadata ;; List of retained types
metadata ;; List of subprograms
metadata ;; List of global variables
}
"""
accept_optional_data = True
type_descriptors = [
desc("tag", get_i32),
desc("unused", get_i32),
# Positional argument list starts here:
desc("langid", get_i32),
desc("source_filename", get_mdstr),
desc("source_filedir", get_mdstr),
desc("producer", get_mdstr),
desc("is_main", get_i1, default=False),
desc("is_optimized", get_i1, default=False),
desc("compile_flags", get_mdstr, default=""),
desc("runtime_version", get_i32, default=0),
desc("enum_types", get_mdlist, default=empty),
desc("retained_types", get_mdlist, default=empty),
desc("subprograms", get_mdlist, default=empty),
desc("global_vars", get_mdlist, default=empty),
]
def __init__(self, *args, **kwargs):
super(CompileUnitDescriptor, self).__init__(
_dwarf.DW_TAG_compile_unit + _dwarf.LLVMDebugVersion, # tag
0, # unused
*args, **kwargs)
def define(self, llvm_module):
"""
Define this debug descriptor as named debug metadata for the module.
"""
md = self.get_metadata(llvm_module)
llvm.core.MetaData.add_named_operand(llvm_module, "llvm.dbg.cu", md)
class FileDescriptor(DebugInfoDescriptor):
"""
!0 = metadata !{
i32, ;; Tag = 41 + LLVMDebugVersion (DW_TAG_file_type)
metadata, ;; Source file name
metadata, ;; Source file directory (includes trailing slash)
metadata ;; Unused
}
"""
type_descriptors = [
desc("tag", get_i32),
# Positional argument list starts here:
desc("source_filename", get_mdstr),
desc("source_filedir", get_mdstr),
desc("compile_unit", get_md, default=null),
]
def __init__(self, *args, **kwargs):
super(FileDescriptor, self).__init__(
_dwarf.DW_TAG_file_type + _dwarf.LLVMDebugVersion, # Tag
*args, **kwargs)
@classmethod
def from_compileunit(cls, compile_unit_descriptor):
return cls(compile_unit_descriptor.operands_dict["source_filename"],
compile_unit_descriptor.operands_dict["source_filedir"],
compile_unit_descriptor)
class SubprogramDescriptor(DebugInfoDescriptor):
"""
!2 = metadata !{
i32, ;; Tag = 46 + LLVMDebugVersion (DW_TAG_subprogram)
i32, ;; Unused field.
metadata, ;; Reference to context descriptor
metadata, ;; Name
metadata, ;; Display name (fully qualified C++ name)
metadata, ;; MIPS linkage name (for C++)
metadata, ;; Reference to file where defined
i32, ;; Line number where defined
metadata, ;; Reference to type descriptor
i1, ;; True if the global is local to compile unit (static)
i1, ;; True if the global is defined in the compile unit (not extern)
i32, ;; Line number where the scope of the subprogram begins
i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual
i32, ;; Index into a virtual function
metadata, ;; indicates which base type contains the vtable pointer for the
;; derived class
i32, ;; Flags - Artifical, Private, Protected, Explicit, Prototyped.
i1, ;; isOptimized
Function * , ;; Pointer to LLVM function
metadata, ;; Lists function template parameters
metadata, ;; Function declaration descriptor
metadata ;; List of function variables
}
"""
accept_optional_data = True
type_descriptors = [
desc("tag", get_i32),
desc("unused", get_i32),
# Positional argument list starts here:
desc("file_desc", get_md),
desc("name", get_mdstr),
desc("display_name", get_mdstr),
desc("mips_linkage_name", get_mdstr),
desc("source_file_ref", get_md),
desc("line_number", get_i32),
desc("signature", get_md),
desc("is_local", get_i1, default=False),
desc("is_definition", get_i1, default=True),
desc("virtual_attribute", get_i32, default=0),
desc("virtual_index", get_i32, default=0),
desc("virttab", get_i32, default=0),
desc("flags", get_i32, default=0),
desc("is_optimized", get_i1, default=False),
desc("llvm_func", get_lfunc),
# Template params
# Func decl
# Func vars
]
def __init__(self, *args, **kwargs):
super(SubprogramDescriptor, self).__init__(
_dwarf.DW_TAG_subprogram + _dwarf.LLVMDebugVersion, # Tag
0, # Unused
*args, **kwargs)
class BlockDescriptor(DebugInfoDescriptor):
"""
!3 = metadata !{
i32, ;; Tag = 11 + LLVMDebugVersion (DW_TAG_lexical_block)
metadata,;; Reference to context descriptor
i32, ;; Line number
i32 ;; Column number
}
"""
type_descriptors = [
desc("tag", get_i32),
# Positional argument list starts here:
desc("context_descr", get_md), # FileDescr | BlockDescr |
# SubprogDescr | ComputeUnit
desc("line_number", get_i32),
desc("col_number", get_i32),
]
def __init__(self, *args, **kwargs):
super(BlockDescriptor, self).__init__(
_dwarf.DW_TAG_lexical_block + _dwarf.LLVMDebugVersion,
*args, **kwargs)
class PositionInfoDescriptor(DebugInfoDescriptor):
"""
line number, column number, scope, and original scope
"""
type_descriptors = [
desc("line_number", get_i32),
desc("col_number", get_i32),
desc("context_descr", get_md), # Scope of instruction
# (FileDescr etc)
desc("original_context_descr", get_md, # The original scope if inlined
default=null),
]

25
llvm/deprecated.py Normal file
View file

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

View file

@ -28,85 +28,54 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""Execution Engine and related classes.
"Execution Engine and related classes."
"""
import sys
import llvm # top-level, for common stuff
import llvm.core as core # module, function etc.
import llvm._core as _core # C wrappers
import llvm._util as _util # utility functions
import logging
import os
logger = logging.getLogger(__name__)
# re-export TargetData for backward compatibility.
from llvm.passes import TargetData
def _detect_avx_support():
'''FIXME: This is a workaround for AVX support.
'''
disable_avx_detect = int(os.environ.get('LLVMPY_DISABLE_AVX_DETECT', 0))
if disable_avx_detect:
return False # enable AVX if user disable AVX detect
force_disable_avx = int(os.environ.get('LLVMPY_FORCE_DISABLE_AVX', 0))
if force_disable_avx:
return True # force disable AVX
# auto-detect avx
try:
for line in open('/proc/cpuinfo'):
if line.lstrip().startswith('flags') and 'avx' in line.split():
# enable AVX if flags contain AVX
return False
except IOError:
pass # disable AVX if no /proc/cpuinfo is found
return True # disable AVX if flags does not have AVX
FORCE_DISABLE_AVX = _detect_avx_support()
import llvm
from llvm import core
from llvm.passes import TargetData, TargetTransformInfo
from llvmpy import api, extra
#===----------------------------------------------------------------------===
# Enumerations
# import items which were moved to target module
#===----------------------------------------------------------------------===
from llvm.target import (initialize_all, initialize_target,
print_registered_targets, get_host_cpu_name, get_default_triple,
TargetMachine,
BO_BIG_ENDIAN, BO_LITTLE_ENDIAN,
CM_DEFAULT, CM_JITDEFAULT, CM_SMALL, CM_KERNEL, CM_MEDIUM, CM_LARGE,
RELOC_DEFAULT, RELOC_STATIC, RELOC_PIC, RELOC_DYNAMIC_NO_PIC)
BO_BIG_ENDIAN = 0
BO_LITTLE_ENDIAN = 1
# CodeModel
CM_DEFAULT = 0
CM_JITDEFAULT = 1
CM_SMALL = 2
CM_KERNEL = 3
CM_MEDIUM = 4
CM_LARGE = 5
#===----------------------------------------------------------------------===
# Generic value
#===----------------------------------------------------------------------===
class GenericValue(object):
class GenericValue(llvm.Wrapper):
@staticmethod
def int(ty, intval):
core.check_is_type(ty)
ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 0)
ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), False)
return GenericValue(ptr)
@staticmethod
def int_signed(ty, intval):
core.check_is_type(ty)
ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 1)
ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), True)
return GenericValue(ptr)
@staticmethod
def real(ty, floatval):
core.check_is_type(ty) # only float or double
ptr = _core.LLVMCreateGenericValueOfFloat(ty.ptr, floatval)
if str(ty) == 'float':
ptr = api.llvm.GenericValue.CreateFloat(float(floatval))
elif str(ty) == 'double':
ptr = api.llvm.GenericValue.CreateDouble(float(floatval))
else:
raise Exception('Unreachable')
return GenericValue(ptr)
@staticmethod
def pointer(*args):
def pointer(addr):
'''
One argument version takes (addr).
Two argument version takes (ty, addr). [Deprecated]
@ -114,79 +83,46 @@ class GenericValue(object):
`ty` is unused.
`addr` is an integer representing an address.
TODO: remove two argument version.
'''
if len(args)==2:
logger.warning("Deprecated: Two argument version of "
"GenericValue.pointer() is deprecated.")
addr = args[1]
elif len(args)!=1:
raise TypeError("pointer() takes 1 or 2 arguments.")
else:
addr = args[0]
ptr = _core.LLVMCreateGenericValueOfPointer(addr)
ptr = api.llvm.GenericValue.CreatePointer(int(addr))
return GenericValue(ptr)
def __init__(self, ptr):
self.ptr = ptr
def __del__(self):
_core.LLVMDisposeGenericValue(self.ptr)
def as_int(self):
return _core.LLVMGenericValueToInt(self.ptr, 0)
return self._ptr.toUnsignedInt()
def as_int_signed(self):
return _core.LLVMGenericValueToInt(self.ptr, 1)
return self._ptr.toSignedInt()
def as_real(self, ty):
core.check_is_type(ty) # only float or double
return _core.LLVMGenericValueToFloat(ty.ptr, self.ptr)
return self._ptr.toFloat(ty._ptr)
def as_pointer(self):
return _core.LLVMGenericValueToPointer(self.ptr)
# helper functions for generic value objects
def check_is_generic_value(obj): _util.check_gen(obj, GenericValue)
def _unpack_generic_values(objlist):
return _util.unpack_gen(objlist, check_is_generic_value)
return self._ptr.toPointer()
#===----------------------------------------------------------------------===
# Engine builder
#===----------------------------------------------------------------------===
class EngineBuilder(object):
class EngineBuilder(llvm.Wrapper):
@staticmethod
def new(module):
core.check_is_module(module)
_util.check_is_unowned(module)
obj = _core.LLVMCreateEngineBuilder(module.ptr)
return EngineBuilder(obj, module)
def __init__(self, ptr, module):
self.ptr = ptr
self._module = module
self.__has_mattrs = False
def __del__(self):
_core.LLVMDisposeEngineBuilder(self.ptr)
ptr = api.llvm.EngineBuilder.new(module._ptr)
return EngineBuilder(ptr)
def force_jit(self):
_core.LLVMEngineBuilderForceJIT(self.ptr)
self._ptr.setEngineKind(api.llvm.EngineKind.Kind.JIT)
return self
def force_interpreter(self):
_core.LLVMEngineBuilderForceInterpreter(self.ptr)
self._ptr.setEngineKind(api.llvm.EngineKind.Kind.Interpreter)
return self
def opt(self, level):
'''
level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive]
'''
assert level in range(4)
_core.LLVMEngineBuilderSetOptLevel(self.ptr, level)
assert 0 <= level <= 3
self._ptr.setOptLevel(level)
return self
def mattrs(self, string):
@ -194,45 +130,53 @@ class EngineBuilder(object):
e.g: +sse,-3dnow
'''
self.__has_mattrs = True
if FORCE_DISABLE_AVX:
if 'avx' not in map(lambda x: x.strip(), string.split(',')):
# User did not override
string += ',-avx'
_core.LLVMEngineBuilderSetMAttrs(self.ptr, string.replace(',', ' '))
self._ptr.setMAttrs(string.split(','))
return self
def create(self, tm=None):
'''
tm --- Optional. Provide a TargetMachine. Ownership is transfered
to the returned execution engine.
to the returned execution engine.
'''
if not self.__has_mattrs and FORCE_DISABLE_AVX:
self.mattrs('-avx')
if tm:
_util.check_is_unowned(tm)
ret = _core.LLVMEngineBuilderCreateTM(self.ptr, tm.ptr)
if tm is not None:
engine = self._ptr.create(tm._ptr)
elif (sys.platform.startswith('win32') and
getattr(self, '_use_mcjit', False)):
# force ELF generation on MCJIT on win32
triple = get_default_triple()
tm = TargetMachine.new('%s-elf' % triple)
engine = self._ptr.create(tm._ptr)
else:
ret = _core.LLVMEngineBuilderCreate(self.ptr)
if isinstance(ret, str):
raise llvm.LLVMException(ret)
engine = ExecutionEngine(ret, self._module)
if tm:
tm._own(owner=llvm.DummyOwner)
return engine
engine = self._ptr.create()
ee = ExecutionEngine(engine)
ee.finalize_object() # no effect for legacy JIT
return ee
def select_target(self):
def select_target(self, *args):
'''get the corresponding target machine
Accept no arguments or (triple, march, mcpu, mattrs)
'''
ptr = _core.LLVMTargetMachineFromEngineBuilder(self.ptr)
if args:
triple, march, mcpu, mattrs = args
ptr = self._ptr.selectTarget(triple, march, mcpu,
mattrs.split(','))
else:
ptr = self._ptr.selectTarget()
return TargetMachine(ptr)
def mcjit(self, enable):
'''Enable/disable MCJIT
'''
self._ptr.setUseMCJIT(enable)
self._use_mcjit = True
return self
#===----------------------------------------------------------------------===
# Execution engine
#===----------------------------------------------------------------------===
class ExecutionEngine(object):
class ExecutionEngine(llvm.Wrapper):
@staticmethod
def new(module, force_interpreter=False):
@ -241,152 +185,80 @@ class ExecutionEngine(object):
eb.force_interpreter()
return eb.create()
def __init__(self, ptr, module):
self.ptr = ptr
module._own(self)
def __del__(self):
_core.LLVMDisposeExecutionEngine(self.ptr)
def disable_lazy_compilation(self, disabled=True):
_core.LLVMExecutionEngineDisableLazyCompilation(self.ptr,
int(bool(disabled)))
self._ptr.DisableLazyCompilation(disabled)
def run_function(self, fn, args):
core.check_is_function(fn)
ptrs = _unpack_generic_values(args)
gvptr = _core.LLVMRunFunction2(self.ptr, fn.ptr, ptrs)
return GenericValue(gvptr)
ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args)))
return GenericValue(ptr)
def get_pointer_to_named_function(self, name, abort=True):
return self._ptr.getPointerToNamedFunction(name, abort)
def get_pointer_to_function(self, fn):
core.check_is_function(fn)
return _core.LLVMGetPointerToFunction(self.ptr,fn.ptr)
return self._ptr.getPointerToFunction(fn._ptr)
def get_pointer_to_global(self, val):
core.check_is_global_value(val)
return _core.LLVMGetPointerToGlobal(self.ptr, val.ptr)
return self._ptr.getPointerToGlobal(val._ptr)
def add_global_mapping(self, gvar, addr):
assert addr >= 0, "Address cannot not be negative"
_core.LLVMAddGlobalMapping(self.ptr, gvar.ptr, addr)
self._ptr.addGlobalMapping(gvar._ptr, addr)
def run_static_ctors(self):
_core.LLVMRunStaticConstructors(self.ptr)
self._ptr.runStaticConstructorsDestructors(False)
def run_static_dtors(self):
_core.LLVMRunStaticDestructors(self.ptr)
self._ptr.runStaticConstructorsDestructors(True)
def free_machine_code_for(self, fn):
core.check_is_function(fn)
_core.LLVMFreeMachineCodeForFunction(self.ptr, fn.ptr)
self._ptr.freeMachineCodeForFunction(fn._ptr)
def add_module(self, module):
core.check_is_module(module)
_core.LLVMAddModule(self.ptr, module.ptr)
module._own(self)
self._ptr.addModule(module._ptr)
def remove_module(self, module):
core.check_is_module(module)
if module.owner != self:
raise llvm.LLVMException("module is not owned by self")
ret = _core.LLVMRemoveModule2(self.ptr, module.ptr)
if isinstance(ret, str):
raise llvm.LLVMException(ret)
return core.Module(ret)
return self._ptr.removeModule(module._ptr)
def finalize_object(self):
return self._ptr.finalizeObject()
@property
def target_data(self):
td = TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr))
td._own(self)
return td
ptr = self._ptr.getDataLayout()
return TargetData(ptr)
#===----------------------------------------------------------------------===
# Target machine
# Dynamic Library
#===----------------------------------------------------------------------===
def print_registered_targets():
'''
Note: print directly to stdout
'''
_core.LLVMPrintRegisteredTargetsForVersion()
def dylib_add_symbol(name, ptr):
api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr)
def get_host_cpu_name():
'''return the string name of the host CPU
'''
return _core.LLVMGetHostCPUName()
def dylib_address_of_symbol(name):
return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name)
def get_default_triple():
'''return the target triple of the host in str-rep
'''
return _core.LLVMDefaultTargetTriple()
def dylib_import_library(filename):
"""Permanently import a dynamic library.
Returns a DynamicLibrary object
Raises RuntimeError
"""
return DynamicLibrary(filename)
class TargetMachine(llvm.Ownable):
@staticmethod
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT):
if not triple and not cpu:
triple = get_default_triple()
cpu = get_host_cpu_name()
ptr = _core.LLVMCreateTargetMachine(triple, cpu, features, opt, cm)
return TargetMachine(ptr)
@staticmethod
def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT):
'''create a targetmachine given an architecture name
For a list of architectures,
use: `llc -help`
For a list of available CPUs,
use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help`
For a list of available attributes (features),
use: `llvm-as < /dev/null | llc -march=xyz -mattr=help`
'''
ptr = _core.LLVMTargetMachineLookup(arch, cpu, features, opt, cm)
return TargetMachine(ptr)
def __init__(self, ptr):
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetMachine)
def emit_assembly(self, module):
'''returns byte string of the module as assembly code of the target machine
'''
return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, True)
def emit_object(self, module):
'''returns byte string of the module as native code of the target machine
'''
return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, False)
@property
def target_data(self):
'''get target data of this machine
'''
ptr = _core.LLVMTargetMachineGetTargetData(self.ptr)
td = TargetData(ptr)
td._own(self)
return td
@property
def target_name(self):
return _core.LLVMTargetMachineGetTargetName(self.ptr)
@property
def target_short_description(self):
return _core.LLVMTargetMachineGetTargetShortDescription(self.ptr)
@property
def triple(self):
return _core.LLVMTargetMachineGetTriple(self.ptr)
@property
def cpu(self):
return _core.LLVMTargetMachineGetCPU(self.ptr)
@property
def feature_string(self):
return _core.LLVMTargetMachineGetFS(self.ptr)
class DynamicLibrary(object):
def __init__(self, filename):
"""
Raises RuntimeError
"""
self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary(
filename)
def get_address_of_symbol(self, symbol):
"""
Get the address of `symbol` (str) as integer
"""
return self._ptr.getAddressOfSymbol(symbol)

File diff suppressed because it is too large Load diff

View file

@ -1,676 +0,0 @@
/*
* Copyright (c) 2008-10, Mahadevan R All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of this software, nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* These are some "extra" functions not available in the standard LLVM-C
* bindings, but are required / good-to-have inorder to implement the
* Python bindings.
*/
#ifndef LLVM_PY_EXTRA_H
#define LLVM_PY_EXTRA_H
// select PTX or NVPTX
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2
#define LLVM_HAS_NVPTX 1
#else
#define LLVM_HAS_NVPTX 0
#endif
#include "llvm-c/Transforms/PassManagerBuilder.h"
#include "llvm_c_extra.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2
/*
* Wraps new TargetTransformInfo(
* TargetMachine::getScalarTargetTransformInfo,
* TargetMachine::getVectorTargetTransformInfo)
*/
LLVMPassRef LLVMCreateTargetTransformInfo(LLVMTargetMachineRef tmref);
#endif
/*
* Wraps new TargetLibraryInfo
*/
LLVMPassRef LLVMCreateTargetLibraryInfo(const char * triple);
/*
* Wraps llvm::getDefaultTargetTriple
*/
const char * LLVMDefaultTargetTriple();
/*
* Wraps Pass::lookupPassInfo and PassInfo::createPass
*/
LLVMPassRef LLVMCreatePassByName(const char *name);
/*
* Wraps operator delete (Pass*)
*/
void LLVMDisposePass(LLVMPassRef passref);
/*
* Wraps Pass::getPassName
*/
const char * LLVMGetPassName(LLVMPassRef passref);
/*
* Wraps PassManager::add
*/
void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref);
/*
* Wraps Pass::dump
*/
void LLVMPassDump(LLVMPassRef passref);
/*
* Wraps llvm:InlineAsm::get
*/
LLVMValueRef LLVMGetFunctionFromInlineAsm(LLVMTypeRef funcType,
const char inlineAsm[],
const char constrains[],
bool hasSideEffect,
bool isAlignStack,
int asmDialect);
/*
* Wraps llvm::CloneModule
*/
LLVMModuleRef LLVMCloneModule(LLVMModuleRef mod);
/*
* Wraps NamedMDNode::print()
*/
const char * LLVMDumpNamedMDToString(LLVMNamedMDRef nmd);
/*
* Wraps NamedMDNode::getName()
*/
const char * LLVMNamedMetaDataGetName(LLVMNamedMDRef nmd);
/*
* Wraps NamedMDNode::addOperand()
*/
void LLVMNamedMetaDataAddOperand(LLVMNamedMDRef nmd, LLVMValueRef md);
/*
* Wraps NamedMDNode::eraseFromParent()
*/
void LLVMEraseNamedMetaData(LLVMNamedMDRef nmd);
/*
* Wraps Module::getOrInsertNamedMetadata
*/
LLVMNamedMDRef LLVMModuleGetOrInsertNamedMetaData(LLVMModuleRef mod, const char *name);
/*
* Wraps Module::getNamedMetadata
*/
LLVMNamedMDRef LLVMModuleGetNamedMetaData(LLVMModuleRef mod, const char *name);
/*
* Wraps Instruction::setMetadata()
*/
void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind,
LLVMValueRef metaref);
/*
* Wraps MDNode::get()
*/
LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs,
unsigned valct);
/*
* Wraps MDNode::getOperand()
*/
LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index);
/*
* Wraps MDNode::getNumOperands()
*/
unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref);
/*
* Wraps MDString::get()
*/
LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s);
/*
* Wraps ConstantExpr::getOpcodeName()
*/
const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst);
/*
* Wraps ConstantExpr::getOpcode()
*/
unsigned LLVMGetConstExprOpcode(LLVMValueRef inst);
/*
* Wraps LoadInst::SetAlignment
*/
void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align);
/*
* Wraps StoreInst::SetAlignment
*/
void LLVMStSetAlignment(LLVMValueRef inst, unsigned align);
const char * LLVMGetHostCPUName();
int LLVMInitializeNativeTargetAsmPrinter();
LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu,
const char *features, int opt,
int codemodel, std::string &error);
LLVMTargetMachineRef LLVMCreateTargetMachine(const char *arch, const char *cpu,
const char *features, int opt,
int codemodel,
std::string &error);
/*
* Wraps EngineBuilder::selectTarget
*/
LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb);
/*
* Wraps operator delete
*/
void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::addPassesToEmitFile
*/
unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref,
LLVMModuleRef modref,
int assembly, size_t * lenp,
std::string &error);
/*
* Wraps TargetMachine::getTargetData
*/
LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTarget().getName()
*/
const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTarget().getShortDescription()
*/
const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTargetTriple
*/
const char * LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTargetCPU
*/
const char * LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm);
/*
* Wraps TargetMachine::getTargetFeatureString
*/
const char * LLVMTargetMachineGetFS(LLVMTargetMachineRef tm);
/*
* Wraps TargetRegister::printRegisteredTargetsForVersion
*/
void LLVMPrintRegisteredTargetsForVersion();
/*
* Wraps TargetMachine::addPassesToEmitFile
*/
unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly,
size_t * lenp, std::string &error);
/*
* Wraps IRBuilder::CreateFence
*/
LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering,
int crossthread);
/*
* Wraps IRBuilder::CreateLoad, LoadInst::setAtomic
*/
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
unsigned align, const char* ordering,
int crossthread);
/*
* Wraps IRBuilder::CreateStore, StoreInst::setAtomic
*/
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
LLVMValueRef ptr, LLVMValueRef val,
unsigned align, const char* ordering,
int crossthread);
/*
* Wraps IRBuilder::CreateAtomicRMW
*/
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * op,
LLVMValueRef ptr, LLVMValueRef val,
const char* ordering, int crossthread);
/*
* Wraps IRBuilder::CreateAtomicCmpXchg
*/
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr,
LLVMValueRef cmp, LLVMValueRef val,
const char* ordering, int crossthread);
/*
* Wraps new EngineBuilder
*/
LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod);
/*
* Wraps delete EngineBuilder
*/
void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb);
/*
* Wraps EngineBuilder::setEngineKind(EngineKind::JIT)
*/
void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb);
/*
* Wraps EngineBuilder::setEngineKind(EngineKind::Interpreter)
*/
void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb);
/*
* Wraps EngineBuilder::setOptLevel
*/
void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level);
/*
* Wraps EngineBuilder::setMCPU
*/
void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu);
/*
* Wraps EngineBuilder::setMAttrs
*/
void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs);
/*
* Wraps EngineBuilder::setErrorStr and EngineBuilder::create
*/
LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb,
std::string &error);
/*
* Wraps EngineBuilder::create(TargetMachine*)
*/
LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef ebref,
LLVMTargetMachineRef tmref,
std::string & error);
/*
* Wraps PassManagerBuilder::OptLevel
*/
int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb);
/*
* Wraps PassManagerBuilder::SizeLevel
*/
int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb);
/*
* Wraps PassManagerBuilder::Vectorize
*/
void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag);
/*
* Wraps PassManagerBuilder::Vectorize
*/
int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb);
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2
/*
* Wraps PassManagerBuilder::LoopVectorize
*/
void LLVMPassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef pmb,
int flag);
/*
* Wraps PassManagerBuilder::LoopVectorize
*/
int LLVMPassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef pmb);
#endif // llvm-3.2
/*
* Wraps PassManagerBuilder::DisableUnitAtATime
*/
int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb);
/*
* Wraps PassManagerBuilder::DisableUnrollLoops
*/
int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb);
/*
* Wraps PassManagerBuilder::DisableSimplifyLibCalls
*/
int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb);
/*
* Wraps PassManager::add
*/
int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name);
/*
* Wraps initialize*
*/
void LLVMInitializePasses(void);
/*
* Wraps PassRegistry::enumerateWith()
* Returns a '\n' separated string of all passes available to `opt`.
*/
const char * LLVMDumpPasses(void);
/*
* Wraps StructType::isLiteral()
*/
int LLVMIsLiteralStruct(LLVMTypeRef type);
/*
* Wraps StructType::create()
*/
LLVMTypeRef LLVMStructTypeIdentified(const char * name);
/*
* StructType::setBody()
*/
void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed);
/*
* Wraps llvm::StructType::setName()
*/
void LLVMSetStructName(LLVMTypeRef type, const char * name);
/*
* Wraps llvm::Module::getModuleIdentifier()
*/
char *LLVMGetModuleIdentifier(LLVMModuleRef module);
/*
* Wraps llvm::Module::setModuleIdentifier()
*/
void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name);
/* Notes:
* - Some returned strings must be disposed of by LLVMDisposeMessage. These are
* indicated in the comments. Where it is not indicated, DO NOT call dispose.
*/
/* Wraps llvm::Module::print(). Dispose the returned string after use, via
* LLVMDisposeMessage(). */
char *LLVMDumpModuleToString(LLVMModuleRef module);
/* Wraps llvm::Module::addLibrary(name). */
void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name);
/* Wraps llvm::Type::print(). Dispose the returned string after use, via
* LLVMDisposeMessage(). */
char *LLVMDumpTypeToString(LLVMTypeRef type);
/* Wraps llvm::Value::print(). Dispose the returned string after use, via
* LLVMDisposeMessage(). */
char *LLVMDumpValueToString(LLVMValueRef Val);
/* Wraps llvm::IRBuilder::CreateRet(). */
LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef bulder, LLVMValueRef *values,
unsigned n_values);
/* Wraps llvm::IRBuilder::CreateGetResult(). */
LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, LLVMValueRef value,
unsigned index, const char *name);
/* Wraps llvm::Value::getValueID(). */
unsigned LLVMValueGetID(LLVMValueRef value);
/* Wraps llvm::Value::getNumUses(). */
unsigned LLVMValueGetNumUses(LLVMValueRef value);
/* Wraps llvm::Value::use_{begin,end}. Allocates LLVMValueRef's as
* required. Number of objects are returned as return value. If that is
* greater than zero, the pointer given out must be freed by a
* subsequent call to LLVMDisposeValueRefArray(). */
unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs);
/* See above. */
void LLVMDisposeValueRefArray(LLVMValueRef *refs);
/* Wraps llvm:User::getNumOperands(). */
unsigned LLVMUserGetNumOperands(LLVMValueRef user);
/* Wraps llvm:User::getOperand(). */
LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx);
/* Wraps llvm::ConstantExpr::getVICmp(). */
LLVMValueRef LLVMConstVICmp(LLVMIntPredicate predicate, LLVMValueRef lhs,
LLVMValueRef rhs);
/* Wraps llvm::ConstantExpr::getVFCmp(). */
LLVMValueRef LLVMConstVFCmp(LLVMRealPredicate predicate, LLVMValueRef lhs,
LLVMValueRef rhs);
/* Wraps llvm::IRBuilder::CreateVICmp(). */
LLVMValueRef LLVMBuildVICmp(LLVMBuilderRef builder, LLVMIntPredicate predicate,
LLVMValueRef lhs, LLVMValueRef rhs, const char *name);
/* Wraps llvm::IRBuilder::CreateVFCmp(). */
LLVMValueRef LLVMBuildVFCmp(LLVMBuilderRef builder, LLVMRealPredicate predicate,
LLVMValueRef lhs, LLVMValueRef rhs, const char *name);
/* Wraps llvm::Intrinsic::getDeclaration(). */
LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef builder, int id,
LLVMTypeRef *types, unsigned n_types);
/* Wraps llvm::Function::doesNotThrow(). */
unsigned LLVMGetDoesNotThrow(LLVMValueRef fn);
/* Wraps llvm::Function::setDoesNotThrow(). */
void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow);
/* Wraps llvm::Module::getPointerSize(). */
unsigned LLVMModuleGetPointerSize(LLVMModuleRef module);
/* Wraps llvm::Module::getOrInsertFunction(). */
LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module,
const char *name, LLVMTypeRef function_type);
/* Wraps llvm::GlobalVariable::hasInitializer(). */
int LLVMHasInitializer(LLVMValueRef global_var);
/* The following functions wrap various llvm::Instruction::isXXX() functions.
* All of them take an instruction and return 0 (isXXX returned false) or 1
* (isXXX returned false). */
unsigned LLVMInstIsTerminator (LLVMValueRef inst);
unsigned LLVMInstIsBinaryOp (LLVMValueRef inst);
unsigned LLVMInstIsShift (LLVMValueRef inst);
unsigned LLVMInstIsCast (LLVMValueRef inst);
unsigned LLVMInstIsLogicalShift (LLVMValueRef inst);
unsigned LLVMInstIsArithmeticShift (LLVMValueRef inst);
unsigned LLVMInstIsAssociative (LLVMValueRef inst);
unsigned LLVMInstIsCommutative (LLVMValueRef inst);
unsigned LLVMInstIsTrapping (LLVMValueRef inst);
/* As above, but these are wrap methods from subclasses of Instruction. */
unsigned LLVMInstIsVolatile (LLVMValueRef inst);
/* Wraps llvm::Instruction::getOpcodeName(). */
const char *LLVMInstGetOpcodeName(LLVMValueRef inst);
/* Wraps llvm::Instruction::getOpcode(). */
unsigned LLVMInstGetOpcode(LLVMValueRef inst);
/* Wraps llvm::CmpInst::getPredicate(). */
unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst);
/* Wraps llvm::CallSite::getCalledFunction.
*/
LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst);
/* Wraps llvm::CallSite::setCalledFunction.
*/
void LLVMInstSetCalledFunction(LLVMValueRef inst, LLVMValueRef fn);
/* Wraps llvm::ParseAssemblyString(). Returns a module reference or NULL (with
* `out' pointing to an error message). Dispose error message after use, via
* LLVMDisposeMessage(). */
LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtxt, char **out);
/* Wraps llvm::ParseBitcodeFile(). Returns a module reference or NULL (with
* `out' pointing to an error message). Dispose error message after use, via
* LLVMDisposeMessage(). */
LLVMModuleRef LLVMGetModuleFromBitcode(const char *bc, unsigned bclen,
char **out);
#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2
/* Wraps llvm::Linker::LinkModules(). Returns 0 on failure (with errmsg
* filled in) and 1 on success. Dispose error message after use with
* LLVMDisposeMessage(). */
unsigned LLVMLinkModules(LLVMModuleRef dest, LLVMModuleRef src, int mode,
char **errmsg);
#endif
/* Returns pointer to a heap-allocated block of `*len' bytes containing bit code
* for the given module. NULL on error. */
unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, size_t *len);
/* Wraps llvm::sys::DynamicLibrary::LoadLibraryPermanently(). Returns 0 on
* failure (with errmsg filled in) and 1 on success. Dispose error message after
* use, via LLVMDisposeMessage(). */
unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg);
/* Wraps llvm::ExecutionEngine::DisableLazyCompilation(bool)
*/
void LLVMExecutionEngineDisableLazyCompilation(LLVMExecutionEngineRef ee,
int flag);
/* Wraps llvm::ExecutionEngine::getPointerToFunction(). Returns a pointer
* to the JITted function. */
void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn);
/* Wraps llvm::InlineFunction(). Inlines a function. C is the call
* instruction, created by LLVMBuildCall. Even if it fails, the Function
* containing the call is still in a proper state (not changed).
*/
int LLVMInlineFunction(LLVMValueRef call);
/* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the
* already available LLVMSetParamAlignment(). */
unsigned LLVMGetParamAlignment(LLVMValueRef arg);
/* Passes. Some passes are used directly from LLVM-C, rest are declared
* here. */
/*
#define declare_pass(P) \
void LLVMAdd ## P ## Pass (LLVMPassManagerRef PM);
declare_pass( AAEval )
declare_pass( AliasAnalysisCounter )
declare_pass( AlwaysInliner )
declare_pass( BasicAliasAnalysis )
declare_pass( BlockPlacement )
declare_pass( BreakCriticalEdges )
declare_pass( CodeGenPrepare )
declare_pass( DbgInfoPrinter )
declare_pass( DeadCodeElimination )
declare_pass( DeadInstElimination )
declare_pass( DemoteRegisterToMemory )
declare_pass( DomOnlyPrinter )
declare_pass( DomOnlyViewer )
declare_pass( DomPrinter )
declare_pass( DomViewer )
declare_pass( EdgeProfiler )
//declare_pass( GEPSplitter )
declare_pass( GlobalsModRef )
declare_pass( InstCount )
declare_pass( InstructionNamer )
declare_pass( LazyValueInfo )
declare_pass( LCSSA )
//declare_pass( LiveValues )
declare_pass( LoopDependenceAnalysis )
declare_pass( LoopExtractor )
declare_pass( LoopSimplify )
declare_pass( LoopStrengthReduce )
declare_pass( LowerInvoke )
declare_pass( LowerSwitch )
declare_pass( MergeFunctions )
declare_pass( NoAA )
declare_pass( NoProfileInfo )
declare_pass( OptimalEdgeProfiler )
declare_pass( PartialInlining )
//declare_pass( PartialSpecialization )
declare_pass( PostDomOnlyPrinter )
declare_pass( PostDomOnlyViewer )
declare_pass( PostDomPrinter )
declare_pass( PostDomViewer )
declare_pass( ProfileEstimator )
declare_pass( ProfileLoader )
declare_pass( ProfileVerifier )
declare_pass( ScalarEvolutionAliasAnalysis )
declare_pass( SimplifyHalfPowrLibCalls )
declare_pass( SingleLoopExtractor )
declare_pass( StripNonDebugSymbols )
declare_pass( StructRetPromotion )
declare_pass( TailDuplication )
declare_pass( UnifyFunctionExitNodes )
declare_pass( Internalize2 )
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LLVM_PY_EXTRA_H */

79
llvm/llrt.py Normal file
View file

@ -0,0 +1,79 @@
import os
import llvm.core as lc
import llvm.passes as lp
import llvm.ee as le
def replace_divmod64(lfunc):
'''Replaces all 64-bit integer division (sdiv, udiv) and modulo (srem, urem)
'''
int64 = lc.Type.int(64)
int64ptr = lc.Type.pointer(lc.Type.int(64))
functy = lc.Type.function(int64, [int64, int64])
udiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_udiv64')
sdiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_sdiv64')
umod64 = lfunc.module.get_or_insert_function(functy, '__llrt_umod64')
smod64 = lfunc.module.get_or_insert_function(functy, '__llrt_smod64')
builder = lc.Builder.new(lfunc.entry_basic_block)
for bb in lfunc.basic_blocks:
for inst in bb.instructions:
if inst.opcode_name == 'sdiv' and inst.type == int64:
_replace_with(builder, inst, sdiv64)
elif inst.opcode_name == 'udiv' and inst.type == int64:
_replace_with(builder, inst, udiv64)
elif inst.opcode_name == 'srem' and inst.type == int64:
_replace_with(builder, inst, smod64)
elif inst.opcode_name == 'urem' and inst.type == int64:
_replace_with(builder, inst, umod64)
def _replace_with(builder, inst, func):
'''Replace instruction with a call to the function with the same operands
as arguments.
'''
builder.position_before(inst)
replacement = builder.call(func, inst.operands)
inst.replace_all_uses_with(replacement._ptr)
inst.erase_from_parent()
def load(arch):
'''Load the LLRT module corresponding to the given architecture
Creates a new module and optimizes it using the information from
the host machine.
'''
if arch != 'x86_64':
arch = 'x86'
path = os.path.join(os.path.dirname(__file__), 'llrt', 'llrt_%s.ll' % arch)
with open(path) as fin:
lib = lc.Module.from_assembly(fin)
# run passes to optimize
tm = le.TargetMachine.new()
pms = lp.build_pass_managers(tm, opt=3, fpm=False)
pms.pm.run(lib)
return lib
class LLRT(object):
def __init__(self):
arch = le.get_default_triple().split('-', 1)[0]
self.module = load(arch)
self.engine = le.EngineBuilder.new(self.module).opt(3).create()
self.installed_symbols = set()
def install_symbols(self):
'''Bind all the external symbols to the global symbol map.
Any future reference to these symbols will be automatically resolved
by LLVM.
'''
for lfunc in self.module.functions:
if lfunc.linkage == lc.LINKAGE_EXTERNAL:
mangled = '__llrt_' + lfunc.name
self.installed_symbols.add(mangled)
ptr = self.engine.get_pointer_to_function(lfunc)
le.dylib_add_symbol(mangled, ptr)
def uninstall_symbols(self):
for sym in self.installed_symbols:
le.dylib_add_symbol(sym, 0)

371
llvm/llrt/llrt_x86.ll Normal file
View file

@ -0,0 +1,371 @@
; ModuleID = 'udivmod64_x86.bc'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128"
%struct.div_state_ = type { i64, i64 }
define i64 @udivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind ssp {
%1 = alloca i64, align 4
%2 = alloca i64, align 8
%3 = alloca i64, align 8
%4 = alloca i64*, align 4
%state = alloca %struct.div_state_, align 4
%quotient = alloca i64, align 8
%i = alloca i32, align 4
%skipahead = alloca i32, align 4
store i64 %dividend, i64* %2, align 8
store i64 %divisor, i64* %3, align 8
store i64* %remainder, i64** %4, align 4
%5 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
store i64 0, i64* %5, align 4
%6 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 1
%7 = load i64* %2, align 8
store i64 %7, i64* %6, align 4
store i64 0, i64* %quotient, align 8
%8 = load i64* %3, align 8
%9 = icmp eq i64 %8, 0
br i1 %9, label %10, label %11
; <label>:10 ; preds = %0
store i64 0, i64* %1
br label %57
; <label>:11 ; preds = %0
%12 = load i64* %2, align 8
%13 = call i32 @clz64(i64 %12)
store i32 %13, i32* %skipahead, align 4
store i32 0, i32* %i, align 4
br label %14
; <label>:14 ; preds = %19, %11
%15 = load i32* %i, align 4
%16 = load i32* %skipahead, align 4
%17 = icmp slt i32 %15, %16
br i1 %17, label %18, label %22
; <label>:18 ; preds = %14
call void @div_state_lshift(%struct.div_state_* %state)
br label %19
; <label>:19 ; preds = %18
%20 = load i32* %i, align 4
%21 = add nsw i32 %20, 1
store i32 %21, i32* %i, align 4
br label %14
; <label>:22 ; preds = %14
%23 = load i32* %skipahead, align 4
store i32 %23, i32* %i, align 4
br label %24
; <label>:24 ; preds = %45, %22
%25 = load i32* %i, align 4
%26 = icmp slt i32 %25, 64
br i1 %26, label %27, label %48
; <label>:27 ; preds = %24
call void @div_state_lshift(%struct.div_state_* %state)
%28 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
%29 = load i64* %28, align 4
%30 = load i64* %3, align 8
%31 = icmp uge i64 %29, %30
br i1 %31, label %32, label %44
; <label>:32 ; preds = %27
%33 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
%34 = load i64* %33, align 4
%35 = load i64* %3, align 8
%36 = sub i64 %34, %35
%37 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
store i64 %36, i64* %37, align 4
%38 = load i32* %i, align 4
%39 = sub nsw i32 63, %38
%40 = zext i32 %39 to i64
%41 = shl i64 1, %40
%42 = load i64* %quotient, align 8
%43 = or i64 %42, %41
store i64 %43, i64* %quotient, align 8
br label %44
; <label>:44 ; preds = %32, %27
br label %45
; <label>:45 ; preds = %44
%46 = load i32* %i, align 4
%47 = add nsw i32 %46, 1
store i32 %47, i32* %i, align 4
br label %24
; <label>:48 ; preds = %24
%49 = load i64** %4, align 4
%50 = icmp ne i64* %49, null
br i1 %50, label %51, label %55
; <label>:51 ; preds = %48
%52 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
%53 = load i64* %52, align 4
%54 = load i64** %4, align 4
store i64 %53, i64* %54, align 4
br label %55
; <label>:55 ; preds = %51, %48
%56 = load i64* %quotient, align 8
store i64 %56, i64* %1
br label %57
; <label>:57 ; preds = %55, %10
%58 = load i64* %1
ret i64 %58
}
define internal i32 @clz64(i64 %x) nounwind ssp {
%1 = alloca i64, align 8
%total_bits = alloca i32, align 4
%zc = alloca i32, align 4
store i64 %x, i64* %1, align 8
store i32 64, i32* %total_bits, align 4
store i32 0, i32* %zc, align 4
br label %2
; <label>:2 ; preds = %16, %0
%3 = load i32* %zc, align 4
%4 = icmp slt i32 %3, 64
br i1 %4, label %5, label %14
; <label>:5 ; preds = %2
%6 = load i64* %1, align 8
%7 = load i32* %zc, align 4
%8 = sub nsw i32 64, %7
%9 = sub nsw i32 %8, 1
%10 = zext i32 %9 to i64
%11 = lshr i64 %6, %10
%12 = and i64 %11, 1
%13 = icmp eq i64 %12, 0
br label %14
; <label>:14 ; preds = %5, %2
%15 = phi i1 [ false, %2 ], [ %13, %5 ]
br i1 %15, label %16, label %19
; <label>:16 ; preds = %14
%17 = load i32* %zc, align 4
%18 = add nsw i32 %17, 1
store i32 %18, i32* %zc, align 4
br label %2
; <label>:19 ; preds = %14
%20 = load i32* %zc, align 4
ret i32 %20
}
define internal void @div_state_lshift(%struct.div_state_* %state) nounwind ssp {
%1 = alloca %struct.div_state_*, align 4
store %struct.div_state_* %state, %struct.div_state_** %1, align 4
%2 = load %struct.div_state_** %1, align 4
%3 = getelementptr inbounds %struct.div_state_* %2, i32 0, i32 0
%4 = load i64* %3, align 4
%5 = shl i64 %4, 1
%6 = load %struct.div_state_** %1, align 4
%7 = getelementptr inbounds %struct.div_state_* %6, i32 0, i32 1
%8 = load i64* %7, align 4
%9 = lshr i64 %8, 63
%10 = or i64 %5, %9
%11 = load %struct.div_state_** %1, align 4
%12 = getelementptr inbounds %struct.div_state_* %11, i32 0, i32 0
store i64 %10, i64* %12, align 4
%13 = load %struct.div_state_** %1, align 4
%14 = getelementptr inbounds %struct.div_state_* %13, i32 0, i32 1
%15 = load i64* %14, align 4
%16 = shl i64 %15, 1
%17 = load %struct.div_state_** %1, align 4
%18 = getelementptr inbounds %struct.div_state_* %17, i32 0, i32 1
store i64 %16, i64* %18, align 4
ret void
}
define i64 @sdivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%3 = alloca i64*, align 4
%signbitidx = alloca i32, align 4
%signed_dividend = alloca i32, align 4
%signed_divisor = alloca i32, align 4
%signed_result = alloca i32, align 4
%quotient = alloca i64, align 8
%udvd = alloca i64, align 8
%udvr = alloca i64, align 8
%uquotient = alloca i64, align 8
%uremainder = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
store i64* %remainder, i64** %3, align 4
store i32 63, i32* %signbitidx, align 4
%4 = load i64* %1, align 8
%5 = icmp slt i64 %4, 0
%6 = zext i1 %5 to i32
store i32 %6, i32* %signed_dividend, align 4
%7 = load i64* %2, align 8
%8 = icmp slt i64 %7, 0
%9 = zext i1 %8 to i32
store i32 %9, i32* %signed_divisor, align 4
%10 = load i32* %signed_divisor, align 4
%11 = load i32* %signed_dividend, align 4
%12 = xor i32 %10, %11
store i32 %12, i32* %signed_result, align 4
%13 = load i32* %signed_dividend, align 4
%14 = icmp ne i32 %13, 0
br i1 %14, label %15, label %18
; <label>:15 ; preds = %0
%16 = load i64* %1, align 8
%17 = sub nsw i64 0, %16
br label %20
; <label>:18 ; preds = %0
%19 = load i64* %1, align 8
br label %20
; <label>:20 ; preds = %18, %15
%21 = phi i64 [ %17, %15 ], [ %19, %18 ]
store i64 %21, i64* %udvd, align 8
%22 = load i32* %signed_divisor, align 4
%23 = icmp ne i32 %22, 0
br i1 %23, label %24, label %27
; <label>:24 ; preds = %20
%25 = load i64* %2, align 8
%26 = sub nsw i64 0, %25
br label %29
; <label>:27 ; preds = %20
%28 = load i64* %2, align 8
br label %29
; <label>:29 ; preds = %27, %24
%30 = phi i64 [ %26, %24 ], [ %28, %27 ]
store i64 %30, i64* %udvr, align 8
%31 = load i64* %udvd, align 8
%32 = load i64* %udvr, align 8
%33 = call i64 @udivmod64(i64 %31, i64 %32, i64* %uremainder)
store i64 %33, i64* %uquotient, align 8
%34 = load i32* %signed_result, align 4
%35 = icmp ne i32 %34, 0
br i1 %35, label %36, label %57
; <label>:36 ; preds = %29
%37 = load i64* %uremainder, align 8
%38 = icmp ne i64 %37, 0
br i1 %38, label %39, label %43
; <label>:39 ; preds = %36
%40 = load i64* %uquotient, align 8
%41 = sub nsw i64 0, %40
%42 = sub nsw i64 %41, 1
store i64 %42, i64* %quotient, align 8
br label %46
; <label>:43 ; preds = %36
%44 = load i64* %uquotient, align 8
%45 = sub nsw i64 0, %44
store i64 %45, i64* %quotient, align 8
br label %46
; <label>:46 ; preds = %43, %39
%47 = load i64** %3, align 4
%48 = icmp ne i64* %47, null
br i1 %48, label %49, label %56
; <label>:49 ; preds = %46
%50 = load i64* %1, align 8
%51 = load i64* %quotient, align 8
%52 = load i64* %2, align 8
%53 = mul i64 %51, %52
%54 = sub i64 %50, %53
%55 = load i64** %3, align 4
store i64 %54, i64* %55, align 4
br label %56
; <label>:56 ; preds = %49, %46
br label %73
; <label>:57 ; preds = %29
%58 = load i64* %uquotient, align 8
store i64 %58, i64* %quotient, align 8
%59 = load i64** %3, align 4
%60 = icmp ne i64* %59, null
br i1 %60, label %61, label %72
; <label>:61 ; preds = %57
%62 = load i32* %signed_divisor, align 4
%63 = icmp ne i32 %62, 0
br i1 %63, label %64, label %67
; <label>:64 ; preds = %61
%65 = load i64* %uremainder, align 8
%66 = sub i64 0, %65
br label %69
; <label>:67 ; preds = %61
%68 = load i64* %uremainder, align 8
br label %69
; <label>:69 ; preds = %67, %64
%70 = phi i64 [ %66, %64 ], [ %68, %67 ]
%71 = load i64** %3, align 4
store i64 %70, i64* %71, align 4
br label %72
; <label>:72 ; preds = %69, %57
br label %73
; <label>:73 ; preds = %72, %56
%74 = load i64* %quotient, align 8
ret i64 %74
}
define i64 @udiv64(i64 %dividend, i64 %divisor) nounwind ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @udivmod64(i64 %3, i64 %4, i64* null)
ret i64 %5
}
define i64 @sdiv64(i64 %dividend, i64 %divisor) nounwind ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @sdivmod64(i64 %3, i64 %4, i64* null)
ret i64 %5
}
define i64 @umod64(i64 %dividend, i64 %divisor) nounwind ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%rem = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @udivmod64(i64 %3, i64 %4, i64* %rem)
%6 = load i64* %rem, align 8
ret i64 %6
}
define i64 @smod64(i64 %dividend, i64 %divisor) nounwind ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%rem = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @sdivmod64(i64 %3, i64 %4, i64* %rem)
%6 = load i64* %rem, align 8
ret i64 %6
}

371
llvm/llrt/llrt_x86_64.ll Normal file
View file

@ -0,0 +1,371 @@
; ModuleID = 'udivmod64_x86_64.bc'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
%struct.div_state_ = type { i64, i64 }
define i64 @udivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind uwtable ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%3 = alloca i64, align 8
%4 = alloca i64*, align 8
%state = alloca %struct.div_state_, align 8
%quotient = alloca i64, align 8
%i = alloca i32, align 4
%skipahead = alloca i32, align 4
store i64 %dividend, i64* %2, align 8
store i64 %divisor, i64* %3, align 8
store i64* %remainder, i64** %4, align 8
%5 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
store i64 0, i64* %5, align 8
%6 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 1
%7 = load i64* %2, align 8
store i64 %7, i64* %6, align 8
store i64 0, i64* %quotient, align 8
%8 = load i64* %3, align 8
%9 = icmp eq i64 %8, 0
br i1 %9, label %10, label %11
; <label>:10 ; preds = %0
store i64 0, i64* %1
br label %57
; <label>:11 ; preds = %0
%12 = load i64* %2, align 8
%13 = call i32 @clz64(i64 %12)
store i32 %13, i32* %skipahead, align 4
store i32 0, i32* %i, align 4
br label %14
; <label>:14 ; preds = %19, %11
%15 = load i32* %i, align 4
%16 = load i32* %skipahead, align 4
%17 = icmp slt i32 %15, %16
br i1 %17, label %18, label %22
; <label>:18 ; preds = %14
call void @div_state_lshift(%struct.div_state_* %state)
br label %19
; <label>:19 ; preds = %18
%20 = load i32* %i, align 4
%21 = add nsw i32 %20, 1
store i32 %21, i32* %i, align 4
br label %14
; <label>:22 ; preds = %14
%23 = load i32* %skipahead, align 4
store i32 %23, i32* %i, align 4
br label %24
; <label>:24 ; preds = %45, %22
%25 = load i32* %i, align 4
%26 = icmp slt i32 %25, 64
br i1 %26, label %27, label %48
; <label>:27 ; preds = %24
call void @div_state_lshift(%struct.div_state_* %state)
%28 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
%29 = load i64* %28, align 8
%30 = load i64* %3, align 8
%31 = icmp uge i64 %29, %30
br i1 %31, label %32, label %44
; <label>:32 ; preds = %27
%33 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
%34 = load i64* %33, align 8
%35 = load i64* %3, align 8
%36 = sub i64 %34, %35
%37 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
store i64 %36, i64* %37, align 8
%38 = load i32* %i, align 4
%39 = sub nsw i32 63, %38
%40 = zext i32 %39 to i64
%41 = shl i64 1, %40
%42 = load i64* %quotient, align 8
%43 = or i64 %42, %41
store i64 %43, i64* %quotient, align 8
br label %44
; <label>:44 ; preds = %32, %27
br label %45
; <label>:45 ; preds = %44
%46 = load i32* %i, align 4
%47 = add nsw i32 %46, 1
store i32 %47, i32* %i, align 4
br label %24
; <label>:48 ; preds = %24
%49 = load i64** %4, align 8
%50 = icmp ne i64* %49, null
br i1 %50, label %51, label %55
; <label>:51 ; preds = %48
%52 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0
%53 = load i64* %52, align 8
%54 = load i64** %4, align 8
store i64 %53, i64* %54, align 8
br label %55
; <label>:55 ; preds = %51, %48
%56 = load i64* %quotient, align 8
store i64 %56, i64* %1
br label %57
; <label>:57 ; preds = %55, %10
%58 = load i64* %1
ret i64 %58
}
define internal i32 @clz64(i64 %x) nounwind uwtable ssp {
%1 = alloca i64, align 8
%total_bits = alloca i32, align 4
%zc = alloca i32, align 4
store i64 %x, i64* %1, align 8
store i32 64, i32* %total_bits, align 4
store i32 0, i32* %zc, align 4
br label %2
; <label>:2 ; preds = %16, %0
%3 = load i32* %zc, align 4
%4 = icmp slt i32 %3, 64
br i1 %4, label %5, label %14
; <label>:5 ; preds = %2
%6 = load i64* %1, align 8
%7 = load i32* %zc, align 4
%8 = sub nsw i32 64, %7
%9 = sub nsw i32 %8, 1
%10 = zext i32 %9 to i64
%11 = lshr i64 %6, %10
%12 = and i64 %11, 1
%13 = icmp eq i64 %12, 0
br label %14
; <label>:14 ; preds = %5, %2
%15 = phi i1 [ false, %2 ], [ %13, %5 ]
br i1 %15, label %16, label %19
; <label>:16 ; preds = %14
%17 = load i32* %zc, align 4
%18 = add nsw i32 %17, 1
store i32 %18, i32* %zc, align 4
br label %2
; <label>:19 ; preds = %14
%20 = load i32* %zc, align 4
ret i32 %20
}
define internal void @div_state_lshift(%struct.div_state_* %state) nounwind uwtable ssp {
%1 = alloca %struct.div_state_*, align 8
store %struct.div_state_* %state, %struct.div_state_** %1, align 8
%2 = load %struct.div_state_** %1, align 8
%3 = getelementptr inbounds %struct.div_state_* %2, i32 0, i32 0
%4 = load i64* %3, align 8
%5 = shl i64 %4, 1
%6 = load %struct.div_state_** %1, align 8
%7 = getelementptr inbounds %struct.div_state_* %6, i32 0, i32 1
%8 = load i64* %7, align 8
%9 = lshr i64 %8, 63
%10 = or i64 %5, %9
%11 = load %struct.div_state_** %1, align 8
%12 = getelementptr inbounds %struct.div_state_* %11, i32 0, i32 0
store i64 %10, i64* %12, align 8
%13 = load %struct.div_state_** %1, align 8
%14 = getelementptr inbounds %struct.div_state_* %13, i32 0, i32 1
%15 = load i64* %14, align 8
%16 = shl i64 %15, 1
%17 = load %struct.div_state_** %1, align 8
%18 = getelementptr inbounds %struct.div_state_* %17, i32 0, i32 1
store i64 %16, i64* %18, align 8
ret void
}
define i64 @sdivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind uwtable ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%3 = alloca i64*, align 8
%signbitidx = alloca i32, align 4
%signed_dividend = alloca i32, align 4
%signed_divisor = alloca i32, align 4
%signed_result = alloca i32, align 4
%quotient = alloca i64, align 8
%udvd = alloca i64, align 8
%udvr = alloca i64, align 8
%uquotient = alloca i64, align 8
%uremainder = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
store i64* %remainder, i64** %3, align 8
store i32 63, i32* %signbitidx, align 4
%4 = load i64* %1, align 8
%5 = icmp slt i64 %4, 0
%6 = zext i1 %5 to i32
store i32 %6, i32* %signed_dividend, align 4
%7 = load i64* %2, align 8
%8 = icmp slt i64 %7, 0
%9 = zext i1 %8 to i32
store i32 %9, i32* %signed_divisor, align 4
%10 = load i32* %signed_divisor, align 4
%11 = load i32* %signed_dividend, align 4
%12 = xor i32 %10, %11
store i32 %12, i32* %signed_result, align 4
%13 = load i32* %signed_dividend, align 4
%14 = icmp ne i32 %13, 0
br i1 %14, label %15, label %18
; <label>:15 ; preds = %0
%16 = load i64* %1, align 8
%17 = sub nsw i64 0, %16
br label %20
; <label>:18 ; preds = %0
%19 = load i64* %1, align 8
br label %20
; <label>:20 ; preds = %18, %15
%21 = phi i64 [ %17, %15 ], [ %19, %18 ]
store i64 %21, i64* %udvd, align 8
%22 = load i32* %signed_divisor, align 4
%23 = icmp ne i32 %22, 0
br i1 %23, label %24, label %27
; <label>:24 ; preds = %20
%25 = load i64* %2, align 8
%26 = sub nsw i64 0, %25
br label %29
; <label>:27 ; preds = %20
%28 = load i64* %2, align 8
br label %29
; <label>:29 ; preds = %27, %24
%30 = phi i64 [ %26, %24 ], [ %28, %27 ]
store i64 %30, i64* %udvr, align 8
%31 = load i64* %udvd, align 8
%32 = load i64* %udvr, align 8
%33 = call i64 @udivmod64(i64 %31, i64 %32, i64* %uremainder)
store i64 %33, i64* %uquotient, align 8
%34 = load i32* %signed_result, align 4
%35 = icmp ne i32 %34, 0
br i1 %35, label %36, label %57
; <label>:36 ; preds = %29
%37 = load i64* %uremainder, align 8
%38 = icmp ne i64 %37, 0
br i1 %38, label %39, label %43
; <label>:39 ; preds = %36
%40 = load i64* %uquotient, align 8
%41 = sub nsw i64 0, %40
%42 = sub nsw i64 %41, 1
store i64 %42, i64* %quotient, align 8
br label %46
; <label>:43 ; preds = %36
%44 = load i64* %uquotient, align 8
%45 = sub nsw i64 0, %44
store i64 %45, i64* %quotient, align 8
br label %46
; <label>:46 ; preds = %43, %39
%47 = load i64** %3, align 8
%48 = icmp ne i64* %47, null
br i1 %48, label %49, label %56
; <label>:49 ; preds = %46
%50 = load i64* %1, align 8
%51 = load i64* %quotient, align 8
%52 = load i64* %2, align 8
%53 = mul i64 %51, %52
%54 = sub i64 %50, %53
%55 = load i64** %3, align 8
store i64 %54, i64* %55, align 8
br label %56
; <label>:56 ; preds = %49, %46
br label %73
; <label>:57 ; preds = %29
%58 = load i64* %uquotient, align 8
store i64 %58, i64* %quotient, align 8
%59 = load i64** %3, align 8
%60 = icmp ne i64* %59, null
br i1 %60, label %61, label %72
; <label>:61 ; preds = %57
%62 = load i32* %signed_divisor, align 4
%63 = icmp ne i32 %62, 0
br i1 %63, label %64, label %67
; <label>:64 ; preds = %61
%65 = load i64* %uremainder, align 8
%66 = sub i64 0, %65
br label %69
; <label>:67 ; preds = %61
%68 = load i64* %uremainder, align 8
br label %69
; <label>:69 ; preds = %67, %64
%70 = phi i64 [ %66, %64 ], [ %68, %67 ]
%71 = load i64** %3, align 8
store i64 %70, i64* %71, align 8
br label %72
; <label>:72 ; preds = %69, %57
br label %73
; <label>:73 ; preds = %72, %56
%74 = load i64* %quotient, align 8
ret i64 %74
}
define i64 @udiv64(i64 %dividend, i64 %divisor) nounwind uwtable ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @udivmod64(i64 %3, i64 %4, i64* null)
ret i64 %5
}
define i64 @sdiv64(i64 %dividend, i64 %divisor) nounwind uwtable ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @sdivmod64(i64 %3, i64 %4, i64* null)
ret i64 %5
}
define i64 @umod64(i64 %dividend, i64 %divisor) nounwind uwtable ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%rem = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @udivmod64(i64 %3, i64 %4, i64* %rem)
%6 = load i64* %rem, align 8
ret i64 %6
}
define i64 @smod64(i64 %dividend, i64 %divisor) nounwind uwtable ssp {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%rem = alloca i64, align 8
store i64 %dividend, i64* %1, align 8
store i64 %divisor, i64* %2, align 8
%3 = load i64* %1, align 8
%4 = load i64* %2, align 8
%5 = call i64 @sdivmod64(i64 %3, i64 %4, i64* %rem)
%6 = load i64* %rem, align 8
ret i64 %6
}

View file

@ -1,31 +0,0 @@
#ifndef LLVM_C_EXTRA_H_
#define LLVM_C_EXTRA_H_
#include <llvm-c/Core.h>
#ifdef __cplusplus
extern "C" {
#endif
// Resurrect from llvm-c/Core.h
#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \
inline ty *unwrap(ref P) { \
return reinterpret_cast<ty*>(P); \
} \
\
inline ref wrap(const ty *P) { \
return reinterpret_cast<ref>(const_cast<ty*>(P)); \
}
typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef;
typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
typedef struct LLVMOpaqueNamedMD *LLVMNamedMDRef;
typedef struct LLVMOpaquePass *LLVMPassRef;
#ifdef __cplusplus
}
#endif
#endif //LLVM_C_EXTRA_H_

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

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

View file

@ -37,191 +37,180 @@ are available.
import llvm # top-level, for common stuff
import llvm.core as core # module, function etc.
import llvm._core as _core # C wrappers
import llvm._util as _util # Utility functions
from llvmpy import api
import warnings
#===----------------------------------------------------------------------===
# Pass manager builder
#===----------------------------------------------------------------------===
class PassManagerBuilder(object):
class PassManagerBuilder(llvm.Wrapper):
@staticmethod
def new():
return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate())
def __init__(self, ptr):
self.ptr = ptr
def __del__(self):
_core.LLVMPassManagerBuilderDispose(self.ptr)
return PassManagerBuilder(api.llvm.PassManagerBuilder.new())
def populate(self, pm):
if isinstance(pm, FunctionPassManager):
return _core.LLVMPassManagerBuilderPopulateFunctionPassManager(
self.ptr, pm.ptr)
self._ptr.populateFunctionPassManager(pm._ptr)
else:
return _core.LLVMPassManagerBuilderPopulateModulePassManager(
self.ptr, pm.ptr)
self._ptr.populateModulePassManager(pm._ptr)
@property
def opt_level(self):
return self._ptr.OptLevel
@opt_level.setter
def opt_level(self, optlevel):
self._ptr.OptLevel = optlevel
@property
def size_level(self):
return self._ptr.SizeLevel
@size_level.setter
def size_level(self, sizelevel):
self._ptr.SizeLevel = sizelevel
if llvm.version >= (3, 3):
@property
def bbvectorize(self):
return self._ptr.BBVectorize
@bbvectorize.setter
def bbvectorize(self, enable):
self._ptr.BBVectorize = enable
vectorize = bbvectorize
@property
def slpvectorize(self):
return self._ptr.SLPVectorize
@slpvectorize.setter
def slpvectorize(self, enable):
self._ptr.SLPVectorize = enable
else:
@property
def vectorize(self):
return self._ptr.Vectorize
@vectorize.setter
def vectorize(self, enable):
self._ptr.Vectorize = enable
def _set_opt_level(self, optlevel):
_core.LLVMPassManagerBuilderSetOptLevel(self.ptr, optlevel)
def _get_opt_level(self):
return _core.LLVMPassManagerBuilderGetOptLevel(self.ptr)
opt_level = property(_get_opt_level, _set_opt_level)
def _set_size_level(self, sizelevel):
_core.LLVMPassManagerBuilderSetSizeLevel(self.ptr, sizelevel)
def _get_size_level(self):
return _core.LLVMPassManagerBuilderGetSizeLevel(self.ptr)
size_level = property(_get_size_level, _set_size_level)
def _set_vectorize(self, enable):
_core.LLVMPassManagerBuilderSetVectorize(self.ptr, int(bool(enable)))
def _get_vectorize(self):
return bool(_core.LLVMPassManagerBuilderGetVectorize(self.ptr))
vectorize = property(_get_vectorize, _set_vectorize)
def _set_loop_vectorize(self, enable):
if llvm.version >= (3, 2):
_core.LLVMPassManagerBuilderSetLoopVectorize(self.ptr,
int(bool(enable)))
elif enable:
warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.")
def _get_loop_vectorize(self):
@property
def loop_vectorize(self):
try:
return bool(_core.LLVMPassManagerBuilderGetLoopVectorize(self.ptr))
return self._ptr.LoopVectorize
except AttributeError:
return False
loop_vectorize = property(_get_loop_vectorize, _set_loop_vectorize)
@loop_vectorize.setter
def loop_vectorize(self, enable):
if llvm.version >= (3, 2):
self._ptr.LoopVectorize = enable
elif enable:
warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.")
def _set_disable_unit_at_a_time(self, disable):
return _core.LLVMPassManagerBuilderSetDisableUnitAtATime(
self.ptr, disable)
@property
def disable_unit_at_a_time(self):
return self._ptr.DisableUnitAtATime
def _get_disable_unit_at_a_time(self):
return _core.LLVMPassManagerBuilderGetDisableUnitAtATime(
self.ptr)
@disable_unit_at_a_time.setter
def disable_unit_at_a_time(self, disable):
self._ptr.DisableUnitAtATime = disable
disable_unit_at_a_time = property(_get_disable_unit_at_a_time,
_set_disable_unit_at_a_time)
@property
def disable_unroll_loops(self):
return self._ptr.DisableUnrollLoops
def _set_disable_unroll_loops(self, disable):
return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(
self.ptr, disable)
@disable_unroll_loops.setter
def disable_unroll_loops(self, disable):
self._ptr.DisableUnrollLoops = disable
def _get_disable_unroll_loops(self):
return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(self.ptr)
if llvm.version <= (3, 3):
@property
def disable_simplify_lib_calls(self):
return self._ptr.DisableSimplifyLibCalls
disable_unroll_loops = property(_get_disable_unroll_loops,
_set_disable_unroll_loops)
def _set_disable_simplify_lib_calls(self, disable):
return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(
self.ptr, disable)
def _get_disable_simplify_lib_calls(self):
return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(self.ptr)
disable_simplify_lib_calls = property(_get_disable_simplify_lib_calls,
_set_disable_simplify_lib_calls)
@disable_simplify_lib_calls.setter
def disable_simplify_lib_calls(self, disable):
self._ptr.DisableSimplifyLibCalls = disable
def use_inliner_with_threshold(self, threshold):
_core.LLVMPassManagerBuilderUseInlinerWithThreshold(self.ptr, threshold)
self._ptr.Inliner = api.llvm.createFunctionInliningPass(threshold)
#===----------------------------------------------------------------------===
# Pass manager
#===----------------------------------------------------------------------===
class PassManager(object):
class PassManager(llvm.Wrapper):
@staticmethod
def new():
return PassManager(_core.LLVMCreatePassManager())
def __init__(self, ptr):
self.ptr = ptr
def __del__(self):
_core.LLVMDisposePassManager(self.ptr)
return PassManager(api.llvm.PassManager.new())
def add(self, pass_obj):
'''Add a pass to the pass manager.
pass_obj --- Either a Pass instance, a string name of a pass
'''
if isinstance(pass_obj, Pass):
_util.check_is_unowned(pass_obj)
_core.LLVMAddPass(self.ptr, pass_obj.ptr)
pass_obj._own(self) # PassManager owns the pass
elif _util.isstring(pass_obj):
self._add_pass(pass_obj)
self._ptr.add(pass_obj._ptr)
else:
raise llvm.LLVMException("invalid pass_id (%s)" % pass_obj)
self._add_pass(str(pass_obj))
def _add_pass(self, pass_name):
status = _core.LLVMAddPassByName(self.ptr, pass_name)
if not status:
passreg = api.llvm.PassRegistry.getPassRegistry()
a_pass = passreg.getPassInfo(pass_name).createPass()
if not a_pass:
assert pass_name not in PASSES, "Registered but not found?"
raise llvm.LLVMException('Invalid pass name "%s"' % pass_name)
self._ptr.add(a_pass)
def run(self, module):
core.check_is_module(module)
return _core.LLVMRunPassManager(self.ptr, module.ptr)
return self._ptr.run(module._ptr)
class FunctionPassManager(PassManager):
@staticmethod
def new(module):
core.check_is_module(module)
ptr = _core.LLVMCreateFunctionPassManagerForModule(module.ptr)
ptr = api.llvm.FunctionPassManager.new(module._ptr)
return FunctionPassManager(ptr)
def __init__(self, ptr):
PassManager.__init__(self, ptr)
def initialize(self):
_core.LLVMInitializeFunctionPassManager(self.ptr)
self._ptr.doInitialization()
def run(self, fn):
core.check_is_function(fn)
return _core.LLVMRunFunctionPassManager(self.ptr, fn.ptr)
return self._ptr.run(fn._ptr)
def finalize(self):
_core.LLVMFinalizeFunctionPassManager(self.ptr)
self._ptr.doFinalization()
#===----------------------------------------------------------------------===
# Passes
#===----------------------------------------------------------------------===
class Pass(llvm.Ownable):
class Pass(llvm.Wrapper):
'''Pass Inferface
'''
def __init__(self, ptr):
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass)
self.__name = ''
'''
@staticmethod
def new(name):
'''Create a new pass by name.
Note: Not all pass has a default constructor. LLVM will kill
the process if an the pass requires arguments to construct.
The error cannot be caught.
'''
ptr = _core.LLVMCreatePassByName(name)
p = Pass(ptr)
Note: Not all pass has a default constructor. LLVM will kill
the process if an the pass requires arguments to construct.
The error cannot be caught.
'''
passreg = api.llvm.PassRegistry.getPassRegistry()
a_pass = passreg.getPassInfo(name).createPass()
p = Pass(a_pass)
p.__name = name
return p
@ -229,15 +218,17 @@ class Pass(llvm.Ownable):
def name(self):
'''The name used in PassRegistry.
'''
return self.__name
try:
return self.__name
except AttributeError:
return
@property
def description(self):
return _core.LLVMGetPassName(self.ptr)
return self._ptr.getPassName()
def dump(self):
return _core.LLVMPassDump(self.ptr)
return self._ptr.dump()
#===----------------------------------------------------------------------===
# Target data
@ -247,67 +238,59 @@ class TargetData(Pass):
@staticmethod
def new(strrep):
return TargetData(_core.LLVMCreateTargetData(strrep))
ptr = api.llvm.DataLayout.new(strrep)
return TargetData(ptr)
def clone(self):
return TargetData.new(str(self))
def __str__(self):
return _core.LLVMTargetDataAsString(self.ptr)
return self._ptr.getStringRepresentation()
@property
def byte_order(self):
return _core.LLVMByteOrder(self.ptr)
if self._ptr.isLittleEndian():
return 1
else:
return 0
@property
def pointer_size(self):
return _core.LLVMPointerSize(self.ptr)
return self._ptr.getPointerSize()
@property
def target_integer_type(self):
ptr = _core.LLVMIntPtrType(self.ptr);
return core.IntegerType(ptr, core.TYPE_INTEGER)
context = api.llvm.getGlobalContext()
return api.llvm.IntegerType(api.llvm.Type.getInt32Ty(context))
def size(self, ty):
core.check_is_type(ty)
return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr)
return self._ptr.getTypeSizeInBits(ty._ptr)
def store_size(self, ty):
core.check_is_type(ty)
return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr)
return self._ptr.getTypeStoreSize(ty._ptr)
def abi_size(self, ty):
core.check_is_type(ty)
return _core.LLVMABISizeOfType(self.ptr, ty.ptr)
return self._ptr.getTypeAllocSize(ty._ptr)
def abi_alignment(self, ty):
core.check_is_type(ty)
return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr)
return self._ptr.getABITypeAlignment(ty._ptr)
def callframe_alignment(self, ty):
core.check_is_type(ty)
return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr)
return self._ptr.getCallFrameTypeAlignment(ty._ptr)
def preferred_alignment(self, ty_or_gv):
if isinstance(ty_or_gv, core.Type):
return _core.LLVMPreferredAlignmentOfType(self.ptr,
ty_or_gv.ptr)
return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr)
elif isinstance(ty_or_gv, core.GlobalVariable):
return _core.LLVMPreferredAlignmentOfGlobal(self.ptr,
ty_or_gv.ptr)
return self._ptr.getPreferredAlignment(ty_or_gv._ptr)
else:
raise core.LLVMException("argument is neither a type nor a global variable")
def element_at_offset(self, ty, ofs):
core.check_is_type_struct(ty)
ofs = int(ofs) # ofs is unsigned long long
return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs)
return self._ptr.getStructLayout(ty._ptr).getElementContainingOffset(ofs)
def offset_of_element(self, ty, el):
core.check_is_type_struct(ty)
el = int(el) # el should be an int
return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el)
return self._ptr.getStructLayout(ty._ptr).getElementOffset(el)
#===----------------------------------------------------------------------===
# Target Library Info
@ -316,19 +299,20 @@ class TargetData(Pass):
class TargetLibraryInfo(Pass):
@staticmethod
def new(triple):
ptr = _core.LLVMCreateTargetLibraryInfo(triple)
triple = api.llvm.Triple.new(str(triple))
ptr = api.llvm.TargetLibraryInfo.new(triple)
return TargetLibraryInfo(ptr)
#===----------------------------------------------------------------------===
# Target Transform Info
# Target Transformation Info
#===----------------------------------------------------------------------===
class TargetTransformInfo(Pass):
@staticmethod
def new(targetmachine):
llvm.require_version_at_least(3, 2)
ptr = _core.LLVMCreateTargetTransformInfo(targetmachine.ptr)
scalartti = targetmachine._ptr.getScalarTargetTransformInfo()
vectortti = targetmachine._ptr.getVectorTargetTransformInfo()
ptr = api.llvm.TargetTransformInfo.new(scalartti, vectortti)
return TargetTransformInfo(ptr)
@ -336,21 +320,35 @@ class TargetTransformInfo(Pass):
# Helpers
#===----------------------------------------------------------------------===
def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
inline_threshold=2000, pm=True, fpm=True, mod=None):
'''
tm --- The TargetMachine for which the passes are optimizing for.
The TargetMachine must stay alive until the pass managers
are removed.
opt --- [0-3] Optimization level. Default to 2.
loop_vectorize --- [boolean] Whether to use loop-vectorizer.
vectorize --- [boolean] Whether to use basic-block vectorizer.
inline_threshold --- [int] Threshold for the inliner.
features --- [str] CPU feature string.
pm --- [boolean] Whether to build a module-level pass-manager.
fpm --- [boolean] Whether to build a function-level pass-manager.
mod --- [Module] The module object for the FunctionPassManager.
def build_pass_managers(tm, opt=2, size=0, loop_vectorize=False,
slp_vectorize=False, vectorize=False,
inline_threshold=None, pm=True, fpm=True, mod=None):
'''
tm --- The TargetMachine for which the passes are optimizing for.
The TargetMachine must stay alive until the pass managers
are removed.
opt --- [0-3] Optimization level. Default to 2.
size --- [0-2] Optimize for size. Default to 0.
loop_vectorize --- [boolean] Whether to use loop-vectorizer.
vectorize --- [boolean] Whether to use basic-block vectorizer.
inline_threshold --- [int] Threshold for the inliner.
features --- [str] CPU feature string.
pm --- [boolean] Whether to build a module-level pass-manager.
fpm --- [boolean] Whether to build a function-level pass-manager.
mod --- [Module] The module object for the FunctionPassManager.
'''
if inline_threshold is None:
if 0 < opt < 3:
inline_threshold = 225
if size == 1:
inline_threshold = 75
elif size == 2:
inline_threshold = 25
if opt >= 3:
inline_threshold = 275
if pm:
pm = PassManager.new()
if fpm:
@ -363,27 +361,31 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
pmb.opt_level = opt
pmb.vectorize = vectorize
pmb.loop_vectorize = loop_vectorize
if llvm.version >= (3, 3):
pmb.slp_vectorize = slp_vectorize
if inline_threshold:
pmb.use_inliner_with_threshold(inline_threshold)
if pm:
pm.add(tm.target_data.clone())
pm.add(TargetLibraryInfo.new(tm.triple))
if llvm.version >= (3, 2):
if llvm.version <= (3, 2):
pm.add(TargetTransformInfo.new(tm))
else:
tm.add_analysis_passes(pm)
pmb.populate(pm)
if fpm:
fpm.add(tm.target_data)
fpm.add(tm.target_data.clone())
fpm.add(TargetLibraryInfo.new(tm.triple))
if llvm.version >= (3, 2):
if llvm.version <= (3, 2):
fpm.add(TargetTransformInfo.new(tm))
else:
tm.add_analysis_passes(fpm)
pmb.populate(fpm)
fpm.initialize()
from collections import namedtuple
return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm)
#===----------------------------------------------------------------------===
# Misc.
#===----------------------------------------------------------------------===
@ -392,16 +394,26 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
PASSES = None
def _dump_all_passes():
passes_sep_by_line = _core.LLVMDumpPasses()
strip = lambda S : S.strip()
for line in passes_sep_by_line.splitlines():
passarg, passname = map(strip, line.split('\t', 1))
if passarg:
yield passarg, passname
passreg = api.llvm.PassRegistry.getPassRegistry()
for name, desc in passreg.enumerate():
yield name, desc
def _initialize_passes():
global PASSES
_core.LLVMInitializePasses()
passreg = api.llvm.PassRegistry.getPassRegistry()
api.llvm.initializeCore(passreg)
api.llvm.initializeScalarOpts(passreg)
api.llvm.initializeVectorization(passreg)
api.llvm.initializeIPO(passreg)
api.llvm.initializeAnalysis(passreg)
api.llvm.initializeIPA(passreg)
api.llvm.initializeTransformUtils(passreg)
api.llvm.initializeInstCombine(passreg)
api.llvm.initializeInstrumentation(passreg)
api.llvm.initializeTarget(passreg)
PASSES = dict(_dump_all_passes())
# build globals

View file

@ -1,973 +0,0 @@
--- .\setup-win32.py (original)
+++ .\setup-win32.py (refactored)
@@ -145,10 +145,10 @@
# get llvm config
llvm_dir, llvm_build_dir, is_good = get_llvm_config()
- print "Using llvm-dir=" + llvm_dir + " and llvm-build-dir=" + llvm_build_dir
+ print("Using llvm-dir=" + llvm_dir + " and llvm-build-dir=" + llvm_build_dir)
if not is_good:
- print "Cannot find llvm-dir or llvm-build-dir"
- print "Try again with --llvm-dir=/path/to/llvm-top-dir --llvm-build-dir=/path/to/llvm/cmake/dir."
+ print("Cannot find llvm-dir or llvm-build-dir")
+ print("Try again with --llvm-dir=/path/to/llvm-top-dir --llvm-build-dir=/path/to/llvm/cmake/dir.")
return 1
# setup
--- .\setup.py (original)
+++ .\setup.py (refactored)
@@ -120,10 +120,10 @@
# get llvm config
llvm_config, is_good = get_llvm_config()
if is_good:
- print "Using llvm-config=" + llvm_config
+ print("Using llvm-config=" + llvm_config)
else:
- print "Cannot invoke llvm-config (tried '%s')." % llvm_config
- print "Try again with --llvm-config=/path/to/llvm-config."
+ print("Cannot invoke llvm-config (tried '%s')." % llvm_config)
+ print("Try again with --llvm-config=/path/to/llvm-config.")
return 1
# setup
--- .\llvm\__init__.py (original)
+++ .\llvm\__init__.py (refactored)
@@ -68,12 +68,12 @@
def _own(self, owner):
if self.owner:
- raise LLVMException, "object already owned"
+ raise LLVMException("object already owned")
self.owner = owner
def _disown(self):
if not self.owner:
- raise LLVMException, "not owned"
+ raise LLVMException("not owned")
self.owner = None
def __del__(self):
@@ -135,15 +135,13 @@
# Cacheables
#===----------------------------------------------------------------------===
-class Cacheable(object):
+class Cacheable(object, metaclass=_ObjectCache):
"""Objects that can be cached.
Objects that wrap a PyCObject are cached to avoid "aliasing", i.e.,
two Python objects each containing a PyCObject which internally points
to the same C pointer."""
- __metaclass__ = _ObjectCache
-
def forget(self):
_ObjectCache.forget(self)
--- .\llvm\_util.py (original)
+++ .\llvm\_util.py (refactored)
@@ -45,11 +45,11 @@
if not isinstance(obj, typ):
typ_str = typ.__name__
msg = "argument not an instance of llvm.core.%s" % typ_str
- raise TypeError, msg
+ raise TypeError(msg)
def check_is_unowned(ownable):
if ownable.owner:
- raise llvm.LLVMException, "object is already owned"
+ raise llvm.LLVMException("object is already owned")
#===----------------------------------------------------------------------===
--- .\llvm\core.py (original)
+++ .\llvm\core.py (refactored)
@@ -297,7 +297,7 @@
if isinstance(typ, PointerType) and \
isinstance(typ.pointee, FunctionType):
return
- raise TypeError, "argument is neither a function nor a function pointer"
+ raise TypeError("argument is neither a function nor a function pointer")
def _to_int(v):
if v:
@@ -341,9 +341,9 @@
data = fileobj.read()
ret = _core.LLVMGetModuleFromBitcode(data)
if not ret:
- raise llvm.LLVMException, "Unable to create module from bitcode"
+ raise llvm.LLVMException("Unable to create module from bitcode")
elif isinstance(ret, str):
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
else:
return Module(ret)
@@ -355,10 +355,9 @@
data = fileobj.read()
ret = _core.LLVMGetModuleFromAssembly(data)
if not ret:
- raise llvm.LLVMException, \
- "Unable to create module from assembly"
+ raise llvm.LLVMException("Unable to create module from assembly")
elif isinstance(ret, str):
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
else:
return Module(ret)
@@ -437,7 +436,7 @@
other.forget() # remove it from object cache
ret = _core.LLVMLinkModules(self.ptr, other.ptr)
if isinstance(ret, str):
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
# Do not try to destroy the other module's llvm::Module*.
other._own(llvm.DummyOwner())
@@ -506,7 +505,7 @@
error."""
ret = _core.LLVMVerifyModule(self.ptr)
if ret != "":
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
def to_bitcode(self, fileobj):
"""Write bitcode representation of module to given file-like
@@ -514,7 +513,7 @@
data = _core.LLVMGetBitcodeFromModule(self.ptr)
if not data:
- raise llvm.LLVMException, "Unable to create bitcode"
+ raise llvm.LLVMException("Unable to create bitcode")
fileobj.write(data)
@@ -1236,7 +1235,7 @@
check_is_module(module)
ptr = _core.LLVMGetNamedGlobal(module.ptr, name)
if not ptr:
- raise llvm.LLVMException, ("no global named `%s`" % name)
+ raise llvm.LLVMException("no global named `%s`" % name)
return _make_value(ptr)
def delete(self):
@@ -1307,7 +1306,7 @@
check_is_module(module)
ptr = _core.LLVMGetNamedFunction(module.ptr, name)
if not ptr:
- raise llvm.LLVMException, ("no function named `%s`" % name)
+ raise llvm.LLVMException("no function named `%s`" % name)
return _make_value(ptr)
@staticmethod
@@ -2006,7 +2005,7 @@
ret = _core.LLVMLoadLibraryPermanently(filename)
if isinstance(ret, str):
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
def inline_function(call):
check_is_value(call)
--- .\llvm\ee.py (original)
+++ .\llvm\ee.py (refactored)
@@ -103,12 +103,11 @@
return _core.LLVMPreferredAlignmentOfGlobal(self.ptr,
ty_or_gv.ptr)
else:
- raise core.LLVMException, \
- "argument is neither a type nor a global variable"
+ raise core.LLVMException("argument is neither a type nor a global variable")
def element_at_offset(self, ty, ofs):
core.check_is_type_struct(ty)
- ofs = long(ofs) # ofs is unsigned long long
+ ofs = int(ofs) # ofs is unsigned long long
return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs)
def offset_of_element(self, ty, el):
@@ -185,7 +184,7 @@
_util.check_is_unowned(module)
ret = _core.LLVMCreateExecutionEngine(module.ptr, int(force_interpreter))
if isinstance(ret, str):
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
return ExecutionEngine(ret, module)
def __init__(self, ptr, module):
@@ -223,10 +222,10 @@
def remove_module(self, module):
core.check_is_module(module)
if module.owner != self:
- raise llvm.LLVMException, "module is not owned by self"
+ raise llvm.LLVMException("module is not owned by self")
ret = _core.LLVMRemoveModule2(self.ptr, module.ptr)
if isinstance(ret, str):
- raise llvm.LLVMException, ret
+ raise llvm.LLVMException(ret)
return core.Module(ret)
@property
--- .\llvm\passes.py (original)
+++ .\llvm\passes.py (refactored)
@@ -245,8 +245,7 @@
elif tgt_data_or_pass_id in _pass_creator:
self._add_pass(tgt_data_or_pass_id)
else:
- raise llvm.LLVMException, \
- ("invalid pass_id (%s)" % str(tgt_data_or_pass_id))
+ raise llvm.LLVMException("invalid pass_id (%s)" % str(tgt_data_or_pass_id))
def _add_target_data(self, tgt):
_core.LLVMAddTargetData(tgt.ptr, self.ptr)
--- .\test\JITTutorial1.py (original)
+++ .\test\JITTutorial1.py (refactored)
@@ -28,4 +28,4 @@
bldr.ret (tmp_2)
-print module
+print(module)
--- .\test\JITTutorial2.py (original)
+++ .\test\JITTutorial2.py (refactored)
@@ -47,4 +47,4 @@
recur_2 = bldr.call (gcd, (x_sub_y, y,), "tmp")
bldr.ret (recur_2)
-print module
+print(module)
--- .\test\asm.py (original)
+++ .\test\asm.py (refactored)
@@ -9,9 +9,9 @@
# write it's assembly representation to a file
asm = str(m)
-print >> file("/tmp/testasm.ll", "w"), asm
+print(asm, file=file("/tmp/testasm.ll", "w"))
# read it back into a module
m2 = Module.from_assembly(file("/tmp/testasm.ll"))
-print m2
+print(m2)
--- .\test\call-jit-ctypes.py (original)
+++ .\test\call-jit-ctypes.py (refactored)
@@ -42,7 +42,7 @@
if 0:
# print the created module
- print my_module
+ print(my_module)
# compile the function
ee = ExecutionEngine.new(my_module)
--- .\test\example-jit.py (original)
+++ .\test\example-jit.py (refactored)
@@ -29,5 +29,5 @@
retval = ee.run_function(f_sum, [arg1, arg2])
# The return value is also GenericValue. Let's print it.
-print "returned", retval.as_int()
+print("returned", retval.as_int())
--- .\test\example.py (original)
+++ .\test\example.py (refactored)
@@ -41,5 +41,5 @@
# We've completed the definition now! Let's see the LLVM assembly
# language representation of what we've created:
-print my_module
+print(my_module)
--- .\test\intrinsic.py (original)
+++ .\test\intrinsic.py (refactored)
@@ -16,7 +16,7 @@
val = Constant.int(Type.int(), 42)
bswap = Function.intrinsic(mod, INTR_BSWAP, [Type.int()])
b.call(bswap, [val])
-print mod
+print(mod)
# the output is:
#
@@ -50,7 +50,7 @@
onemc2 = b.sub(one, cos2, "onemc2")
sin = b.call(sqrt, [onemc2], "sin")
b.ret(sin)
-print mod
+print(mod)
#
# ; ModuleID = 'test'
--- .\test\objcache.py (original)
+++ .\test\objcache.py (refactored)
@@ -4,17 +4,17 @@
def check(a, b):
if a is b:
- print "OK"
+ print("OK")
else:
- print "FAIL"
+ print("FAIL")
def check_isnot(a, b):
if not (a is b):
- print "OK"
+ print("OK")
else:
- print "FAIL"
+ print("FAIL")
-print "Testing module aliasing ..",
+print("Testing module aliasing ..", end=' ')
m1 = Module.new('a')
t = Type.int()
ft = Type.function(t, [t])
@@ -22,75 +22,75 @@
m2 = f1.module
check(m1, m2)
-print "Testing global vairable aliasing 1 .. ",
+print("Testing global vairable aliasing 1 .. ", end=' ')
gv1 = GlobalVariable.new(m1, t, "gv")
gv2 = GlobalVariable.get(m1, "gv")
check(gv1, gv2)
-print "Testing global vairable aliasing 2 .. ",
+print("Testing global vairable aliasing 2 .. ", end=' ')
gv3 = m1.global_variables[0]
check(gv1, gv3)
-print "Testing global vairable aliasing 3 .. ",
+print("Testing global vairable aliasing 3 .. ", end=' ')
gv2 = None
gv3 = None
gv1.delete()
gv4 = GlobalVariable.new(m1, t, "gv")
check_isnot(gv1, gv4)
-print "Testing function aliasing 1 ..",
+print("Testing function aliasing 1 ..", end=' ')
b1 = f1.append_basic_block('entry')
f2 = b1.function
check(f1, f2)
-print "Testing function aliasing 2 ..",
+print("Testing function aliasing 2 ..", end=' ')
f3 = m1.get_function_named("func")
check(f1, f3)
-print "Testing function aliasing 3 ..",
+print("Testing function aliasing 3 ..", end=' ')
f4 = Function.get_or_insert(m1, ft, "func")
check(f1, f4)
-print "Testing function aliasing 4 ..",
+print("Testing function aliasing 4 ..", end=' ')
f5 = Function.get(m1, "func")
check(f1, f5)
-print "Testing function aliasing 5 ..",
+print("Testing function aliasing 5 ..", end=' ')
f6 = m1.get_or_insert_function(ft, "func")
check(f1, f6)
-print "Testing function aliasing 6 ..",
+print("Testing function aliasing 6 ..", end=' ')
f7 = m1.functions[0]
check(f1, f7)
-print "Testing argument aliasing .. ",
+print("Testing argument aliasing .. ", end=' ')
a1 = f1.args[0]
a2 = f1.args[0]
check(a1, a2)
-print "Testing basic block aliasing 1 .. ",
+print("Testing basic block aliasing 1 .. ", end=' ')
b2 = f1.basic_blocks[0]
check(b1, b2)
-print "Testing basic block aliasing 2 .. ",
+print("Testing basic block aliasing 2 .. ", end=' ')
b3 = f1.get_entry_basic_block()
check(b1, b3)
-print "Testing basic block aliasing 3 .. ",
+print("Testing basic block aliasing 3 .. ", end=' ')
b31 = f1.entry_basic_block
check(b1, b31)
-print "Testing basic block aliasing 4 .. ",
+print("Testing basic block aliasing 4 .. ", end=' ')
bldr = Builder.new(b1)
b4 = bldr.basic_block
check(b1, b4)
-print "Testing basic block aliasing 5 .. ",
+print("Testing basic block aliasing 5 .. ", end=' ')
i1 = bldr.ret_void()
b5 = i1.basic_block
check(b1, b5)
-print "Testing instruction aliasing 1 .. ",
+print("Testing instruction aliasing 1 .. ", end=' ')
i2 = b5.instructions[0]
check(i1, i2)
@@ -100,9 +100,9 @@
v2 = phi.get_incoming_value(0)
b6 = phi.get_incoming_block(0)
-print "Testing PHI / basic block aliasing 5 .. ",
+print("Testing PHI / basic block aliasing 5 .. ", end=' ')
check(b1, b6)
-print "Testing PHI / value aliasing .. ",
+print("Testing PHI / value aliasing .. ", end=' ')
check(f1.args[0], v2)
--- .\test\operands.py (original)
+++ .\test\operands.py (refactored)
@@ -28,9 +28,9 @@
def __init__(self): pass
def read(self): return test_module
m = Module.from_assembly(strstream())
-print "-"*60
-print m
-print "-"*60
+print("-"*60)
+print(m)
+print("-"*60)
test_func = m.get_function_named("test_func")
prod = m.get_function_named("prod")
@@ -38,16 +38,16 @@
#===----------------------------------------------------------------------===
# test operands
-print
+print()
i1 = test_func.basic_blocks[0].instructions[0]
i2 = test_func.basic_blocks[0].instructions[1]
-print "Testing User.operand_count ..",
+print("Testing User.operand_count ..", end=' ')
if i1.operand_count == 3 and i2.operand_count == 2:
- print "OK"
+ print("OK")
else:
- print "FAIL"
+ print("FAIL")
-print "Testing User.operands ..",
+print("Testing User.operands ..", end=' ')
c1 = i1.operands[0] is prod
c2 = i1.operands[1] is test_func.args[0]
c3 = i1.operands[2] is test_func.args[1]
@@ -56,22 +56,22 @@
c6 = len(i1.operands) == 3
c7 = len(i2.operands) == 2
if c1 and c2 and c3 and c5 and c6 and c7:
- print "OK"
+ print("OK")
else:
- print "FAIL"
-print
+ print("FAIL")
+print()
#===----------------------------------------------------------------------===
# show test_function
-print "Examining test_function `test_test_func':"
+print("Examining test_function `test_test_func':")
idx = 1
for inst in test_func.basic_blocks[0].instructions:
- print "Instruction #%d:" % (idx,)
- print " operand_count =", inst.operand_count
- print " operands:"
+ print("Instruction #%d:" % (idx,))
+ print(" operand_count =", inst.operand_count)
+ print(" operands:")
oidx = 1
for op in inst.operands:
- print " %d: %s" % (oidx, repr(op))
+ print(" %d: %s" % (oidx, repr(op)))
oidx += 1
idx += 1
--- .\test\passes.py (original)
+++ .\test\passes.py (refactored)
@@ -36,8 +36,8 @@
}
"""
m = Module.from_assembly(strstream(asm))
-print "-"*72
-print m
+print("-"*72)
+print(m)
# Let's run a module-level inlining pass. First, create a pass manager.
pm = PassManager.new()
@@ -55,8 +55,8 @@
del pm
# Print the result. Note the change in @test2.
-print "-"*72
-print m
+print("-"*72)
+print(m)
# Let's run a DCE pass on the the function 'test1' now. First create a
@@ -73,5 +73,5 @@
fpm.run( m.get_function_named('test1') )
# Print the result. Note the change in @test1.
-print "-"*72
-print m
+print("-"*72)
+print(m)
--- .\test\test.py (original)
+++ .\test\test.py (refactored)
@@ -69,7 +69,7 @@
# done
if gc.garbage:
- print "garbage = ", gc.garbage
+ print("garbage = ", gc.garbage)
main()
--- .\test\testall.py (original)
+++ .\test\testall.py (refactored)
@@ -15,12 +15,12 @@
def do_llvmexception():
- print " Testing class LLVMException"
+ print(" Testing class LLVMException")
e = LLVMException()
def do_ownable():
- print " Testing class Ownable"
+ print(" Testing class Ownable")
o = Ownable(None, lambda x: None)
try:
o._own(None)
@@ -30,7 +30,7 @@
def do_misc():
- print " Testing miscellaneous functions"
+ print(" Testing miscellaneous functions")
try:
load_library_permanently("/usr/lib/libm.so")
except LLVMException:
@@ -42,14 +42,14 @@
def do_llvm():
- print " Testing module llvm"
+ print(" Testing module llvm")
do_llvmexception()
do_ownable()
do_misc()
def do_module():
- print " Testing class Module"
+ print(" Testing class Module")
m = Module.new('test')
m.target = 'a'
a = m.target
@@ -101,7 +101,7 @@
def do_type():
- print " Testing class Type"
+ print(" Testing class Type")
for i in range(1,100):
Type.int(i)
Type.float()
@@ -151,14 +151,14 @@
def do_typehandle():
- print " Testing class TypeHandle"
+ print(" Testing class TypeHandle")
th = TypeHandle.new(Type.opaque())
ts = Type.struct([ Type.int(), Type.pointer(th.type) ])
th.type.refine(ts)
def do_value():
- print " Testing class Value"
+ print(" Testing class Value")
k = Constant.int(ti, 42)
k.name = 'a'
s = k.name
@@ -186,7 +186,7 @@
def do_constant():
- print " Testing class Constant"
+ print(" Testing class Constant")
Constant.null(ti)
Constant.all_ones(ti)
Constant.undef(ti)
@@ -231,7 +231,7 @@
def do_global_value():
- print " Testing class GlobalValue"
+ print(" Testing class GlobalValue")
m = Module.new('a')
gv = GlobalVariable.new(m, Type.int(), 'b')
s = gv.is_declaration
@@ -247,7 +247,7 @@
def do_global_variable():
- print " Testing class GlobalVariable"
+ print(" Testing class GlobalVariable")
m = Module.new('a')
gv = GlobalVariable.new(m, Type.int(), 'b')
gv = GlobalVariable.get(m, 'b')
@@ -260,7 +260,7 @@
def do_argument():
- print " Testing class Argument"
+ print(" Testing class Argument")
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
@@ -272,7 +272,7 @@
def do_function():
- print " Testing class Function"
+ print(" Testing class Function")
ft = Type.function(ti, [ti]*20)
zz = Function.new(Module.new('z'), ft, 'foobar')
del zz
@@ -307,7 +307,7 @@
def do_instruction():
- print " Testing class Instruction"
+ print(" Testing class Instruction")
m = Module.new('a')
ft = Type.function(ti, [ti]*20)
f = Function.new(m, ft, 'func')
@@ -320,7 +320,7 @@
def do_callorinvokeinstruction():
- print " Testing class CallOrInvokeInstruction"
+ print(" Testing class CallOrInvokeInstruction")
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
@@ -337,7 +337,7 @@
def do_phinode():
- print " Testing class PhiNode"
+ print(" Testing class PhiNode")
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
@@ -354,7 +354,7 @@
def do_switchinstruction():
- print " Testing class SwitchInstruction"
+ print(" Testing class SwitchInstruction")
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
@@ -365,7 +365,7 @@
def do_basicblock():
- print " Testing class BasicBlock"
+ print(" Testing class BasicBlock")
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
@@ -395,7 +395,7 @@
def do_builder():
- print " Testing class Builder"
+ print(" Testing class Builder")
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
@@ -488,7 +488,7 @@
def do_llvm_core():
- print " Testing module llvm.core"
+ print(" Testing module llvm.core")
do_module()
do_type()
do_typehandle()
@@ -508,7 +508,7 @@
def do_targetdata():
- print " Testing class TargetData"
+ print(" Testing class TargetData")
t = TargetData.new('')
v = str(t)
v = t.byte_order
@@ -530,7 +530,7 @@
def do_genericvalue():
- print " Testing class GenericValue"
+ print(" Testing class GenericValue")
v = GenericValue.int(ti, 1)
v = GenericValue.int_signed(ti, 1)
v = GenericValue.real(Type.float(), 3.14)
@@ -540,7 +540,7 @@
def do_executionengine():
- print " Testing class ExecutionEngine"
+ print(" Testing class ExecutionEngine")
m = Module.new('a')
ee = ExecutionEngine.new(m, True)
ft = Type.function(ti, [])
@@ -567,14 +567,14 @@
def do_llvm_ee():
- print " Testing module llvm.ee"
+ print(" Testing module llvm.ee")
do_targetdata()
do_genericvalue()
do_executionengine()
def do_passmanager():
- print " Testing class PassManager"
+ print(" Testing class PassManager")
pm = PassManager.new()
pm.add(TargetData.new(''))
for i in [getattr(llvm.passes, x) for x in \
@@ -586,7 +586,7 @@
def do_functionpassmanager():
- print " Testing class FunctionPassManager"
+ print(" Testing class FunctionPassManager")
m = Module.new('a')
ft = Type.function(ti, [])
f = m.add_function(ft, 'func')
@@ -602,13 +602,13 @@
def do_llvm_passes():
- print " Testing module llvm.passes"
+ print(" Testing module llvm.passes")
do_passmanager()
do_functionpassmanager()
def main():
- print "Testing package llvm"
+ print("Testing package llvm")
do_llvm()
do_llvm_core()
do_llvm_ee()
--- .\test\testattrs.py (original)
+++ .\test\testattrs.py (refactored)
@@ -1,7 +1,7 @@
#!/usr/bin/env python
from llvm.core import *
-from cStringIO import StringIO
+from io import StringIO
def make_module():
--- .\test\typehandle.py (original)
+++ .\test\typehandle.py (refactored)
@@ -16,4 +16,4 @@
m.add_type_name("struct.node", th.type)
# show what we created
-print m
+print(m)
--- .\test\uses.py (original)
+++ .\test\uses.py (refactored)
@@ -13,11 +13,11 @@
tmp3 = bld.add(tmp1, f.args[2], "tmp3")
bld.ret(tmp3)
-print "-"*60
-print m
-print "-"*60
+print("-"*60)
+print(m)
+print("-"*60)
-print "Testing use count ..",
+print("Testing use count ..", end=' ')
c1 = f.args[0].use_count == 1
c2 = f.args[1].use_count == 1
c3 = f.args[2].use_count == 1
@@ -25,11 +25,11 @@
c5 = tmp2.use_count == 0
c6 = tmp3.use_count == 1
if c1 and c2 and c3 and c4 and c5 and c6:
- print "OK"
+ print("OK")
else:
- print "FAIL"
+ print("FAIL")
-print "Testing uses ..",
+print("Testing uses ..", end=' ')
c1 = f.args[0].uses[0] is tmp1
c2 = len(f.args[0].uses) == 1
c3 = f.args[1].uses[0] is tmp2
@@ -40,6 +40,6 @@
c8 = len(tmp2.uses) == 0
c9 = len(tmp3.uses) == 1
if c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8 and c9:
- print "OK"
+ print("OK")
else:
- print "FAIL"
+ print("FAIL")
--- .\tools\intrgen.py (original)
+++ .\tools\intrgen.py (refactored)
@@ -26,7 +26,7 @@
idx = 1
for i in intr:
s = 'INTR_' + i.upper()
- print '%s = %d' % (s.ljust(maxw), idx)
+ print('%s = %d' % (s.ljust(maxw), idx))
idx += 1
gen(sys.argv[1])
--- .\tools\intrs_for_doc.py (original)
+++ .\tools\intrs_for_doc.py (refactored)
@@ -21,5 +21,5 @@
outf = open(OUTF, 'wt')
i = 0
while i < len(intrs):
- print >>outf, "`" + "`,`".join(intrs[i:min(i+NCOLS,len(intrs)+1)]) + "`"
+ print("`" + "`,`".join(intrs[i:min(i+NCOLS,len(intrs)+1)]) + "`", file=outf)
i += NCOLS
--- .\www\makeweb.py (original)
+++ .\www\makeweb.py (refactored)
@@ -52,7 +52,7 @@
def _rmtree_warn(fn, path, excinfo):
- print "** WARNING **: error while doing %s on %s" % (fn, path)
+ print("** WARNING **: error while doing %s on %s" % (fn, path))
def _can_skip(opts, infile, outfile):
@@ -67,14 +67,14 @@
cmd = cmdfn(opts, infile, outfile_actual)
if _can_skip(opts, infile, outfile_actual):
if opts.verbose >= 2:
- print "up to date %s -> %s" % (infile, outfile_actual)
+ print("up to date %s -> %s" % (infile, outfile_actual))
return
if cmd:
# do cmd
if opts.verbose:
- print "process %s -> %s" % (infile, outfile_actual)
+ print("process %s -> %s" % (infile, outfile_actual))
if opts.verbose >= 3:
- print "command is [%s]" % cmd
+ print("command is [%s]" % cmd)
if not opts.dryrun:
os.system(cmd)
# else if cmd is None, do nothing
@@ -83,7 +83,7 @@
# nothing matched, default action is to copy
if not _can_skip(opts, infile, outfile):
if opts.verbose:
- print "copying %s -> %s" % (infile, outfile)
+ print("copying %s -> %s" % (infile, outfile))
if not opts.dryrun:
shutil.copy(infile, outfile)
@@ -95,14 +95,14 @@
# if it exists, it must be a dir!
if odexists and not os.path.isdir(outdir):
- print "** WARNING **: output dir '%s' exists but is " \
- "not a dir, skipping" % outdir
+ print("** WARNING **: output dir '%s' exists but is " \
+ "not a dir, skipping" % outdir)
return
# make outdir if not existing
if not odexists:
if opts.verbose:
- print "creating %s" % outdir
+ print("creating %s" % outdir)
if not opts.dryrun:
os.mkdir(outdir)
@@ -114,8 +114,8 @@
# process files
if os.path.isfile(inp):
if os.path.exists(outp) and not os.path.isfile(outp):
- print "** WARNING **: output '%s' corresponding to " \
- "input '%s' is not a file, skipping" % (outp, inp)
+ print("** WARNING **: output '%s' corresponding to " \
+ "input '%s' is not a file, skipping" % (outp, inp))
else:
process_file(opts, inp, outp)
@@ -124,15 +124,15 @@
# if dir is in skip list, silently ignore
if elem in DIR_SKIP_TBL:
if opts.verbose >= 3:
- print "skipping %s" % inp
+ print("skipping %s" % inp)
continue
# just recurse
make(opts, inp, outp)
# neither a file nor a dir
else:
- print "** WARNING **: input '%s' is neither file nor " \
- "dir, skipping" % inp
+ print("** WARNING **: input '%s' is neither file nor " \
+ "dir, skipping" % inp)
def get_opts():
@@ -173,14 +173,14 @@
def main():
opts, src, dest = get_opts()
if opts.verbose >= 3:
- print ("running with options:\nsrc = [%s]\ndest = [%s]\nverbose = [%d]\n" +\
+ print(("running with options:\nsrc = [%s]\ndest = [%s]\nverbose = [%d]\n" +\
"dry-run = [%d]\nclean-first = [%d]\nforce = [%d]") %\
- (src, dest, opts.verbose, opts.dryrun, opts.clean, opts.force)
+ (src, dest, opts.verbose, opts.dryrun, opts.clean, opts.force))
if opts.dryrun and opts.verbose == 0:
opts.verbose = 1
if opts.clean:
if opts.dryrun or opts.verbose:
- print "removing tree %s" % dest
+ print("removing tree %s" % dest)
if not opts.dryrun:
os.rmtree(dest, True, _rmtree_warn)
make(opts, src, dest)

View file

@ -1,62 +0,0 @@
C:\Users\AndrewBC\src\llvm-py>python "C:\Program Files\Python27\Tools\Scripts\2to3.py" -w -f all -f idioms . > llvm/py3k_update.diff
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored .\setup-win32.py
RefactoringTool: Refactored .\setup.py
RefactoringTool: Refactored .\llvm\__init__.py
RefactoringTool: Refactored .\llvm\_util.py
RefactoringTool: Refactored .\llvm\core.py
RefactoringTool: Refactored .\llvm\ee.py
RefactoringTool: Refactored .\llvm\passes.py
RefactoringTool: Refactored .\test\JITTutorial1.py
RefactoringTool: Refactored .\test\JITTutorial2.py
RefactoringTool: Refactored .\test\asm.py
RefactoringTool: Refactored .\test\call-jit-ctypes.py
RefactoringTool: Refactored .\test\example-jit.py
RefactoringTool: Refactored .\test\example.py
RefactoringTool: Refactored .\test\intrinsic.py
RefactoringTool: Refactored .\test\objcache.py
RefactoringTool: Refactored .\test\operands.py
RefactoringTool: Refactored .\test\passes.py
RefactoringTool: Refactored .\test\test.py
RefactoringTool: Refactored .\test\testall.py
RefactoringTool: Refactored .\test\testattrs.py
RefactoringTool: Refactored .\test\typehandle.py
RefactoringTool: Refactored .\test\uses.py
RefactoringTool: Refactored .\tools\intrgen.py
RefactoringTool: Refactored .\tools\intrs_for_doc.py
RefactoringTool: Refactored .\www\makeweb.py
RefactoringTool: Can't parse .\www\src\examples\JITTutorial1.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2))
RefactoringTool: Can't parse .\www\src\examples\JITTutorial2.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2))
RefactoringTool: Files that need to be modified:
RefactoringTool: .\setup-win32.py
RefactoringTool: .\setup.py
RefactoringTool: .\llvm\__init__.py
RefactoringTool: .\llvm\_util.py
RefactoringTool: .\llvm\core.py
RefactoringTool: .\llvm\ee.py
RefactoringTool: .\llvm\passes.py
RefactoringTool: .\test\JITTutorial1.py
RefactoringTool: .\test\JITTutorial2.py
RefactoringTool: .\test\asm.py
RefactoringTool: .\test\call-jit-ctypes.py
RefactoringTool: .\test\example-jit.py
RefactoringTool: .\test\example.py
RefactoringTool: .\test\intrinsic.py
RefactoringTool: .\test\objcache.py
RefactoringTool: .\test\operands.py
RefactoringTool: .\test\passes.py
RefactoringTool: .\test\test.py
RefactoringTool: .\test\testall.py
RefactoringTool: .\test\testattrs.py
RefactoringTool: .\test\typehandle.py
RefactoringTool: .\test\uses.py
RefactoringTool: .\tools\intrgen.py
RefactoringTool: .\tools\intrs_for_doc.py
RefactoringTool: .\www\makeweb.py
RefactoringTool: There were 2 errors:
RefactoringTool: Can't parse .\www\src\examples\JITTutorial1.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2))
RefactoringTool: Can't parse .\www\src\examples\JITTutorial2.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2))
C:\Users\AndrewBC\src\llvm-py>

266
llvm/target.py Normal file
View file

@ -0,0 +1,266 @@
import llvm
from llvmpy import api, extra
from io import BytesIO
import contextlib
from llvm.passes import TargetData
#===----------------------------------------------------------------------===
# Enumerations
#===----------------------------------------------------------------------===
BO_BIG_ENDIAN = 0
BO_LITTLE_ENDIAN = 1
# CodeModel
CM_DEFAULT = api.llvm.CodeModel.Model.Default
CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault
CM_SMALL = api.llvm.CodeModel.Model.Small
CM_KERNEL = api.llvm.CodeModel.Model.Kernel
CM_MEDIUM = api.llvm.CodeModel.Model.Medium
CM_LARGE = api.llvm.CodeModel.Model.Large
# Reloc
RELOC_DEFAULT = api.llvm.Reloc.Model.Default
RELOC_STATIC = api.llvm.Reloc.Model.Static
RELOC_PIC = api.llvm.Reloc.Model.PIC_
RELOC_DYNAMIC_NO_PIC = api.llvm.Reloc.Model.DynamicNoPIC
def initialize_all():
api.llvm.InitializeAllTargets()
api.llvm.InitializeAllTargetInfos()
api.llvm.InitializeAllTargetMCs()
api.llvm.InitializeAllAsmPrinters()
api.llvm.InitializeAllDisassemblers()
api.llvm.InitializeAllAsmParsers()
def initialize_target(target, noraise=False):
"""Initialize target by name.
It is safe to initialize the same target multiple times.
"""
prefix = 'LLVMInitialize'
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser']
try:
for postfix in postfixes:
getattr(api, '%s%s%s' % (prefix, target, postfix))()
except AttributeError:
if noraise:
return False
else:
raise
else:
return True
def print_registered_targets():
'''
Note: print directly to stdout
'''
api.llvm.TargetRegistry.printRegisteredTargetsForVersion()
def get_host_cpu_name():
'''return the string name of the host CPU
'''
return api.llvm.sys.getHostCPUName()
def get_default_triple():
'''return the target triple of the host in str-rep
'''
return api.llvm.sys.getDefaultTargetTriple()
class TargetMachine(llvm.Wrapper):
@staticmethod
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
if not triple:
triple = get_default_triple()
if not cpu:
cpu = get_host_cpu_name()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(triple, cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
@staticmethod
def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT,
reloc=RELOC_DEFAULT):
'''create a targetmachine given an architecture name
For a list of architectures,
use: `llc -help`
For a list of available CPUs,
use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help`
For a list of available attributes (features),
use: `llvm-as < /dev/null | llc -march=xyz -mattr=help`
'''
triple = api.llvm.Triple.new()
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error)
if not target:
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
tm = target.createTargetMachine(str(triple), cpu, features,
target_options,
reloc, cm, opt)
if not tm:
raise llvm.LLVMException("Cannot create target machine")
return TargetMachine(tm)
@staticmethod
def x86():
return TargetMachine.lookup('x86')
@staticmethod
def x86_64():
return TargetMachine.lookup('x86-64')
@staticmethod
def arm():
return TargetMachine.lookup('arm')
@staticmethod
def thumb():
return TargetMachine.lookup('thumb')
def _emit_file(self, module, cgft):
pm = api.llvm.PassManager.new()
os = extra.make_raw_ostream_for_printing()
pm.add(api.llvm.DataLayout.new(str(self.target_data)))
failed = self._ptr.addPassesToEmitFile(pm, os, cgft)
pm.run(module)
CGFT = api.llvm.TargetMachine.CodeGenFileType
if cgft == CGFT.CGFT_ObjectFile:
return os.bytes()
else:
return os.str()
def emit_assembly(self, module):
'''returns byte string of the module as assembly code of the target machine
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
return self._emit_file(module._ptr, CGFT.CGFT_AssemblyFile)
def emit_object(self, module):
'''returns byte string of the module as native code of the target machine
'''
CGFT = api.llvm.TargetMachine.CodeGenFileType
return self._emit_file(module._ptr, CGFT.CGFT_ObjectFile)
@property
def target_data(self):
'''get target data of this machine
'''
return TargetData(self._ptr.getDataLayout())
@property
def target_name(self):
return self._ptr.getTarget().getName()
@property
def target_short_description(self):
return self._ptr.getTarget().getShortDescription()
@property
def triple(self):
return self._ptr.getTargetTriple()
@property
def cpu(self):
return self._ptr.getTargetCPU()
@property
def feature_string(self):
return self._ptr.getTargetFeatureString()
@property
def target(self):
return self._ptr.getTarget()
if llvm.version >= (3, 3):
def add_analysis_passes(self, pm):
self._ptr.addAnalysisPasses(pm._ptr)
if llvm.version >= (3, 4):
@property
def reg_info(self):
mri = self._ptr.getRegisterInfo()
if not mri:
raise llvm.LLVMException("no reg info for this machine")
return mri
@property
def subtarget_info(self):
sti = self._ptr.getSubtargetImpl()
if not sti:
raise llvm.LLVMException("no subtarget info for this machine")
return sti
@property
def asm_info(self):
ai = self._ptr.getMCAsmInfo()
if not ai:
raise llvm.LLVMException("no asm info for this machine")
return ai
@property
def instr_info(self):
ii = self._ptr.getInstrInfo()
if not ii:
raise llvm.LLVMException("no instr info for this machine")
return ii
@property
def instr_analysis(self):
if not getattr(self, '_mia', False):
self._mia = self.target.createMCInstrAnalysis(self.instr_info)
if not self._mia:
raise llvm.LLVMException("no instr analysis for this machine")
return self._mia
@property
def disassembler(self):
if not getattr(self, '_dasm', False):
self._dasm = self.target.createMCDisassembler(self.subtarget_info)
if not self._dasm:
raise llvm.LLVMException("no disassembler for this machine")
return self._dasm
@property
def inst_printer(self):
if not getattr(self, '_mip', False):
self._mip = self.target.createMCInstPrinter(
self.asm_info.getAssemblerDialect(),
self.asm_info,
self.instr_info,
self.reg_info,
self.subtarget_info
)
if not self._mip:
raise llvm.LLVMException("no instr printer for this machine")
return self._mip
def is_little_endian(self):
return self.asm_info.isLittleEndian()

View file

@ -2,11 +2,11 @@ from llvm.core import *
class TBAABuilder(object):
'''Simplify creation of TBAA metadata.
Each TBAABuidler object operates on a module.
Each TBAABuidler object operates on a module.
User can create multiple TBAABuilder on a module
'''
def __init__(self, module, rootid):
'''
module --- the module to use.
@ -23,7 +23,7 @@ class TBAABuilder(object):
def get_node(self, name, parent=None, const=False):
'''Returns a MetaData object representing a TBAA node.
Use loadstore_instruction.set_metadata('tbaa', node) to
Use loadstore_instruction.set_metadata('tbaa', node) to
bind a type to a memory.
'''
parent = parent or self.root

File diff suppressed because it is too large Load diff

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

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

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

@ -0,0 +1,78 @@
from __future__ import print_function, division
import sys
import platform
import unittest
import contextlib
import types
from llvm.tests import tests, isolated_tests # re-expose symbol
IS_PY3K = sys.version_info[0] >= 3
BITS = tuple.__itemsize__ * 8
OS = sys.platform
MACHINE = platform.machine()
INTEL_CPUS = 'i386', 'x86_64'
if sys.version_info[:2] <= (2, 6):
# create custom TestCase
class _TestCase(unittest.TestCase):
def assertIn(self, item, container):
self.assertTrue(item in container)
def assertNotIn(self, item, container):
self.assertFalse(item in container)
def assertLess(self, a, b):
self.assertTrue(a < b)
def assertIs(self, a, b):
self.assertTrue(a is b)
@contextlib.contextmanager
def assertRaises(self, exc):
try:
yield
except exc:
pass
else:
raise self.failureException("Did not raise %s" % exc)
else:
_TestCase = unittest.TestCase
class TestCase(_TestCase):
def assertClose(self, got, expect):
rel = abs(got - expect) / expect
self.assertTrue(rel < 1e-6, 'relative error = %f' % rel)
#-------------------------------------------------------------------------------
# Tests decorators
def _skipped(name, msg):
def _test(self):
if hasattr(unittest, 'SkipTest'):
raise unittest.SkipTest(msg)
else:
print('skipped %s' % name, msg)
return _test
def skip_if(cond, msg=''):
def skipper(test):
if not isinstance(test, types.FunctionType):
repl = None
else:
repl = _skipped(test, msg)
return repl if cond else test
return skipper
skip_if_not_64bits = skip_if(BITS != 64, msg='skipped not 64-bit')
skip_if_not_32bits = skip_if(BITS != 32, msg='skipped not 32-bits')
skip_if_win32 = skip_if(OS.startswith('win32'), msg='skipped win32')
skip_if_not_win32 = skip_if(not OS.startswith('win32'),
msg='skipped not win32')
skip_if_not_intel_cpu = skip_if(MACHINE not in INTEL_CPUS,
msg='skipped not Intel CPU')

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

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

View file

@ -0,0 +1,24 @@
import unittest
from llvm.core import Module, Type
import llvm.core as lc
from .support import TestCase, tests
class TestArgAttr(TestCase):
def test_arg_attr(self):
m = Module.new('oifjda')
vptr = Type.pointer(Type.float())
fnty = Type.function(Type.void(), [vptr] * 5)
func = m.add_function(fnty, 'foo')
attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST,
lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE]
for i, attr in enumerate(attrs):
arg = func.args[i]
self.assertEqual(i, arg.arg_no)
arg.add_attribute(attr)
self.assertTrue(attr in func.args[i])
tests.append(TestArgAttr)
if __name__ == '__main__':
unittest.main()

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

@ -0,0 +1,73 @@
import unittest
import llvm
from llvm.core import (Module, Type, Builder)
from llvm.ee import EngineBuilder
from .support import TestCase, tests, skip_if, skip_if_not_64bits
@skip_if(llvm.version < (3, 3))
class TestArith(TestCase):
'''
Test basic arithmetic support with LLVM MCJIT
'''
def func_template(self, ty, op):
m = Module.new('dofjaa')
fnty = Type.function(ty, [ty, ty])
fn = m.add_function(fnty, 'foo')
bldr = Builder.new(fn.append_basic_block(''))
bldr.ret(getattr(bldr, op)(*fn.args))
engine = EngineBuilder.new(m).mcjit(True).create()
ptr = engine.get_pointer_to_function(fn)
from ctypes import c_uint32, c_uint64, c_float, c_double, CFUNCTYPE
maptypes = {
Type.int(32): c_uint32,
Type.int(64): c_uint64,
Type.float(): c_float,
Type.double(): c_double,
}
cty = maptypes[ty]
prototype = CFUNCTYPE(*[cty] * 3)
callee = prototype(ptr)
callee(12, 23)
def template(self, iop, fop):
inttys = [Type.int(32), Type.int(64)]
flttys = [Type.float(), Type.double()]
if iop:
for ty in inttys:
self.func_template(ty, iop)
if fop:
for ty in flttys:
self.func_template(ty, fop)
def test_add(self):
self.template('add', 'fadd')
def test_sub(self):
self.template('sub', 'fsub')
def test_mul(self):
self.template('mul', 'fmul')
@skip_if_not_64bits
def test_div(self):
'''
known failure due to unresolved external symbol __udivdi3
'''
self.template('udiv', None) # 'fdiv')
@skip_if_not_64bits
def test_rem(self):
'''
known failure due to unresolved external symbol __umoddi3
'''
self.template('urem', None) # 'frem')
tests.append(TestArith)
if __name__ == '__main__':
unittest.main()

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

@ -0,0 +1,58 @@
import os
import unittest
import tempfile
import shutil
from llvm.core import Module, Type
from .support import TestCase, tests
class TestAsm(TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self.tmpdir)
def test_asm(self):
# create a module
m = Module.new('module1')
m.add_global_variable(Type.int(), 'i')
# write it's assembly representation to a file
asm = str(m)
testasm_ll = os.path.join(self.tmpdir, 'testasm.ll')
with open(testasm_ll, "w") as fout:
fout.write(asm)
# read it back into a module
with open(testasm_ll) as fin:
m2 = Module.from_assembly(fin)
# The default `m.id` is '<string>'.
m2.id = m.id # Copy the name from `m`
self.assertEqual(str(m2).strip(), asm.strip())
def test_bitcode(self):
# create a module
m = Module.new('module1')
m.add_global_variable(Type.int(), 'i')
# write it's assembly representation to a file
asm = str(m)
testasm_bc = os.path.join(self.tmpdir, 'testasm.bc')
with open(testasm_bc, "wb") as fout:
m.to_bitcode(fout)
# read it back into a module
with open(testasm_bc, "rb") as fin:
m2 = Module.from_bitcode(fin)
# The default `m.id` is '<string>'.
m2.id = m.id # Copy the name from `m`
self.assertEqual(str(m2).strip(), asm.strip())
tests.append(TestAsm)
if __name__ == '__main__':
unittest.main()

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

@ -0,0 +1,85 @@
import unittest
from llvm.core import (Module, Type, Builder, Constant)
from .support import TestCase, tests
class TestAtomic(TestCase):
orderings = ['unordered', 'monotonic', 'acquire',
'release', 'acq_rel', 'seq_cst']
atomic_op = ['xchg', 'add', 'sub', 'and', 'nand', 'or', 'xor',
'max', 'min', 'umax', 'umin']
def test_atomic_cmpxchg(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
old = bldr.load(ptr)
new = Constant.int(Type.int(), 1234)
for ordering in self.orderings:
inst = bldr.atomic_cmpxchg(ptr, old, new, ordering)
self.assertEqual(ordering, str(inst).strip().split(' ')[-1])
inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False)
self.assertEqual('singlethread', str(inst).strip().split(' ')[-2])
def test_atomic_rmw(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
val = Constant.int(Type.int(), 1234)
for ordering in self.orderings:
inst = bldr.atomic_rmw('xchg', ptr, val, ordering)
self.assertEqual(ordering, str(inst).split(' ')[-1])
for op in self.atomic_op:
inst = bldr.atomic_rmw(op, ptr, val, ordering)
self.assertEqual(op, str(inst).strip().split(' ')[3])
inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False)
self.assertEqual('singlethread', str(inst).strip().split(' ')[-2])
for op in self.atomic_op:
atomic_op = getattr(bldr, 'atomic_%s' % op)
inst = atomic_op(ptr, val, ordering)
self.assertEqual(op, str(inst).strip().split(' ')[3])
def test_atomic_ldst(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
for ordering in self.orderings:
loaded = bldr.atomic_load(ptr, ordering)
self.assert_('load atomic' in str(loaded))
self.assertEqual(ordering,
str(loaded).strip().split(' ')[-3].rstrip(','))
self.assert_('align 1' in str(loaded))
stored = bldr.atomic_store(loaded, ptr, ordering)
self.assert_('store atomic' in str(stored))
self.assertEqual(ordering,
str(stored).strip().split(' ')[-3].rstrip(','))
self.assert_('align 1' in str(stored))
fenced = bldr.fence(ordering)
self.assertEqual(['fence', ordering],
str(fenced).strip().split(' '))
tests.append(TestAtomic)
if __name__ == '__main__':
unittest.main()

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