Compare commits
355 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34900d2748 | ||
|
|
749b518b90 | ||
|
|
c07fce0477 | ||
|
|
7f8476dd33 | ||
|
|
57afefb069 | ||
|
|
0629ccb226 | ||
|
|
6e4620edc6 | ||
|
|
2410267c8e | ||
|
|
bc12aae8c1 | ||
|
|
6578412437 | ||
|
|
ce696c9b4e | ||
|
|
3befa1be59 | ||
|
|
a9174f09c5 | ||
|
|
b86cc097d9 | ||
|
|
0e9f434ad8 | ||
|
|
e868b825bb | ||
|
|
dd2a569d76 | ||
|
|
059192f1ae | ||
|
|
3db6d8352a | ||
|
|
00db78d89e | ||
|
|
d9eb3ec175 | ||
|
|
4ed8f80774 | ||
|
|
43095609c3 | ||
|
|
b9cccbf9ae | ||
|
|
8689d62f02 | ||
|
|
17d3cef4bd | ||
|
|
ecac668bef | ||
|
|
078f1fe5c1 | ||
|
|
b9752e1e98 | ||
|
|
f8c1c78df1 | ||
|
|
b8e0338da8 | ||
|
|
091a393d1d | ||
|
|
d7590fb029 | ||
|
|
c199881b67 | ||
|
|
fb3b6a3674 | ||
|
|
4e814b7d53 | ||
|
|
8a6dd7af7f | ||
|
|
d08095299e | ||
|
|
bf5859be7e | ||
|
|
18d3b4809f | ||
|
|
a82e876f93 | ||
|
|
1f7b9e3922 | ||
|
|
fac1bc782d | ||
|
|
ea452bd33c | ||
|
|
ddf2007553 | ||
|
|
e7a7896710 | ||
|
|
69a78d0a54 | ||
|
|
cc4e4631bd | ||
|
|
8034854ad4 | ||
|
|
733fd7d18e | ||
|
|
6e55bfc406 | ||
|
|
72192c7e6a | ||
|
|
b303fd532a | ||
|
|
aa264cee2d | ||
|
|
3743146121 | ||
|
|
8de5c3faff | ||
|
|
083586464b | ||
|
|
0f3d5a8127 | ||
|
|
3e77a55de3 | ||
|
|
65c4558cac | ||
|
|
43f7330fda | ||
|
|
1d735e49d2 | ||
|
|
fea82991c3 | ||
|
|
b3bf7f86cd | ||
|
|
3c06f0d590 | ||
|
|
cadc53f174 | ||
|
|
0ed471d336 | ||
|
|
7234b0d200 | ||
|
|
fa3aec8353 | ||
|
|
bd9d71c713 | ||
|
|
8dbfc377ad | ||
|
|
82d9c787f3 | ||
|
|
87d444c9e9 | ||
|
|
fa26aa1651 | ||
|
|
cbf4a61a17 | ||
|
|
0e265a2cc5 | ||
|
|
e65f6174a7 | ||
|
|
83299a20a6 | ||
|
|
97c0e15e72 | ||
|
|
4eab936224 | ||
|
|
78be6a7f5f | ||
|
|
bc02b3d90a | ||
|
|
aa0ee9b6a6 | ||
|
|
0610a27535 | ||
|
|
f4bbb18e47 | ||
|
|
25e6651055 | ||
|
|
38a00c6e55 | ||
|
|
818c9289fc | ||
|
|
ba03b226c8 | ||
|
|
8f2c27ba41 | ||
|
|
ef59848d18 | ||
|
|
4905743e0a | ||
|
|
09d9dbba1e | ||
|
|
aae25f5e55 | ||
|
|
af2c1d6d01 | ||
|
|
4e993570cd | ||
|
|
6bbf53241d | ||
|
|
0801df41dc | ||
|
|
24f1b33737 | ||
|
|
536bc37c94 | ||
|
|
351bd39814 | ||
|
|
33ca795e0c | ||
|
|
d57c4d88c6 | ||
|
|
328f88bbd5 | ||
|
|
ea5b430297 | ||
|
|
5f01343bba | ||
|
|
bf8693bb80 | ||
|
|
e69048ad3d | ||
|
|
8480d55faf | ||
|
|
7d1c4c18a0 | ||
|
|
07c64779d8 | ||
|
|
d10b182479 | ||
|
|
1be8b07ced | ||
|
|
3a289ccace | ||
|
|
bf0253c9f9 | ||
|
|
d060c10096 | ||
|
|
1ed3c77310 | ||
|
|
cfe5e9ea92 | ||
|
|
1e9d37a64e | ||
|
|
eb4fc653f2 | ||
|
|
b4d943a671 | ||
|
|
c20c4d776f | ||
|
|
84a95945ea | ||
|
|
0421ad8456 | ||
|
|
2a25b1c2b3 | ||
|
|
c4db61c7f5 | ||
|
|
c0e9dedc90 | ||
|
|
319984f0e0 | ||
|
|
56a511854a | ||
|
|
625858aa6f | ||
|
|
6d3253e4ea | ||
|
|
4c1b9016fb | ||
|
|
2338eae5f6 | ||
|
|
2415042a2a | ||
|
|
ad287faeb1 | ||
|
|
69c75355f4 | ||
|
|
84f1b433de | ||
|
|
2e8944916c | ||
|
|
17ec89e457 | ||
|
|
6b333e84aa | ||
|
|
009239713e | ||
|
|
1812cff2d0 | ||
|
|
a0eb03b239 | ||
|
|
5b2b878f24 | ||
|
|
edab81ed7e | ||
|
|
96dc907613 | ||
|
|
592f9c6988 | ||
|
|
331f71f26f | ||
|
|
db7323771f | ||
|
|
f4b320ff09 | ||
|
|
08bed7dd74 | ||
|
|
c118427118 | ||
|
|
3e0dc25070 | ||
|
|
489d8056b9 | ||
|
|
a357987597 | ||
|
|
b754e803ec | ||
|
|
a5f6f2596f | ||
|
|
238ea0e453 | ||
|
|
e74b26f84c | ||
|
|
020032b578 | ||
|
|
777eea719c | ||
|
|
66346ee507 | ||
|
|
125e65e261 | ||
|
|
2479c2dc22 | ||
|
|
003768cdea | ||
|
|
ca8fa2593a | ||
|
|
fab52057ba | ||
|
|
0b1abe7b26 | ||
|
|
22b5d4695c | ||
|
|
b13aee0668 | ||
|
|
b14161c184 | ||
|
|
6c2ed9a3ed | ||
|
|
b6c1e7a961 | ||
|
|
8800ebac66 | ||
|
|
1b2a9dec9a | ||
|
|
a8c78a6e2e | ||
|
|
d06a5f3eb4 | ||
|
|
01c8ec1769 | ||
|
|
b913b2840e | ||
|
|
edc391f292 | ||
|
|
ec0dda4621 | ||
|
|
bd129baa0a | ||
|
|
6f524130d0 | ||
|
|
e63bdd6da2 | ||
|
|
67f4acf91f | ||
|
|
3c4769c58d | ||
|
|
b8da3c7a73 | ||
|
|
931352d4bf | ||
|
|
e4996f02d7 | ||
|
|
372d601875 | ||
|
|
a5078d6cd7 | ||
|
|
f5fd7241ea | ||
|
|
f8deae06dd | ||
|
|
ba759b59d0 | ||
|
|
bb43f4097a | ||
|
|
fde153aab6 | ||
|
|
51ff879a07 | ||
|
|
e89c19ee60 | ||
|
|
f172e82f10 | ||
|
|
91d2740fbf | ||
|
|
75b7d11fb1 | ||
|
|
61d8105e2c | ||
|
|
d9c2ec696d | ||
|
|
1a34e412a5 | ||
|
|
4bf0fa65ef | ||
|
|
268dc2466a | ||
|
|
0cccb3dec9 | ||
|
|
9df508f7c0 | ||
|
|
cd8d622fc9 | ||
|
|
9f9d5a6081 | ||
|
|
8073b67c96 | ||
|
|
f3e7b39bc9 | ||
|
|
d485c22b08 | ||
|
|
ae6dab8e50 | ||
|
|
5d83d626f6 | ||
|
|
17096867f7 | ||
|
|
93cd20e933 | ||
|
|
740d2595ee | ||
|
|
c3a08a446f | ||
|
|
dd9ba65328 | ||
|
|
894539681b | ||
|
|
cada51e297 | ||
|
|
7b1a825380 | ||
|
|
c1b46e4384 | ||
|
|
d270f47328 | ||
|
|
4e87b5170a | ||
|
|
d36cd1dbc7 | ||
|
|
d74ff4dc2b | ||
|
|
8086487ab7 | ||
|
|
769376b055 | ||
|
|
650a49dcab | ||
|
|
fccf439117 | ||
|
|
6c07747a3b | ||
|
|
45e70333fd | ||
|
|
a275068193 | ||
|
|
74982d6fef | ||
|
|
435b92b4a4 | ||
|
|
d270e885cc | ||
|
|
42f7219c3f | ||
|
|
175f558ce0 | ||
|
|
58d410b347 | ||
|
|
081b41db60 | ||
|
|
bf484aa216 | ||
|
|
20d0bf9f2a | ||
|
|
1647580a41 | ||
|
|
acd6ab685b | ||
|
|
0cc2e516ac | ||
|
|
92c9813b3e | ||
|
|
013c7d2009 | ||
|
|
ffa713e332 | ||
|
|
a7c650a458 | ||
|
|
079e31c474 | ||
|
|
7813bec6e9 | ||
|
|
26c4380c2b | ||
|
|
bf121485ad | ||
|
|
cb00dcc52c | ||
|
|
d2dc34cdd3 | ||
|
|
a09394cacd | ||
|
|
0036d55eea | ||
|
|
b4f4483809 | ||
|
|
a97b26415e | ||
|
|
2d8c6f0a41 | ||
|
|
3189be4d58 | ||
|
|
0681d2f37e | ||
|
|
230583f42d | ||
|
|
1fb6b05715 | ||
|
|
8700bbc4f1 | ||
|
|
60336d1c5f | ||
|
|
c66dad7ece | ||
|
|
355332d6d8 | ||
|
|
6eae24bcf3 | ||
|
|
7c39bd1f5b | ||
|
|
fe383ca326 | ||
|
|
b9ac22d136 | ||
|
|
113f30ffab | ||
|
|
541c119fc3 | ||
|
|
11cc78d780 | ||
|
|
aa5b969961 | ||
|
|
cd1fa4c4d8 | ||
|
|
39de8c4003 | ||
|
|
9c81fa1f63 | ||
|
|
c98a1274d9 | ||
|
|
450c29e052 | ||
|
|
da85049eb9 | ||
|
|
168510222f | ||
|
|
961c5e99e1 | ||
|
|
c085bef46e | ||
|
|
1f49bb6d7c | ||
|
|
7788346152 | ||
|
|
372d6804e4 | ||
|
|
9485d03e18 | ||
|
|
ca0a2b9fdd | ||
|
|
78f9c9a610 | ||
|
|
25b498c8fa | ||
|
|
437b1e9490 | ||
|
|
59d0dfddc7 | ||
|
|
895d114730 | ||
|
|
7aa9487f2f | ||
|
|
af7962a2ca | ||
|
|
d939728938 | ||
|
|
fa4927e1fb | ||
|
|
821e937837 | ||
|
|
d1931cc499 | ||
|
|
0168315076 | ||
|
|
4b5cb100f7 | ||
|
|
c76096bbcb | ||
|
|
3c81157ede | ||
|
|
eba88b32ba | ||
|
|
a3da74c416 | ||
|
|
c247cf9527 | ||
|
|
e9e1f5703d | ||
|
|
e9be14ca0e | ||
|
|
6a861d82e6 | ||
|
|
ef4c0d3be3 | ||
|
|
6afab6268c | ||
|
|
6b88ffbaed | ||
|
|
ce103975b8 | ||
|
|
f95b691b61 | ||
|
|
3e89a97fdb | ||
|
|
bd550e3c0e | ||
|
|
f88036274a | ||
|
|
089c825b0c | ||
|
|
e39e1c7205 | ||
|
|
36df29ba71 | ||
|
|
d0935fe533 | ||
|
|
5c1e8985a1 | ||
|
|
47771d8dbc | ||
|
|
a12c4da93d | ||
|
|
b793e72189 | ||
|
|
c822f5f9f7 | ||
|
|
0a6a11f35a | ||
|
|
3f789913f5 | ||
|
|
4fb7549243 | ||
|
|
7bd02ef91a | ||
|
|
fe37d8bae0 | ||
|
|
5dd0948c65 | ||
|
|
1d4c431b23 | ||
|
|
5d54bbb1cd | ||
|
|
b895f1fc99 | ||
|
|
ffc067f852 | ||
|
|
7e7b362e47 | ||
|
|
3d66981cc1 | ||
|
|
8b918f37d6 | ||
|
|
3772b8ba6e | ||
|
|
4ab6791e78 | ||
|
|
d355facf25 | ||
|
|
c0ff3615ee | ||
|
|
60795adb5e | ||
|
|
3b1ae9889d | ||
|
|
2bef762ba2 | ||
|
|
1ccda1ca5c | ||
|
|
2689694de9 | ||
|
|
e6ff2b46e2 | ||
|
|
5209cdb032 | ||
|
|
203858f417 |
250 changed files with 18055 additions and 13326 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
llvm/_version.py export-subst
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -2,4 +2,7 @@
|
||||||
build
|
build
|
||||||
_build
|
_build
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.so
|
||||||
/llvm/_intrinsic_ids.py
|
/llvm/_intrinsic_ids.py
|
||||||
|
llvm_
|
||||||
|
newbinding/api/*
|
||||||
24
.travis.yml
Normal file
24
.travis.yml
Normal 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
102
CHANGELOG
|
|
@ -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.
|
* Add LLVM 3.2 support.
|
||||||
* New TargetData class.
|
* New TargetData class.
|
||||||
* Fixed windows issue (Issue #42).
|
* Fixed windows issue (Issue #42).
|
||||||
|
|
@ -8,16 +73,16 @@
|
||||||
* Added llvm.passes.build_pass_managers as a simpler way to build PassManagers.
|
* 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.
|
* Add llvm.core.Argument.alignment property.
|
||||||
* Migrate to LLVM 2.8.
|
* Migrate to LLVM 2.8.
|
||||||
* Fix ffi link issue on darwin (Albert Mietus) (Issue #29).
|
* Fix ffi link issue on darwin (Albert Mietus) (Issue #29).
|
||||||
* LLVM tutorial ported (Max Shawabkeh) (Issue #33).
|
* 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).
|
* Add and remove function attributes (Krzysztof Goj) (Issue #21).
|
||||||
* Wrap fadd,fsub,fmul (Aaron S Lav) (Issue #31).
|
* Wrap fadd,fsub,fmul (Aaron S Lav) (Issue #31).
|
||||||
* Migrate to LLVM 2.7.
|
* Migrate to LLVM 2.7.
|
||||||
|
|
@ -36,16 +101,16 @@
|
||||||
* Migrate to LLVM 2.5.
|
* Migrate to LLVM 2.5.
|
||||||
|
|
||||||
|
|
||||||
0.5, 22-Nov-2008:
|
2008-11-22 0.5:
|
||||||
|
-----------------
|
||||||
* Added vicmp, vfcmp instructions and constant expressions.
|
* Added vicmp, vfcmp instructions and constant expressions.
|
||||||
* Builds on FreeBSD.
|
* Builds on FreeBSD.
|
||||||
* Updated documentation.
|
* Updated documentation.
|
||||||
* Migrate to LLVM 2.4.
|
* Migrate to LLVM 2.4.
|
||||||
|
|
||||||
|
|
||||||
0.4, 21-Nov-2008:
|
2008-11-21 0.4:
|
||||||
|
-----------------
|
||||||
* Code cleanup, added license headers.
|
* Code cleanup, added license headers.
|
||||||
* Added llvm.core.load_library_permanently() (Issue #12).
|
* Added llvm.core.load_library_permanently() (Issue #12).
|
||||||
* Fix comparison using != (Issue #11).
|
* Fix comparison using != (Issue #11).
|
||||||
|
|
@ -54,8 +119,8 @@
|
||||||
* Added viewCFG methods to Function (Paulo Silva).
|
* Added viewCFG methods to Function (Paulo Silva).
|
||||||
|
|
||||||
|
|
||||||
0.3, 8-Sep-2008:
|
2008-09-08 0.3:
|
||||||
|
-----------------
|
||||||
* Passes added.
|
* Passes added.
|
||||||
* Assembly support: create modules from .ll files.
|
* Assembly support: create modules from .ll files.
|
||||||
* Various bug fixes.
|
* Various bug fixes.
|
||||||
|
|
@ -67,13 +132,13 @@
|
||||||
* Updated documentation.
|
* Updated documentation.
|
||||||
|
|
||||||
|
|
||||||
0.2.1, 18-Jun-2008:
|
2008-06-28 0.2.1:
|
||||||
|
-------------------
|
||||||
* Build cleanly with LLVM 2.3 and 2.3svn.
|
* 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.
|
* Independent package, need not be unpacked into llvm/bindings.
|
||||||
* Fixed ownership issues with Module/ModuleProvider.
|
* Fixed ownership issues with Module/ModuleProvider.
|
||||||
* Modules, values and types can be stringified, to get their LLVM
|
* Modules, values and types can be stringified, to get their LLVM
|
||||||
|
|
@ -88,7 +153,6 @@
|
||||||
* Lots of cleanup.
|
* Lots of cleanup.
|
||||||
|
|
||||||
|
|
||||||
0.1, 10-May-2008:
|
2008-05-10 0.1:
|
||||||
|
-----------------
|
||||||
* Initial release.
|
* Initial release
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 llvm *
|
||||||
|
recursive-include llvmpy *
|
||||||
recursive-include www *
|
recursive-include www *
|
||||||
recursive-include test *
|
recursive-include test *
|
||||||
recursive-include tools *
|
recursive-include tools *
|
||||||
|
|
|
||||||
46
README.rst
46
README.rst
|
|
@ -10,32 +10,54 @@ http://www.llvmpy.org
|
||||||
Versions
|
Versions
|
||||||
--------
|
--------
|
||||||
|
|
||||||
This package has been tested with LLVM 3.1 and 3.2, Python 2.7 and Python 3.2.
|
This package has been tested with LLVM 3.2, Python 2.6, 2.7 and 3.3.
|
||||||
Other Python versions should work.
|
Other Python versions may work.
|
||||||
|
|
||||||
Quickstart
|
Quickstart
|
||||||
----------
|
----------
|
||||||
|
|
||||||
1. Get 3.1 or 3.2 version of LLVM, build it. Make sure ``--enable-pic`` is
|
1. Get and extract LLVM 3.2 source tarball from
|
||||||
passed to LLVM's ``configure``.
|
`llvm.org <http://llvm.org/releases/download.html#3.2>`_. Then, ``cd`` into
|
||||||
|
the extracted directory.
|
||||||
For LLVM 3.2, make sure that environment variable ``REQUIRES_RTTI=1`` is
|
|
||||||
defined when running ``make``. Otherwise, you may see "undefined symbol:
|
|
||||||
_ZTIN4llvm24PassRegistrationListenerE". Please refer to
|
|
||||||
http://llvm.org/docs/Packaging.html#c-features for details.
|
|
||||||
|
|
||||||
2. 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
|
$ git clone git@github.com:llvmpy/llvmpy.git
|
||||||
$ cd llvmpy
|
$ cd llvmpy
|
||||||
$ python setup.py install
|
$ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install
|
||||||
|
|
||||||
Run the tests::
|
Run the tests::
|
||||||
|
|
||||||
$ python -c "import llvm; llvm.test()"
|
$ 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'.
|
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
|
LICENSE
|
||||||
-------
|
-------
|
||||||
|
|
|
||||||
6
buildscripts/condarecipe/bld.bat
Normal file
6
buildscripts/condarecipe/bld.bat
Normal 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
|
||||||
13
buildscripts/condarecipe/build.sh
Normal file
13
buildscripts/condarecipe/build.sh
Normal 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
|
||||||
28
buildscripts/condarecipe/meta.yaml
Normal file
28
buildscripts/condarecipe/meta.yaml
Normal 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
|
||||||
|
|
||||||
|
|
||||||
22
buildscripts/condarecipe/run_test.py
Normal file
22
buildscripts/condarecipe/run_test.py
Normal 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'
|
||||||
|
|
@ -30,7 +30,7 @@ from subprocess import Popen, PIPE, CalledProcessError, check_call
|
||||||
pages_dir = 'gh-pages'
|
pages_dir = 'gh-pages'
|
||||||
html_dir = '_build/html'
|
html_dir = '_build/html'
|
||||||
pdf_dir = '_build/latex'
|
pdf_dir = '_build/latex'
|
||||||
pages_repo = 'git@github.com:llvmpy/llvmpy-doc.git'
|
pages_repo = 'https://github.com/llvmpy/llvmpy-doc.git'
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Functions
|
# Functions
|
||||||
|
|
@ -86,7 +86,7 @@ if __name__ == '__main__':
|
||||||
tag = sh2('git describe --exact-match')
|
tag = sh2('git describe --exact-match')
|
||||||
except CalledProcessError:
|
except CalledProcessError:
|
||||||
tag = "dev" # Fallback
|
tag = "dev" # Fallback
|
||||||
|
|
||||||
startdir = os.getcwdu()
|
startdir = os.getcwdu()
|
||||||
if not os.path.exists(pages_dir):
|
if not os.path.exists(pages_dir):
|
||||||
# init the repo
|
# init the repo
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,23 @@
|
||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
import sys, os
|
import sys, os, glob
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# 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
|
# 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.
|
# 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 -----------------------------------------------------
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -41,16 +52,22 @@ master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'llvmpy'
|
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
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
try:
|
||||||
version = '0.9'
|
import llvm
|
||||||
# The full version, including alpha/beta/rc tags.
|
version_strs = llvm.__version__.split('.')
|
||||||
release = '0.9.0'
|
# 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
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
A More Complicated Function
|
A More Complicated Function
|
||||||
====================
|
===========================
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ supported, for a variety of reasons.
|
||||||
Versions
|
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.
|
previous versions.
|
||||||
|
|
||||||
llvmpy has been built and tested with Python 2.7 and 3.2. It should work with
|
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
|
``llvm-g++`` or any other); llvmpy can be built with any compiler. It
|
||||||
has been tried only with gcc/g++ though.
|
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
|
llvm-config
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
@ -98,13 +82,34 @@ is different from that of 'root', so even if ``llvm-config`` is in your
|
||||||
Steps
|
Steps
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to
|
1. Get and extract LLVM 3.2 source tarball from
|
||||||
LLVM's 'configure'.
|
`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
|
**Note**: With LLVM 3.2, the default build configuration has C++ RTTI
|
||||||
$ cd llvmpy $ python setup.py install
|
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'.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
|
||||||
Shawabkeh <http://max99x.com>`_
|
Shawabkeh <http://max99x.com>`_
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
=========
|
============
|
||||||
|
|
||||||
Welcome to the "Implementing a language with LLVM" tutorial. This
|
Welcome to the "Implementing a language with LLVM" tutorial. This
|
||||||
tutorial runs through the implementation of a simple language, showing
|
tutorial runs through the implementation of a simple language, showing
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,8 @@ Kaleidoscope looks something like this:
|
||||||
br i1 %ifcond, label %then, label %else
|
br i1 %ifcond, label %then, label %else
|
||||||
|
|
||||||
then: ; preds = %entry
|
then: ; preds = %entry
|
||||||
%calltmp1 = call double @bar()
|
%calltmp = call double @foo()
|
||||||
|
br label %ifcont
|
||||||
|
|
||||||
else: ; preds = %entry
|
else: ; preds = %entry
|
||||||
%calltmp1 = call double @bar()
|
%calltmp1 = call double @bar()
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,8 @@ to talk about how LLVM represents stack variables.
|
||||||
In LLVM, all memory accesses are explicit with load/store instructions,
|
In LLVM, all memory accesses are explicit with load/store instructions,
|
||||||
and it is carefully designed not to have (or need) an "address-of"
|
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
|
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
|
"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
|
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
|
*name* actually refers to the address for that space. Stack variables
|
||||||
work the same way, except that instead of being declared with global
|
work the same way, except that instead of being declared with global
|
||||||
variable definitions, they are declared with the `LLVM alloca
|
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() {
|
define i32 @example() {
|
||||||
entry:
|
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.
|
%tmp = load i32* %X ; load the stack value %X from the stack
|
||||||
%tmp2 = add i32 %tmp, 1 ; increment it store i32 %tmp2,
|
%tmp2 = add i32 %tmp, 1 ; increment it
|
||||||
i32* %X ; store it back
|
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:
|
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
|
# Define ':' for sequencing: as a low-precedence operator that ignores operands
|
||||||
# and just returns the RHS.
|
# and just returns the RHS.
|
||||||
|
|
@ -352,7 +352,7 @@ function that ensures that the allocas are created in the entry block of
|
||||||
the function:
|
the function:
|
||||||
|
|
||||||
|
|
||||||
.. code-block::
|
.. code-block:: python
|
||||||
|
|
||||||
# Creates an alloca instruction in the entry block of the function. This is used
|
# Creates an alloca instruction in the entry block of the function. This is used
|
||||||
# for mutable variables.
|
# 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
|
mem2reg optimization runs. For example, this is the before/after code
|
||||||
for our recursive fib function. Before the optimization:
|
for our recursive fib function. Before the optimization:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block:: llvm
|
||||||
|
|
||||||
define double @fib(double %x) {
|
define double @fib(double %x) {
|
||||||
entry:
|
entry:
|
||||||
|
|
@ -515,7 +515,7 @@ still just make the PHI.
|
||||||
|
|
||||||
Here is the code after the mem2reg pass runs:
|
Here is the code after the mem2reg pass runs:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block:: llvm
|
||||||
|
|
||||||
define double @fib(double %x) {
|
define double @fib(double %x) {
|
||||||
entry:
|
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:
|
and arguments. For example, we can now run code like this:
|
||||||
|
|
||||||
|
|
||||||
.. code-block::
|
.. code-block:: none
|
||||||
|
|
||||||
# Function to print a double.
|
# Function to print a double.
|
||||||
extern printd(x)
|
extern printd(x)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
*************************************************
|
***************************************************
|
||||||
Chapter 8: Conclusion and other useful LLVM tidbits
|
Chapter 8: Conclusion and other useful LLVM tidbits
|
||||||
*************************************************
|
***************************************************
|
||||||
|
|
||||||
Written by Chris Lattner
|
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.
|
but are very useful if you want to take advantage of LLVM's capabilities.
|
||||||
|
|
||||||
Properties of the LLVM IR
|
Properties of the LLVM IR
|
||||||
========================
|
=========================
|
||||||
|
|
||||||
We have a couple common questions about code in the LLVM IR form - let's
|
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?
|
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
|
Safety Guarantees
|
||||||
----------------
|
-----------------
|
||||||
|
|
||||||
Many of the languages above are also "safe" languages: it is
|
Many of the languages above are also "safe" languages: it is
|
||||||
impossible for a program written in Java to corrupt its address space and
|
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
|
Tips and Tricks
|
||||||
==============
|
===============
|
||||||
|
|
||||||
There is a variety of useful tips and tricks that you come to
|
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.
|
know after working on/with LLVM that aren't obvious at first glance.
|
||||||
|
|
|
||||||
|
|
@ -56,3 +56,10 @@ Add an attribute ``attr`` to the argument, from the set listed above.
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Remove the attribute ``attr`` of the argument.
|
Remove the attribute ``attr`` of the argument.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Argument
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -28,3 +28,10 @@ A ``Type`` object representing the type of the element of the array.
|
||||||
[read-only]
|
[read-only]
|
||||||
|
|
||||||
The number of elements in the array.
|
The number of elements in the array.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.ArrayType
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -42,3 +42,10 @@ The parent function of this basicblock.
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A list of instructions in this basicblock.
|
A list of instructions in this basicblock.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.BasicBlock
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -409,3 +409,10 @@ positioned.
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
Deprecated. Same as ``basic_block``
|
Deprecated. Same as ``basic_block``
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Builder
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
| title: Constant (llvm.core) |
|
| title: Constant (llvm.core) |
|
||||||
+-------------------------------+
|
+-------------------------------+
|
||||||
|
|
||||||
|
llvm.core.Constant
|
||||||
|
==================
|
||||||
|
|
||||||
``Constant``-s represents constants that appear within the code. The
|
``Constant``-s represents constants that appear within the code. The
|
||||||
values of such objects are known at creation time. Constants can be
|
values of such objects are known at creation time. Constants can be
|
||||||
created from Python constants. A constant expression is also a constant
|
created from Python constants. A constant expression is also a constant
|
||||||
|
|
@ -23,331 +26,338 @@ some examples:
|
||||||
|
|
||||||
tr = Type.float()
|
tr = Type.float()
|
||||||
|
|
||||||
r1 = Constant.real(tr, "3.141592") # create from a string r2 =
|
r1 = Constant.real(tr, "3.141592") # create from a string
|
||||||
Constant.real(tr, 1.61803399) # create from a Python float {%
|
r2 = Constant.real(tr, 1.61803399) # create from a Python float
|
||||||
endhighlight %}
|
|
||||||
|
|
||||||
# llvm.core.Constant
|
# llvm.core.Constant
|
||||||
- This will become a table of contents (this text will be scraped).
|
- This will become a table of contents (this text will be scraped).
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
Static factory methods
|
|
||||||
----------------------
|
Static factory methods
|
||||||
|
----------------------
|
||||||
``null(ty)``
|
|
||||||
~~~~~~~~~~~~
|
``null(ty)``
|
||||||
|
~~~~~~~~~~~~
|
||||||
A null value (all zeros) of type ``ty``
|
|
||||||
|
A null value (all zeros) of type ``ty``
|
||||||
``all_ones(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~
|
``all_ones(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
All 1's value of type ``ty``
|
|
||||||
|
All 1's value of type ``ty``
|
||||||
``undef(ty)``
|
|
||||||
~~~~~~~~~~~~~
|
``undef(ty)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
An undefined value of type ``ty``
|
|
||||||
|
An undefined value of type ``ty``
|
||||||
``int(ty, value)``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
``int(ty, value)``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
Integer of type ``ty``, with value ``value`` (a Python int or long)
|
|
||||||
|
Integer of type ``ty``, with value ``value`` (a Python int or long)
|
||||||
``int_signextend(ty, value)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
``int_signextend(ty, value)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Integer of signed type ``ty`` (use for signed types)
|
|
||||||
|
Integer of signed type ``ty`` (use for signed types)
|
||||||
``real(ty, value)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
``real(ty, value)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
Floating point value of type ``ty``, with value ``value`` (a Python
|
|
||||||
float)
|
Floating point value of type ``ty``, with value ``value`` (a Python
|
||||||
|
float)
|
||||||
``stringz(value)``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
``stringz(value)``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
A null-terminated string. ``value`` is a Python string
|
|
||||||
|
A null-terminated string. ``value`` is a Python string
|
||||||
``string(value)``
|
|
||||||
~~~~~~~~~~~~~~~~~
|
``string(value)``
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
As ``string(ty)``, but not null terminated
|
|
||||||
|
As ``string(ty)``, but not null terminated
|
||||||
``array(ty, consts)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
``array(ty, consts)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
Array of type ``ty``, initialized with ``consts`` (an iterable yielding
|
|
||||||
``Constant`` objects of the appropriate type)
|
Array of type ``ty``, initialized with ``consts`` (an iterable yielding
|
||||||
|
``Constant`` objects of the appropriate type)
|
||||||
``struct(ty, consts)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
``struct(ty, consts)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Struct (unpacked) of type ``ty``, initialized with ``consts`` (an
|
|
||||||
iterable yielding ``Constant`` objects of the appropriate type)
|
Struct (unpacked) of type ``ty``, initialized with ``consts`` (an
|
||||||
|
iterable yielding ``Constant`` objects of the appropriate type)
|
||||||
``packed_struct(ty, consts)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
``packed_struct(ty, consts)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
As ``struct(ty, consts)`` but packed
|
|
||||||
|
As ``struct(ty, consts)`` but packed
|
||||||
``vector(consts)``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
``vector(consts)``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
Vector, initialized with ``consts`` (an iterable yielding ``Constant``
|
|
||||||
objects of the appropriate type)
|
Vector, initialized with ``consts`` (an iterable yielding ``Constant``
|
||||||
|
objects of the appropriate type)
|
||||||
``sizeof(ty)``
|
|
||||||
~~~~~~~~~~~~~~
|
``sizeof(ty)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Constant value representing the sizeof the type ``ty``
|
|
||||||
|
Constant value representing the sizeof the type ``ty``
|
||||||
Methods
|
|
||||||
-------
|
Methods
|
||||||
|
-------
|
||||||
The following operations on constants are supported. For more details on
|
|
||||||
any operation, consult the `Constant
|
The following operations on constants are supported. For more details on
|
||||||
Expressions <http://www.llvm.org/docs/LangRef.html#constantexprs>`_
|
any operation, consult the `Constant
|
||||||
section of the LLVM Language Reference.
|
Expressions <http://www.llvm.org/docs/LangRef.html#constantexprs>`_
|
||||||
|
section of the LLVM Language Reference.
|
||||||
``k.neg()``
|
|
||||||
~~~~~~~~~~~
|
``k.neg()``
|
||||||
|
~~~~~~~~~~~
|
||||||
negation, same as ``0 - k``
|
|
||||||
|
negation, same as ``0 - k``
|
||||||
``k.not_()``
|
|
||||||
~~~~~~~~~~~~
|
``k.not_()``
|
||||||
|
~~~~~~~~~~~~
|
||||||
1's complement of ``k``. Note trailing underscore.
|
|
||||||
|
1's complement of ``k``. Note trailing underscore.
|
||||||
``k.add(k2)``
|
|
||||||
~~~~~~~~~~~~~
|
``k.add(k2)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
``k + k2``, where ``k`` and ``k2`` are integers.
|
|
||||||
|
``k + k2``, where ``k`` and ``k2`` are integers.
|
||||||
``k.fadd(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.fadd(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
``k + k2``, where ``k`` and ``k2`` are floating-point.
|
|
||||||
|
``k + k2``, where ``k`` and ``k2`` are floating-point.
|
||||||
``k.sub(k2)``
|
|
||||||
~~~~~~~~~~~~~
|
``k.sub(k2)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
``k - k2``, where ``k`` and ``k2`` are integers.
|
|
||||||
|
``k - k2``, where ``k`` and ``k2`` are integers.
|
||||||
``k.fsub(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.fsub(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
``k - k2``, where ``k`` and ``k2`` are floating-point.
|
|
||||||
|
``k - k2``, where ``k`` and ``k2`` are floating-point.
|
||||||
``k.mul(k2)``
|
|
||||||
~~~~~~~~~~~~~
|
``k.mul(k2)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
``k * k2``, where ``k`` and ``k2`` are integers.
|
|
||||||
|
``k * k2``, where ``k`` and ``k2`` are integers.
|
||||||
``k.fmul(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.fmul(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
``k * k2``, where ``k`` and ``k2`` are floating-point.
|
|
||||||
|
``k * k2``, where ``k`` and ``k2`` are floating-point.
|
||||||
``k.udiv(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.udiv(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Quotient of unsigned division of ``k`` with ``k2``
|
|
||||||
|
Quotient of unsigned division of ``k`` with ``k2``
|
||||||
``k.sdiv(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.sdiv(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Quotient of signed division of ``k`` with ``k2``
|
|
||||||
|
Quotient of signed division of ``k`` with ``k2``
|
||||||
``k.fdiv(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.fdiv(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Quotient of floating point division of ``k`` with ``k2``
|
|
||||||
|
Quotient of floating point division of ``k`` with ``k2``
|
||||||
``k.urem(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.urem(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Reminder of unsigned division of ``k`` with ``k2``
|
|
||||||
|
Reminder of unsigned division of ``k`` with ``k2``
|
||||||
``k.srem(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.srem(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Reminder of signed division of ``k`` with ``k2``
|
|
||||||
|
Reminder of signed division of ``k`` with ``k2``
|
||||||
``k.frem(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.frem(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Reminder of floating point division of ``k`` with ``k2``
|
|
||||||
|
Reminder of floating point division of ``k`` with ``k2``
|
||||||
``k.and_(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.and_(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Bitwise and of ``k`` and ``k2``. Note trailing underscore.
|
|
||||||
|
Bitwise and of ``k`` and ``k2``. Note trailing underscore.
|
||||||
``k.or_(k2)``
|
|
||||||
~~~~~~~~~~~~~
|
``k.or_(k2)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
Bitwise or of ``k`` and ``k2``. Note trailing underscore.
|
|
||||||
|
Bitwise or of ``k`` and ``k2``. Note trailing underscore.
|
||||||
``k.xor(k2)``
|
|
||||||
~~~~~~~~~~~~~
|
``k.xor(k2)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
Bitwise exclusive-or of ``k`` and ``k2``.
|
|
||||||
|
Bitwise exclusive-or of ``k`` and ``k2``.
|
||||||
``k.icmp(icmp, k2)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
``k.icmp(icmp, k2)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
Compare ``k`` with ``k2`` using the predicate ``icmp``. See
|
|
||||||
`here <comparision.html#icmp>`_ for list of predicates for integer
|
Compare ``k`` with ``k2`` using the predicate ``icmp``. See
|
||||||
operands.
|
`here <comparision.html#icmp>`_ for list of predicates for integer
|
||||||
|
operands.
|
||||||
``k.fcmp(fcmp, k2)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
``k.fcmp(fcmp, k2)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
Compare ``k`` with ``k2`` using the predicate ``fcmp``. See
|
|
||||||
`here <comparision.html#fcmp>`_ for list of predicates for real
|
Compare ``k`` with ``k2`` using the predicate ``fcmp``. See
|
||||||
operands.
|
`here <comparision.html#fcmp>`_ for list of predicates for real
|
||||||
|
operands.
|
||||||
``k.shl(k2)``
|
|
||||||
~~~~~~~~~~~~~
|
``k.shl(k2)``
|
||||||
|
~~~~~~~~~~~~~
|
||||||
Shift ``k`` left by ``k2`` bits.
|
|
||||||
|
Shift ``k`` left by ``k2`` bits.
|
||||||
``k.lshr(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.lshr(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Shift ``k`` logically right by ``k2`` bits (new bits are 0s).
|
|
||||||
|
Shift ``k`` logically right by ``k2`` bits (new bits are 0s).
|
||||||
``k.ashr(k2)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.ashr(k2)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as
|
|
||||||
previous sign bit).
|
Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as
|
||||||
|
previous sign bit).
|
||||||
``k.gep(indices)``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
``k.gep(indices)``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
GEP, see `LLVM docs <http://www.llvm.org/docs/GetElementPtr.html>`_.
|
|
||||||
|
GEP, see `LLVM docs <http://www.llvm.org/docs/GetElementPtr.html>`_.
|
||||||
``k.trunc(ty)``
|
|
||||||
~~~~~~~~~~~~~~~
|
``k.trunc(ty)``
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
Truncate ``k`` to a type ``ty`` of lower bitwidth.
|
|
||||||
|
Truncate ``k`` to a type ``ty`` of lower bitwidth.
|
||||||
``k.sext(ty)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.sext(ty)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending
|
|
||||||
the sign bit.
|
Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending
|
||||||
|
the sign bit.
|
||||||
``k.zext(ty)``
|
|
||||||
~~~~~~~~~~~~~~
|
``k.zext(ty)``
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are
|
|
||||||
0s.
|
Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are
|
||||||
|
0s.
|
||||||
``k.fptrunc(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~~
|
``k.fptrunc(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
Truncate floating point constant ``k`` to floating point type ``ty`` of
|
|
||||||
lower size than k's.
|
Truncate floating point constant ``k`` to floating point type ``ty`` of
|
||||||
|
lower size than k's.
|
||||||
``k.fpext(ty)``
|
|
||||||
~~~~~~~~~~~~~~~
|
``k.fpext(ty)``
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
Extend floating point constant ``k`` to floating point type ``ty`` of
|
|
||||||
higher size than k's.
|
Extend floating point constant ``k`` to floating point type ``ty`` of
|
||||||
|
higher size than k's.
|
||||||
``k.uitofp(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~
|
``k.uitofp(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
Convert an unsigned integer constant ``k`` to floating point constant of
|
|
||||||
type ``ty``.
|
Convert an unsigned integer constant ``k`` to floating point constant of
|
||||||
|
type ``ty``.
|
||||||
``k.sitofp(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~
|
``k.sitofp(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
Convert a signed integer constant ``k`` to floating point constant of
|
|
||||||
type ``ty``.
|
Convert a signed integer constant ``k`` to floating point constant of
|
||||||
|
type ``ty``.
|
||||||
``k.fptoui(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~
|
``k.fptoui(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
Convert a floating point constant ``k`` to an unsigned integer constant
|
|
||||||
of type ``ty``.
|
Convert a floating point constant ``k`` to an unsigned integer constant
|
||||||
|
of type ``ty``.
|
||||||
``k.fptosi(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~
|
``k.fptosi(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
Convert a floating point constant ``k`` to a signed integer constant of
|
|
||||||
type ``ty``.
|
Convert a floating point constant ``k`` to a signed integer constant of
|
||||||
|
type ``ty``.
|
||||||
``k.ptrtoint(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
``k.ptrtoint(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
Convert a pointer constant ``k`` to an integer constant of type ``ty``.
|
|
||||||
|
Convert a pointer constant ``k`` to an integer constant of type ``ty``.
|
||||||
``k.inttoptr(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
``k.inttoptr(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
Convert an integer constant ``k`` to a pointer constant of type ``ty``.
|
|
||||||
|
Convert an integer constant ``k`` to a pointer constant of type ``ty``.
|
||||||
``k.bitcast(ty)``
|
|
||||||
~~~~~~~~~~~~~~~~~
|
``k.bitcast(ty)``
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
Convert ``k`` to a (equal-width) constant of type ``ty``.
|
|
||||||
|
Convert ``k`` to a (equal-width) constant of type ``ty``.
|
||||||
``k.select(cond,k2,k3)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
``k.select(cond,k2,k3)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1,
|
|
||||||
else with ``k3``.
|
Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1,
|
||||||
|
else with ``k3``.
|
||||||
``k.extract_element(idx)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
``k.extract_element(idx)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Extract value at ``idx`` (integer constant) from a vector constant
|
|
||||||
``k``.
|
Extract value at ``idx`` (integer constant) from a vector constant
|
||||||
|
``k``.
|
||||||
``k.insert_element(k2,idx)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
``k.insert_element(k2,idx)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Insert value ``k2`` (scalar constant) at index ``idx`` (integer
|
|
||||||
constant) of vector constant ``k``.
|
Insert value ``k2`` (scalar constant) at index ``idx`` (integer
|
||||||
|
constant) of vector constant ``k``.
|
||||||
``k.shuffle_vector(k2,mask)``
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
``k.shuffle_vector(k2,mask)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Shuffle vector constant ``k`` based on vector constants ``k2`` and
|
|
||||||
``mask``.
|
Shuffle vector constant ``k`` based on vector constants ``k2`` and
|
||||||
|
``mask``.
|
||||||
--------------
|
|
||||||
|
--------------
|
||||||
# Other Constant Classes
|
|
||||||
The following subclasses of ``Constant`` do not provide additional
|
# Other Constant Classes
|
||||||
methods, **they serve only to provide richer type information.**
|
The following subclasses of ``Constant`` do not provide additional
|
||||||
|
methods, **they serve only to provide richer type information.**
|
||||||
Subclass \| LLVM C++ Class \| Remarks \|
|
|
||||||
---------\|----------------\|---------\| ``ConstantExpr`` \|
|
Subclass \| LLVM C++ Class \| Remarks \|
|
||||||
``llvmConstantExpr`` \| A constant expression \|
|
---------\|----------------\|---------\| ``ConstantExpr`` \|
|
||||||
``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero
|
``llvmConstantExpr`` \| A constant expression \|
|
||||||
constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer
|
``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero
|
||||||
constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point
|
constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer
|
||||||
constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array
|
constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point
|
||||||
constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A
|
constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array
|
||||||
structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \|
|
constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A
|
||||||
A vector constant \| ``ConstantPointerNull``\ \|
|
structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \|
|
||||||
``llvmConstantPointerNull``\ \| All-zero pointer constant \|
|
A vector constant \| ``ConstantPointerNull``\ \|
|
||||||
``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of
|
``llvmConstantPointerNull``\ \| All-zero pointer constant \|
|
||||||
LLVM IR \|
|
``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of
|
||||||
|
LLVM IR \|
|
||||||
These types are helpful in ``isinstance`` checks, like so:
|
|
||||||
|
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[] = {
|
{% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) #
|
||||||
k1, k1 };
|
int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = {
|
||||||
|
k1, k1 };
|
||||||
assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray)
|
|
||||||
|
assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray)
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Constant
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -149,3 +149,10 @@ function bodies.
|
||||||
|
|
||||||
Verifies the function. See `LLVM
|
Verifies the function. See `LLVM
|
||||||
docs <http://llvm.org/docs/Passes.html#verify>`_.
|
docs <http://llvm.org/docs/Passes.html#verify>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Function
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -46,3 +46,10 @@ the function. Used like this:
|
||||||
Type.int(), Type.int() ] ) for arg in func_type.args: assert arg.kind
|
Type.int(), Type.int() ] ) for arg in func_type.args: assert arg.kind
|
||||||
== TYPE_INTEGER assert arg == Type.int() assert func_type.arg_count
|
== TYPE_INTEGER assert arg == Type.int() assert func_type.arg_count
|
||||||
== len(func_type.args)
|
== len(func_type.args)
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.FunctionType
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -95,3 +95,9 @@ A power-of-2 integer indicating the boundary to align to.
|
||||||
|
|
||||||
The module object to which this global belongs to.
|
The module object to which this global belongs to.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.GlobalValue
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
| title: GlobalVariable (llvm.core) |
|
| title: GlobalVariable (llvm.core) |
|
||||||
+-------------------------------------+
|
+-------------------------------------+
|
||||||
|
|
||||||
|
llvm.core.GlobalVariable
|
||||||
|
========================
|
||||||
|
|
||||||
Global variables (``llvm.core.GlobalVariable``) are subclasses of
|
Global variables (``llvm.core.GlobalVariable``) are subclasses of
|
||||||
`llvm.core.GlobalValue <llvm.core.GlobalValue.html>`_ and represent
|
`llvm.core.GlobalValue <llvm.core.GlobalValue.html>`_ and represent
|
||||||
module-level variables. These can have optional initializers and can be
|
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
|
# list all global variables in a module
|
||||||
for gv in module_obj.global_variables: print gv.name, "of type",
|
for gv in module_obj.global_variables: print gv.name, "of type",
|
||||||
gv.type
|
gv.type
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.GlobalVariable
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -240,3 +240,10 @@ Properties
|
||||||
|
|
||||||
The predicate of the compare instruction, one of the ``ICMP_*`` or
|
The predicate of the compare instruction, one of the ``ICMP_*`` or
|
||||||
``FCMP_*`` constants.
|
``FCMP_*`` constants.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Instruction
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,10 @@ Properties
|
||||||
[read-only]
|
[read-only]
|
||||||
|
|
||||||
The width of the integer type, in number of bits.
|
The width of the integer type, in number of bits.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.IntegerType
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,26 @@
|
||||||
| title: Module (llvm.core) |
|
| title: Module (llvm.core) |
|
||||||
+-----------------------------+
|
+-----------------------------+
|
||||||
|
|
||||||
|
llvm.core.Module
|
||||||
|
================
|
||||||
|
|
||||||
Modules are top-level container objects. You need to create a module
|
Modules are top-level container objects. You need to create a module
|
||||||
object first, before you can add global variables, aliases or functions.
|
object first, before you can add global variables, aliases or functions.
|
||||||
Modules are created using the static method ``Module.new``:
|
Modules are created using the static method ``Module.new``:
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from llvm import \* from llvm.core import \*
|
from llvm import *
|
||||||
|
from llvm.core import *
|
||||||
|
|
||||||
# create a module
|
# create a module
|
||||||
my_module = Module.new('my_module')
|
my_module = Module.new('my_module')
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Module
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,10 @@ The address space of the pointer.
|
||||||
|
|
||||||
A `Type <llvm.core.Type.html>`_ object representing the type of the
|
A `Type <llvm.core.Type.html>`_ object representing the type of the
|
||||||
value pointed to.
|
value pointed to.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.PointerType
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
llvm.core.StructType
|
||||||
|
====================
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.StructType
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
@ -126,3 +126,10 @@ Example:
|
||||||
|
|
||||||
assert Type.int().kind == TYPE_INTEGER assert
|
assert Type.int().kind == TYPE_INTEGER assert
|
||||||
Type.void().kind == TYPE_VOID
|
Type.void().kind == TYPE_VOID
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Type
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,10 @@ The list of operands (values, of type
|
||||||
|
|
||||||
The number of operands that this value referes to. Same as
|
The number of operands that this value referes to. Same as
|
||||||
``len(uses.operands)`` but faster if you just want the count.
|
``len(uses.operands)`` but faster if you just want the count.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.User
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -63,3 +63,10 @@ representation.
|
||||||
``Value`` objects can be compared for equality. Internally, this
|
``Value`` objects can be compared for equality. Internally, this
|
||||||
converts both arguments into their LLVM assembly representations and
|
converts both arguments into their LLVM assembly representations and
|
||||||
compares the resultant strings.
|
compares the resultant strings.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.Value
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,10 @@ element of the vector.
|
||||||
[read-only]
|
[read-only]
|
||||||
|
|
||||||
The number of elements in the vector.
|
The number of elements in the vector.
|
||||||
|
|
||||||
|
|
||||||
|
Automatically Generated Documentation
|
||||||
|
-------------------------------------
|
||||||
|
.. autoclass:: llvm.core.VectorType
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
llvm_cbuilder
|
llvm_cbuilder
|
||||||
=========
|
=============
|
||||||
|
|
||||||
llvm_cbuilder is a set of Python-contexts you can use to write C-like
|
llvm_cbuilder is a set of Python-contexts you can use to write C-like
|
||||||
constructs in Python which generates llvmpy code directly.
|
constructs in Python which generates llvmpy code directly.
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ follow these steps:
|
||||||
- add a *basic block* to the function
|
- add a *basic block* to the function
|
||||||
- using a helper object called an *instruction builder*, add two
|
- using a helper object called an *instruction builder*, add two
|
||||||
instructions into the basic block:
|
instructions into the basic block:
|
||||||
|
|
||||||
- an instruction to add the two
|
- an instruction to add the two
|
||||||
arguments and store the result into a temporary variable
|
arguments and store the result into a temporary variable
|
||||||
- a return
|
- a return
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
You can adapt this file completely to your liking, but it should at least
|
You can adapt this file completely to your liking, but it should at least
|
||||||
contain the root `toctree` directive.
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
Documentation for llvmpy
|
llvmpy
|
||||||
=================
|
======
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ Contents:
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
------------------
|
||||||
|
|
||||||
* :ref:`genindex`
|
* :ref:`genindex`
|
||||||
* :ref:`modindex`
|
* :ref:`modindex`
|
||||||
|
|
|
||||||
152
example/vector_instr.py
Normal file
152
example/vector_instr.py
Normal 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()
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
from __future__ import absolute_import
|
||||||
import opcode
|
import opcode
|
||||||
import opcode_util
|
from . import opcode_util
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
from bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin
|
from .bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin
|
||||||
from control_flow import ControlFlowGraph
|
from .control_flow import ControlFlowGraph
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
||||||
'''Visitor responsible for traversing a bytecode flow object and
|
'''Visitor responsible for traversing a bytecode basic block map and
|
||||||
building a control flow graph (CFG).
|
building a control flow graph (CFG).
|
||||||
|
|
||||||
The primary purpose of this transformation is to create a CFG,
|
The primary purpose of this transformation is to create a CFG,
|
||||||
|
|
@ -27,21 +26,26 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
||||||
del self.nargs
|
del self.nargs
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def enter_flow_object (self, flow):
|
def enter_blocks (self, blocks):
|
||||||
super(ControlFlowBuilder, self).enter_flow_object(flow)
|
super(ControlFlowBuilder, self).enter_blocks(blocks)
|
||||||
self.flow = flow
|
self.blocks = blocks
|
||||||
|
self.block_list = list(blocks.keys())
|
||||||
|
self.block_list.sort()
|
||||||
self.cfg = ControlFlowGraph()
|
self.cfg = ControlFlowGraph()
|
||||||
for block in flow.keys():
|
self.loop_stack = []
|
||||||
self.cfg.add_block(block, flow[block])
|
for block in self.block_list:
|
||||||
|
self.cfg.add_block(block, blocks[block])
|
||||||
|
|
||||||
def exit_flow_object (self, flow):
|
def exit_blocks (self, blocks):
|
||||||
super(ControlFlowBuilder, self).exit_flow_object(flow)
|
super(ControlFlowBuilder, self).exit_blocks(blocks)
|
||||||
assert self.flow == flow
|
assert self.blocks == blocks
|
||||||
self.cfg.compute_dataflow()
|
self.cfg.compute_dataflow()
|
||||||
self.cfg.update_for_ssa()
|
self.cfg.update_for_ssa()
|
||||||
ret_val = self.cfg
|
ret_val = self.cfg
|
||||||
|
del self.loop_stack
|
||||||
del self.cfg
|
del self.cfg
|
||||||
del self.flow
|
del self.block_list
|
||||||
|
del self.blocks
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def enter_block (self, block):
|
def enter_block (self, block):
|
||||||
|
|
@ -58,13 +62,15 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
||||||
def exit_block (self, block):
|
def exit_block (self, block):
|
||||||
assert block == self.block
|
assert block == self.block
|
||||||
del 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:
|
if op in opcode.hasjabs:
|
||||||
self.cfg.add_edge(block, arg)
|
self.cfg.add_edge(block, arg)
|
||||||
elif op in opcode.hasjrel:
|
elif op in opcode.hasjrel:
|
||||||
self.cfg.add_edge(block, i + arg + 3)
|
self.cfg.add_edge(block, i + arg + 3)
|
||||||
elif opname == 'BREAK_LOOP':
|
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':
|
elif opname != 'RETURN_VALUE':
|
||||||
self.cfg.add_edge(block, self._get_next_block(block))
|
self.cfg.add_edge(block, self._get_next_block(block))
|
||||||
if op in opcode_util.hascbranch:
|
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,
|
return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args,
|
||||||
**kws)
|
**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):
|
def build_cfg (func):
|
||||||
'''Given a Python function, create a bytecode flow, visit the flow
|
'''Given a Python function, create a bytecode flow, visit the flow
|
||||||
object, and return a control flow graph.'''
|
object, and return a control flow graph.'''
|
||||||
import byte_flow
|
co_obj = opcode_util.get_code_object(func)
|
||||||
return ControlFlowBuilder().visit(
|
return ControlFlowBuilder().visit(opcode_util.build_basic_blocks(co_obj),
|
||||||
byte_flow.build_flow(func),
|
co_obj.co_argcount)
|
||||||
opcode_util.get_code_object(func).co_argcount)
|
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
# Main (self-test) routine
|
# Main (self-test) routine
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
from __future__ import absolute_import
|
||||||
import dis
|
import dis
|
||||||
import opcode
|
import opcode
|
||||||
|
|
||||||
from bytecode_visitor import BytecodeIterVisitor
|
from .bytecode_visitor import BasicBlockVisitor
|
||||||
import opcode_util
|
from . import opcode_util
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
class BytecodeFlowBuilder (BytecodeIterVisitor):
|
class BytecodeFlowBuilder (BasicBlockVisitor):
|
||||||
'''Transforms a bytecode vector into a bytecode "flow tree".
|
'''Transforms a CFG into a bytecode "flow tree".
|
||||||
|
|
||||||
The flow tree is a Python dictionary, described loosely by the
|
The flow tree is a Python dictionary, described loosely by the
|
||||||
following set of productions:
|
following set of productions:
|
||||||
|
|
@ -36,6 +35,8 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
|
||||||
if pops:
|
if pops:
|
||||||
if pops < 0:
|
if pops < 0:
|
||||||
pops = arg - pops - 1
|
pops = arg - pops - 1
|
||||||
|
assert pops <= len(self.stack), ("Stack underflow at instruction "
|
||||||
|
"%d (%s)!" % (i, opname))
|
||||||
stk_args = self.stack[-pops:]
|
stk_args = self.stack[-pops:]
|
||||||
del self.stack[-pops:]
|
del self.stack[-pops:]
|
||||||
else:
|
else:
|
||||||
|
|
@ -51,27 +52,50 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
|
||||||
opname, pops, pushes, appends = self.opmap[op]
|
opname, pops, pushes, appends = self.opmap[op]
|
||||||
return self._visit_op(i, op, arg, opname, pops, pushes, appends)
|
return self._visit_op(i, op, arg, opname, pops, pushes, appends)
|
||||||
|
|
||||||
def enter_code_object (self, co_obj):
|
def visit_cfg (self, cfg):
|
||||||
labels = dis.findlabels(co_obj.co_code)
|
self.cfg = cfg
|
||||||
labels = opcode_util.extendlabels(co_obj.co_code, labels)
|
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, [])
|
self.blocks = dict((index, [])
|
||||||
for index in labels)
|
for index in labels)
|
||||||
self.stack = []
|
|
||||||
self.loop_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
|
ret_val = self.blocks
|
||||||
del self.stack
|
del self.stacks
|
||||||
del self.loop_stack
|
del self.loop_stack
|
||||||
del self.block
|
|
||||||
del self.blocks
|
del self.blocks
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def visit_op (self, i, op, arg):
|
def enter_block (self, block):
|
||||||
if i in self.blocks:
|
self.block_no = block
|
||||||
self.block = self.blocks[i]
|
self.block = self.blocks[block]
|
||||||
return super(BytecodeFlowBuilder, self).visit_op(i, op, arg)
|
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_ADD = _op
|
||||||
op_BINARY_AND = _op
|
op_BINARY_AND = _op
|
||||||
|
|
@ -140,8 +164,14 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
|
||||||
op_INPLACE_XOR = _op
|
op_INPLACE_XOR = _op
|
||||||
op_JUMP_ABSOLUTE = _op
|
op_JUMP_ABSOLUTE = _op
|
||||||
op_JUMP_FORWARD = _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_LIST_APPEND = _op
|
||||||
op_LOAD_ATTR = _op
|
op_LOAD_ATTR = _op
|
||||||
op_LOAD_CLOSURE = _op
|
op_LOAD_CLOSURE = _op
|
||||||
|
|
@ -211,7 +241,9 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
|
||||||
def build_flow (func):
|
def build_flow (func):
|
||||||
'''Given a Python function, return a bytecode flow tree for that
|
'''Given a Python function, return a bytecode flow tree for that
|
||||||
function.'''
|
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
|
# Main (self-test) routine
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
'''Defines a bytecode based LLVM translator for llpython code.
|
'''Defines a bytecode based LLVM translator for llpython code.
|
||||||
'''
|
'''
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
# Module imports
|
# Module imports
|
||||||
|
from __future__ import absolute_import
|
||||||
import opcode
|
import opcode
|
||||||
import types
|
import types
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import llvm.core as lc
|
import llvm.core as lc
|
||||||
|
|
||||||
import opcode_util
|
from . import opcode_util
|
||||||
import bytetype
|
from . import bytetype
|
||||||
from bytecode_visitor import BytecodeFlowVisitor
|
from .bytecode_visitor import BytecodeFlowVisitor
|
||||||
from byte_flow import BytecodeFlowBuilder
|
from .byte_flow import BytecodeFlowBuilder
|
||||||
from byte_control import ControlFlowBuilder
|
from .byte_control import ControlFlowBuilder
|
||||||
from phi_injector import PhiInjector, synthetic_opname
|
from .phi_injector import PhiInjector, synthetic_opname
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
# Module data
|
# Module data
|
||||||
|
|
@ -153,7 +152,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
||||||
environment.'''
|
environment.'''
|
||||||
if llvm_type is None:
|
if llvm_type is None:
|
||||||
if llvm_function is None:
|
if llvm_function is None:
|
||||||
llvm_type = lc.Type.function(lvoid, ())
|
llvm_type = lc.Type.function(bytetype.lvoid, ())
|
||||||
else:
|
else:
|
||||||
llvm_type = llvm_function.type.pointee
|
llvm_type = llvm_function.type.pointee
|
||||||
if env is None:
|
if env is None:
|
||||||
|
|
@ -178,7 +177,8 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
||||||
self.globals = func_globals
|
self.globals = func_globals
|
||||||
nargs = self.code_obj.co_argcount
|
nargs = self.code_obj.co_argcount
|
||||||
self.cfg = self.control_flow_builder.visit(
|
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
|
self.llvm_function = llvm_function
|
||||||
flow = self.phi_injector.visit_cfg(self.cfg, nargs)
|
flow = self.phi_injector.visit_cfg(self.cfg, nargs)
|
||||||
ret_val = self.visit(flow)
|
ret_val = self.visit(flow)
|
||||||
|
|
@ -224,6 +224,12 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def exit_block (self, block):
|
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.llvm_block
|
||||||
del self.builder
|
del self.builder
|
||||||
|
|
||||||
|
|
@ -449,7 +455,11 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
||||||
return [self.builder.branch(self.llvm_blocks[i + arg + 3])]
|
return [self.builder.branch(self.llvm_blocks[i + arg + 3])]
|
||||||
|
|
||||||
def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws):
|
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):
|
def op_JUMP_IF_FALSE_OR_POP (self, i, op, arg, *args, **kws):
|
||||||
raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP")
|
raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP")
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
from __future__ import absolute_import
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
import opcode
|
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):
|
class BytecodeFlowVisitor (BytecodeVisitor):
|
||||||
def visit (self, flow):
|
def visit (self, flow):
|
||||||
self.block_list = list(flow.keys())
|
self.block_list = list(flow.keys())
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
from __future__ import absolute_import
|
||||||
import opcode_util
|
from . import opcode_util
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
from __future__ import absolute_import
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import imp
|
import imp
|
||||||
|
|
@ -10,13 +9,12 @@ import types
|
||||||
import llvm.core as lc
|
import llvm.core as lc
|
||||||
import llvm.ee as le
|
import llvm.ee as le
|
||||||
|
|
||||||
import bytetype
|
from . import bytetype, byte_translator
|
||||||
import byte_translator
|
from .pyaddfunc import pyaddfunc
|
||||||
from pyaddfunc import pyaddfunc
|
|
||||||
|
|
||||||
LLVM_TO_INT_PARSE_STR_MAP = {
|
LLVM_TO_INT_PARSE_STR_MAP = {
|
||||||
8 : 'b',
|
8 : 'b',
|
||||||
16 : 'h',
|
16 : 'h',
|
||||||
32 : 'i', # Note that on 32-bit systems sizeof(int) == sizeof(long)
|
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
|
64 : 'L', # Seeing sizeof(long long) == 8 on both 32 and 64-bit platforms
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
import dis
|
import dis
|
||||||
|
|
@ -79,9 +78,9 @@ OPCODE_MAP = {
|
||||||
'INPLACE_XOR': (2, 1, None),
|
'INPLACE_XOR': (2, 1, None),
|
||||||
'JUMP_ABSOLUTE': (0, None, 1),
|
'JUMP_ABSOLUTE': (0, None, 1),
|
||||||
'JUMP_FORWARD': (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_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),
|
'JUMP_IF_TRUE_OR_POP': (None, None, None),
|
||||||
'LIST_APPEND': (2, 0, 1),
|
'LIST_APPEND': (2, 0, 1),
|
||||||
'LOAD_ATTR': (1, 1, None),
|
'LOAD_ATTR': (1, 1, None),
|
||||||
|
|
@ -148,7 +147,7 @@ OPCODE_MAP = {
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
# Module functions
|
# Module functions
|
||||||
|
|
||||||
def itercode(code):
|
def itercode(code, start = 0):
|
||||||
"""Return a generator of byte-offset, opcode, and argument
|
"""Return a generator of byte-offset, opcode, and argument
|
||||||
from a byte-code-string
|
from a byte-code-string
|
||||||
"""
|
"""
|
||||||
|
|
@ -159,7 +158,7 @@ def itercode(code):
|
||||||
n = len(code)
|
n = len(code)
|
||||||
while i < n:
|
while i < n:
|
||||||
op = code[i]
|
op = code[i]
|
||||||
num = i
|
num = i + start
|
||||||
i = i + 1
|
i = i + 1
|
||||||
oparg = None
|
oparg = None
|
||||||
if op >= opcode.HAVE_ARGUMENT:
|
if op >= opcode.HAVE_ARGUMENT:
|
||||||
|
|
@ -211,5 +210,16 @@ def extendlabels(code, labels = None):
|
||||||
def get_code_object (func):
|
def get_code_object (func):
|
||||||
return getattr(func, '__code__', getattr(func, 'func_code', None))
|
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
|
# End of opcode_util.py
|
||||||
|
|
|
||||||
|
|
@ -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):
|
def inject_phis (func):
|
||||||
'''Given a Python function, return a bytecode flow object that has
|
'''Given a Python function, return a bytecode flow object that has
|
||||||
been transformed by a fresh PhiInjector instance.'''
|
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
|
argcount = byte_control.opcode_util.get_code_object(func).co_argcount
|
||||||
cfg = byte_control.build_cfg(func)
|
cfg = byte_control.build_cfg(func)
|
||||||
|
cfg.blocks = byte_flow.BytecodeFlowBuilder().visit_cfg(cfg)
|
||||||
return PhiInjector().visit_cfg(cfg, argcount)
|
return PhiInjector().visit_cfg(cfg, argcount)
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
def doslice (in_string, lower, upper):
|
def doslice (in_string, lower, upper):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
import llvm.core as lc
|
import llvm.core as lc
|
||||||
|
|
|
||||||
22
llrtc/Makefile
Normal file
22
llrtc/Makefile
Normal 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
25
llrtc/README.md
Normal 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
4
llrtc/lib/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
*.o
|
||||||
|
*.run
|
||||||
|
*.out
|
||||||
|
*.ll
|
||||||
66
llrtc/lib/Makefile
Normal file
66
llrtc/lib/Makefile
Normal 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
11
llrtc/lib/div64.c
Normal 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
19
llrtc/lib/llrt.h
Normal 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
15
llrtc/lib/mod64.c
Normal 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
40
llrtc/lib/sdivmod64.c
Normal 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;
|
||||||
|
}
|
||||||
21
llrtc/lib/test_sdivmod64.c
Normal file
21
llrtc/lib/test_sdivmod64.c
Normal 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;
|
||||||
|
}
|
||||||
56
llrtc/lib/test_sdivmod64.py
Normal file
56
llrtc/lib/test_sdivmod64.py
Normal 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()
|
||||||
20
llrtc/lib/test_udivmod64.c
Normal file
20
llrtc/lib/test_udivmod64.c
Normal 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;
|
||||||
|
}
|
||||||
53
llrtc/lib/test_udivmod64.py
Normal file
53
llrtc/lib/test_udivmod64.py
Normal 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
84
llrtc/lib/udivmod64.c
Normal 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;
|
||||||
|
}
|
||||||
15
llrtc/tools/striptriple.py
Normal file
15
llrtc/tools/striptriple.py
Normal 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)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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':
|
def find_llvm_tblgen():
|
||||||
cmd = 'llvm-tblgen --version'
|
path = find_executable('llvm-tblgen')
|
||||||
# Hardcoded extraction, only tested on llvm 3.1
|
if path is None:
|
||||||
result = os.popen(cmd).read().split('\n')[1].strip().split(' ')[2]
|
sys.exit('Error: could not locate llvm-tblgen')
|
||||||
print result
|
return path
|
||||||
elif sys.argv[1] == '--libs':
|
|
||||||
|
|
||||||
|
def find_llvm_prefix():
|
||||||
|
return abspath(dirname(dirname(find_llvm_tblgen())))
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_file(path):
|
||||||
|
if not isfile(path):
|
||||||
|
sys.exit('Error: no file: %r' % path)
|
||||||
|
|
||||||
|
|
||||||
|
def get_llvm_version():
|
||||||
|
args = [find_llvm_tblgen(), '--version']
|
||||||
|
p = Popen(args, stdout=PIPE, stderr=PIPE)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
if stderr:
|
||||||
|
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,
|
# 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 """
|
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
|
Advapi32
|
||||||
Shell32
|
Shell32
|
||||||
""".split():
|
""".split():
|
||||||
print('-l%s' % lib)
|
print('-l%s' % lib)
|
||||||
llvmbin = find_path_of('llvm-tblgen.exe')
|
|
||||||
if os.path.exists(os.path.join(llvmbin, '../lib/LLVMPTXCodeGen.lib')):
|
bpath = join(find_llvm_prefix(), 'lib')
|
||||||
print('-lLLVMPTXAsmPrinter')
|
for filename in listdir(bpath):
|
||||||
print('-lLLVMPTXCodeGen')
|
filepath = join(bpath, filename)
|
||||||
print('-lLLVMPTXDesc')
|
if isfile(filepath) and filename.endswith('.lib') and filename.startswith('LLVM'):
|
||||||
print('-lLLVMPTXInfo')
|
name = filename.split('.', 1)[0]
|
||||||
elif sys.argv[1] == '--includedir':
|
print('-l%s' % name)
|
||||||
llvmbin = find_path_of('llvm-tblgen.exe')
|
|
||||||
if llvmbin is None:
|
def main():
|
||||||
raise RuntimeError('Could not find LLVM')
|
try:
|
||||||
incdir = os.path.abspath(os.path.join(llvmbin, '../include'))
|
option = sys.argv[1]
|
||||||
if not os.path.exists(os.path.join(incdir, 'llvm/BasicBlock.h')):
|
except IndexError:
|
||||||
raise RuntimeError('Could not find LLVM include dir')
|
sys.exit('Error: option missing')
|
||||||
print incdir
|
|
||||||
elif sys.argv[1] == '--libdir':
|
if option == '--version':
|
||||||
llvmbin = find_path_of('llvm-tblgen.exe')
|
print(get_llvm_version())
|
||||||
if llvmbin is None:
|
|
||||||
raise RuntimeError('Could not find LLVM')
|
elif option == '--targets-built':
|
||||||
libdir = os.path.abspath(os.path.join(llvmbin, '../lib'))
|
print('X86') # just do X86
|
||||||
if not os.path.exists(os.path.join(libdir, 'LLVMCore.lib')):
|
|
||||||
raise RuntimeError('Could not find LLVM lib dir')
|
elif option == '--libs':
|
||||||
print libdir
|
libs_options()
|
||||||
else:
|
|
||||||
raise RuntimeError('Unrecognized llvm-config command %s' % sys.argv[1])
|
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()
|
||||||
|
|
|
||||||
2117
llvm/2.9_update.diff
2117
llvm/2.9_update.diff
File diff suppressed because it is too large
Load diff
173
llvm/__init__.py
173
llvm/__init__.py
|
|
@ -1,152 +1,47 @@
|
||||||
"""
|
from ._version import get_versions
|
||||||
Common classes related to LLVM.
|
__version__ = get_versions()['version']
|
||||||
"""
|
del get_versions
|
||||||
|
|
||||||
__version__ = '0.10.0'
|
|
||||||
|
|
||||||
|
|
||||||
from weakref import WeakValueDictionary
|
from llvmpy import extra
|
||||||
import _core
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
version = extra.get_llvm_version()
|
||||||
# LLVM Version
|
del extra
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
|
|
||||||
version = _core.LLVMGetVersion()
|
class Wrapper(object):
|
||||||
|
__slots__ = '__ptr'
|
||||||
|
|
||||||
def require_version_at_least(major, minor):
|
def __init__(self, ptr):
|
||||||
'''Sentry to guard version requirement
|
assert ptr
|
||||||
'''
|
self.__ptr = ptr
|
||||||
if version < (major, minor):
|
|
||||||
raise Exception(major, minor)
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
@property
|
||||||
# Exceptions
|
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):
|
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
|
pass
|
||||||
|
|
||||||
|
def test(verbosity=3, run_isolated=True):
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
# A metaclass to prevent aliasing. It stores a (weak) reference to objects
|
|
||||||
# constructed based on a PyCObject. If an object is constructed based on a
|
|
||||||
# PyCObject with the same underlying pointer as a previous object, a reference
|
|
||||||
# to the previous object is returned rather than a new one.
|
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
|
|
||||||
class _ObjectCache(type):
|
|
||||||
"""A metaclass to prevent aliasing.
|
|
||||||
|
|
||||||
Classes using 'ObjectCache' as a metaclass must have constructors
|
|
||||||
that take a PyCObject as their first argument. When the class is
|
|
||||||
called (to create a new instance of the class), the value of the
|
|
||||||
pointer wrapped by the PyCObj is checked:
|
|
||||||
|
|
||||||
If no previous object has been created based on the same
|
|
||||||
underlying pointer (note that different PyCObject objects can
|
|
||||||
wrap the same pointer), the object will be initialized as
|
|
||||||
usual and returned.
|
|
||||||
|
|
||||||
If a previous has been created based on the same pointer,
|
|
||||||
then a reference to that object will be returned, and no
|
|
||||||
object initialization is performed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__instances = WeakValueDictionary()
|
|
||||||
|
|
||||||
def __call__(cls, ptr, *args, **kwargs):
|
|
||||||
objid = _core.PyCObjectVoidPtrToPyLong(ptr)
|
|
||||||
key = "%s:%d" % (cls.__name__, objid)
|
|
||||||
obj = _ObjectCache.__instances.get(key)
|
|
||||||
if obj is None:
|
|
||||||
obj = super(_ObjectCache, cls).__call__(ptr, *args, **kwargs)
|
|
||||||
_ObjectCache.__instances[key] = obj
|
|
||||||
return obj
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def forget(obj):
|
|
||||||
objid = _core.PyCObjectVoidPtrToPyLong(obj.ptr)
|
|
||||||
key = "%s:%d" % (type(obj).__name__, objid)
|
|
||||||
if key in _ObjectCache.__instances:
|
|
||||||
del _ObjectCache.__instances[key]
|
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
# Cacheables
|
|
||||||
#===----------------------------------------------------------------------===
|
|
||||||
|
|
||||||
# version 2/3 compatibility help
|
|
||||||
# version 2 metaclass
|
|
||||||
# class Cacheable(object):
|
|
||||||
# __metaclass__ = _ObjectCache # Doing nothing for version 3
|
|
||||||
#
|
|
||||||
# version 3 metaclass
|
|
||||||
# class Cacheable(metaclass=_ObjectCache):
|
|
||||||
#
|
|
||||||
# Reference: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/#using-the-metaclass-in-python-3-x
|
|
||||||
ObjectCache = _ObjectCache('ObjectCache', (object, ), {})
|
|
||||||
|
|
||||||
class Cacheable(ObjectCache):
|
|
||||||
"""Objects that can be cached.
|
|
||||||
|
|
||||||
Objects that wrap a PyCObject are cached to avoid "aliasing", i.e.,
|
|
||||||
two Python objects each containing a PyCObject which internally points
|
|
||||||
to the same C pointer."""
|
|
||||||
|
|
||||||
def forget(self):
|
|
||||||
ObjectCache.forget(self)
|
|
||||||
|
|
||||||
|
|
||||||
def test(verbosity=1):
|
|
||||||
"""test(verbosity=1) -> TextTestResult
|
"""test(verbosity=1) -> TextTestResult
|
||||||
|
|
||||||
Run self-test, and return unittest.runner.TextTestResult object.
|
Run self-test, and return the number of failures + errors
|
||||||
"""
|
"""
|
||||||
from llvm.test_llvmpy import run
|
from llvm.tests import run
|
||||||
|
|
||||||
return run(verbosity=verbosity)
|
result = run(verbosity=verbosity, run_isolated=run_isolated)
|
||||||
|
errct = len(result.failures) + len(result.errors)
|
||||||
|
|
||||||
|
return errct
|
||||||
|
|
|
||||||
2212
llvm/_core.cpp
2212
llvm/_core.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
|
||||||
}
|
|
||||||
101
llvm/_dwarf.h
101
llvm/_dwarf.h
|
|
@ -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)
|
|
||||||
|
|
||||||
108
llvm/_util.py
108
llvm/_util.py
|
|
@ -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
193
llvm/_version.py
Normal 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
|
||||||
|
|
@ -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 */
|
|
||||||
2629
llvm/core.py
2629
llvm/core.py
File diff suppressed because it is too large
Load diff
|
|
@ -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
25
llvm/deprecated.py
Normal 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
|
||||||
348
llvm/ee.py
348
llvm/ee.py
|
|
@ -28,85 +28,54 @@
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# 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
|
||||||
import llvm.core as core # module, function etc.
|
from llvm import core
|
||||||
import llvm._core as _core # C wrappers
|
from llvm.passes import TargetData, TargetTransformInfo
|
||||||
import llvm._util as _util # utility functions
|
from llvmpy import api, extra
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
# re-export TargetData for backward compatibility.
|
|
||||||
from llvm.passes import TargetData
|
|
||||||
|
|
||||||
def _detect_avx_support():
|
|
||||||
'''FIXME: This is a workaround for AVX support.
|
|
||||||
'''
|
|
||||||
disable_avx_detect = int(os.environ.get('LLVMPY_DISABLE_AVX_DETECT', 0))
|
|
||||||
if disable_avx_detect:
|
|
||||||
return False # enable AVX if user disable AVX detect
|
|
||||||
force_disable_avx = int(os.environ.get('LLVMPY_FORCE_DISABLE_AVX', 0))
|
|
||||||
if force_disable_avx:
|
|
||||||
return True # force disable AVX
|
|
||||||
# auto-detect avx
|
|
||||||
try:
|
|
||||||
for line in open('/proc/cpuinfo'):
|
|
||||||
if line.lstrip().startswith('flags') and 'avx' in line.split():
|
|
||||||
# enable AVX if flags contain AVX
|
|
||||||
return False
|
|
||||||
except IOError:
|
|
||||||
pass # disable AVX if no /proc/cpuinfo is found
|
|
||||||
return True # disable AVX if flags does not have AVX
|
|
||||||
|
|
||||||
FORCE_DISABLE_AVX = _detect_avx_support()
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Enumerations
|
# 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
|
# Generic value
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class GenericValue(object):
|
class GenericValue(llvm.Wrapper):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def int(ty, intval):
|
def int(ty, intval):
|
||||||
core.check_is_type(ty)
|
ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), False)
|
||||||
ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 0)
|
|
||||||
return GenericValue(ptr)
|
return GenericValue(ptr)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def int_signed(ty, intval):
|
def int_signed(ty, intval):
|
||||||
core.check_is_type(ty)
|
ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), True)
|
||||||
ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 1)
|
|
||||||
return GenericValue(ptr)
|
return GenericValue(ptr)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def real(ty, floatval):
|
def real(ty, floatval):
|
||||||
core.check_is_type(ty) # only float or double
|
if str(ty) == 'float':
|
||||||
ptr = _core.LLVMCreateGenericValueOfFloat(ty.ptr, floatval)
|
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)
|
return GenericValue(ptr)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pointer(*args):
|
def pointer(addr):
|
||||||
'''
|
'''
|
||||||
One argument version takes (addr).
|
One argument version takes (addr).
|
||||||
Two argument version takes (ty, addr). [Deprecated]
|
Two argument version takes (ty, addr). [Deprecated]
|
||||||
|
|
@ -114,79 +83,46 @@ class GenericValue(object):
|
||||||
`ty` is unused.
|
`ty` is unused.
|
||||||
`addr` is an integer representing an address.
|
`addr` is an integer representing an address.
|
||||||
|
|
||||||
TODO: remove two argument version.
|
|
||||||
'''
|
'''
|
||||||
if len(args)==2:
|
ptr = api.llvm.GenericValue.CreatePointer(int(addr))
|
||||||
logger.warning("Deprecated: Two argument version of "
|
|
||||||
"GenericValue.pointer() is deprecated.")
|
|
||||||
addr = args[1]
|
|
||||||
elif len(args)!=1:
|
|
||||||
raise TypeError("pointer() takes 1 or 2 arguments.")
|
|
||||||
else:
|
|
||||||
addr = args[0]
|
|
||||||
ptr = _core.LLVMCreateGenericValueOfPointer(addr)
|
|
||||||
return GenericValue(ptr)
|
return GenericValue(ptr)
|
||||||
|
|
||||||
def __init__(self, ptr):
|
|
||||||
self.ptr = ptr
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
_core.LLVMDisposeGenericValue(self.ptr)
|
|
||||||
|
|
||||||
def as_int(self):
|
def as_int(self):
|
||||||
return _core.LLVMGenericValueToInt(self.ptr, 0)
|
return self._ptr.toUnsignedInt()
|
||||||
|
|
||||||
def as_int_signed(self):
|
def as_int_signed(self):
|
||||||
return _core.LLVMGenericValueToInt(self.ptr, 1)
|
return self._ptr.toSignedInt()
|
||||||
|
|
||||||
def as_real(self, ty):
|
def as_real(self, ty):
|
||||||
core.check_is_type(ty) # only float or double
|
return self._ptr.toFloat(ty._ptr)
|
||||||
return _core.LLVMGenericValueToFloat(ty.ptr, self.ptr)
|
|
||||||
|
|
||||||
def as_pointer(self):
|
def as_pointer(self):
|
||||||
return _core.LLVMGenericValueToPointer(self.ptr)
|
return self._ptr.toPointer()
|
||||||
|
|
||||||
|
|
||||||
# helper functions for generic value objects
|
|
||||||
def check_is_generic_value(obj): _util.check_gen(obj, GenericValue)
|
|
||||||
def _unpack_generic_values(objlist):
|
|
||||||
return _util.unpack_gen(objlist, check_is_generic_value)
|
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Engine builder
|
# Engine builder
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class EngineBuilder(object):
|
class EngineBuilder(llvm.Wrapper):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(module):
|
def new(module):
|
||||||
core.check_is_module(module)
|
ptr = api.llvm.EngineBuilder.new(module._ptr)
|
||||||
_util.check_is_unowned(module)
|
return EngineBuilder(ptr)
|
||||||
obj = _core.LLVMCreateEngineBuilder(module.ptr)
|
|
||||||
return EngineBuilder(obj, module)
|
|
||||||
|
|
||||||
def __init__(self, ptr, module):
|
|
||||||
self.ptr = ptr
|
|
||||||
self._module = module
|
|
||||||
self.__has_mattrs = False
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
_core.LLVMDisposeEngineBuilder(self.ptr)
|
|
||||||
|
|
||||||
def force_jit(self):
|
def force_jit(self):
|
||||||
_core.LLVMEngineBuilderForceJIT(self.ptr)
|
self._ptr.setEngineKind(api.llvm.EngineKind.Kind.JIT)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def force_interpreter(self):
|
def force_interpreter(self):
|
||||||
_core.LLVMEngineBuilderForceInterpreter(self.ptr)
|
self._ptr.setEngineKind(api.llvm.EngineKind.Kind.Interpreter)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def opt(self, level):
|
def opt(self, level):
|
||||||
'''
|
'''
|
||||||
level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive]
|
level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive]
|
||||||
'''
|
'''
|
||||||
assert level in range(4)
|
assert 0 <= level <= 3
|
||||||
_core.LLVMEngineBuilderSetOptLevel(self.ptr, level)
|
self._ptr.setOptLevel(level)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def mattrs(self, string):
|
def mattrs(self, string):
|
||||||
|
|
@ -194,45 +130,53 @@ class EngineBuilder(object):
|
||||||
|
|
||||||
e.g: +sse,-3dnow
|
e.g: +sse,-3dnow
|
||||||
'''
|
'''
|
||||||
self.__has_mattrs = True
|
self._ptr.setMAttrs(string.split(','))
|
||||||
if FORCE_DISABLE_AVX:
|
|
||||||
if 'avx' not in map(lambda x: x.strip(), string.split(',')):
|
|
||||||
# User did not override
|
|
||||||
string += ',-avx'
|
|
||||||
_core.LLVMEngineBuilderSetMAttrs(self.ptr, string.replace(',', ' '))
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def create(self, tm=None):
|
def create(self, tm=None):
|
||||||
'''
|
'''
|
||||||
tm --- Optional. Provide a TargetMachine. Ownership is transfered
|
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:
|
if tm is not None:
|
||||||
self.mattrs('-avx')
|
engine = self._ptr.create(tm._ptr)
|
||||||
|
elif (sys.platform.startswith('win32') and
|
||||||
if tm:
|
getattr(self, '_use_mcjit', False)):
|
||||||
_util.check_is_unowned(tm)
|
# force ELF generation on MCJIT on win32
|
||||||
ret = _core.LLVMEngineBuilderCreateTM(self.ptr, tm.ptr)
|
triple = get_default_triple()
|
||||||
|
tm = TargetMachine.new('%s-elf' % triple)
|
||||||
|
engine = self._ptr.create(tm._ptr)
|
||||||
else:
|
else:
|
||||||
ret = _core.LLVMEngineBuilderCreate(self.ptr)
|
engine = self._ptr.create()
|
||||||
if isinstance(ret, str):
|
ee = ExecutionEngine(engine)
|
||||||
raise llvm.LLVMException(ret)
|
ee.finalize_object() # no effect for legacy JIT
|
||||||
engine = ExecutionEngine(ret, self._module)
|
return ee
|
||||||
if tm:
|
|
||||||
tm._own(owner=llvm.DummyOwner)
|
|
||||||
return engine
|
|
||||||
|
|
||||||
def select_target(self):
|
def select_target(self, *args):
|
||||||
'''get the corresponding target machine
|
'''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)
|
return TargetMachine(ptr)
|
||||||
|
|
||||||
|
def mcjit(self, enable):
|
||||||
|
'''Enable/disable MCJIT
|
||||||
|
'''
|
||||||
|
self._ptr.setUseMCJIT(enable)
|
||||||
|
self._use_mcjit = True
|
||||||
|
return self
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Execution engine
|
# Execution engine
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class ExecutionEngine(object):
|
class ExecutionEngine(llvm.Wrapper):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(module, force_interpreter=False):
|
def new(module, force_interpreter=False):
|
||||||
|
|
@ -241,152 +185,80 @@ class ExecutionEngine(object):
|
||||||
eb.force_interpreter()
|
eb.force_interpreter()
|
||||||
return eb.create()
|
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):
|
def disable_lazy_compilation(self, disabled=True):
|
||||||
_core.LLVMExecutionEngineDisableLazyCompilation(self.ptr,
|
self._ptr.DisableLazyCompilation(disabled)
|
||||||
int(bool(disabled)))
|
|
||||||
|
|
||||||
def run_function(self, fn, args):
|
def run_function(self, fn, args):
|
||||||
core.check_is_function(fn)
|
ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args)))
|
||||||
ptrs = _unpack_generic_values(args)
|
return GenericValue(ptr)
|
||||||
gvptr = _core.LLVMRunFunction2(self.ptr, fn.ptr, ptrs)
|
|
||||||
return GenericValue(gvptr)
|
def get_pointer_to_named_function(self, name, abort=True):
|
||||||
|
return self._ptr.getPointerToNamedFunction(name, abort)
|
||||||
|
|
||||||
def get_pointer_to_function(self, fn):
|
def get_pointer_to_function(self, fn):
|
||||||
core.check_is_function(fn)
|
return self._ptr.getPointerToFunction(fn._ptr)
|
||||||
return _core.LLVMGetPointerToFunction(self.ptr,fn.ptr)
|
|
||||||
|
|
||||||
def get_pointer_to_global(self, val):
|
def get_pointer_to_global(self, val):
|
||||||
core.check_is_global_value(val)
|
return self._ptr.getPointerToGlobal(val._ptr)
|
||||||
return _core.LLVMGetPointerToGlobal(self.ptr, val.ptr)
|
|
||||||
|
|
||||||
def add_global_mapping(self, gvar, addr):
|
def add_global_mapping(self, gvar, addr):
|
||||||
assert addr >= 0, "Address cannot not be negative"
|
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):
|
def run_static_ctors(self):
|
||||||
_core.LLVMRunStaticConstructors(self.ptr)
|
self._ptr.runStaticConstructorsDestructors(False)
|
||||||
|
|
||||||
def run_static_dtors(self):
|
def run_static_dtors(self):
|
||||||
_core.LLVMRunStaticDestructors(self.ptr)
|
self._ptr.runStaticConstructorsDestructors(True)
|
||||||
|
|
||||||
def free_machine_code_for(self, fn):
|
def free_machine_code_for(self, fn):
|
||||||
core.check_is_function(fn)
|
self._ptr.freeMachineCodeForFunction(fn._ptr)
|
||||||
_core.LLVMFreeMachineCodeForFunction(self.ptr, fn.ptr)
|
|
||||||
|
|
||||||
def add_module(self, module):
|
def add_module(self, module):
|
||||||
core.check_is_module(module)
|
self._ptr.addModule(module._ptr)
|
||||||
_core.LLVMAddModule(self.ptr, module.ptr)
|
|
||||||
module._own(self)
|
|
||||||
|
|
||||||
def remove_module(self, module):
|
def remove_module(self, module):
|
||||||
core.check_is_module(module)
|
return self._ptr.removeModule(module._ptr)
|
||||||
if module.owner != self:
|
|
||||||
raise llvm.LLVMException("module is not owned by self")
|
def finalize_object(self):
|
||||||
ret = _core.LLVMRemoveModule2(self.ptr, module.ptr)
|
return self._ptr.finalizeObject()
|
||||||
if isinstance(ret, str):
|
|
||||||
raise llvm.LLVMException(ret)
|
|
||||||
return core.Module(ret)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_data(self):
|
def target_data(self):
|
||||||
td = TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr))
|
ptr = self._ptr.getDataLayout()
|
||||||
td._own(self)
|
return TargetData(ptr)
|
||||||
return td
|
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Target machine
|
# Dynamic Library
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
def print_registered_targets():
|
def dylib_add_symbol(name, ptr):
|
||||||
'''
|
api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr)
|
||||||
Note: print directly to stdout
|
|
||||||
'''
|
|
||||||
_core.LLVMPrintRegisteredTargetsForVersion()
|
|
||||||
|
|
||||||
def get_host_cpu_name():
|
def dylib_address_of_symbol(name):
|
||||||
'''return the string name of the host CPU
|
return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name)
|
||||||
'''
|
|
||||||
return _core.LLVMGetHostCPUName()
|
|
||||||
|
|
||||||
def get_default_triple():
|
def dylib_import_library(filename):
|
||||||
'''return the target triple of the host in str-rep
|
"""Permanently import a dynamic library.
|
||||||
'''
|
|
||||||
return _core.LLVMDefaultTargetTriple()
|
Returns a DynamicLibrary object
|
||||||
|
|
||||||
|
Raises RuntimeError
|
||||||
|
"""
|
||||||
|
return DynamicLibrary(filename)
|
||||||
|
|
||||||
|
|
||||||
class TargetMachine(llvm.Ownable):
|
class DynamicLibrary(object):
|
||||||
|
def __init__(self, filename):
|
||||||
@staticmethod
|
"""
|
||||||
def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT):
|
Raises RuntimeError
|
||||||
if not triple and not cpu:
|
"""
|
||||||
triple = get_default_triple()
|
self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary(
|
||||||
cpu = get_host_cpu_name()
|
filename)
|
||||||
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)
|
|
||||||
|
|
||||||
|
def get_address_of_symbol(self, symbol):
|
||||||
|
"""
|
||||||
|
Get the address of `symbol` (str) as integer
|
||||||
|
"""
|
||||||
|
return self._ptr.getAddressOfSymbol(symbol)
|
||||||
|
|
|
||||||
1361
llvm/extra.cpp
1361
llvm/extra.cpp
File diff suppressed because it is too large
Load diff
676
llvm/extra.h
676
llvm/extra.h
|
|
@ -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
79
llvm/llrt.py
Normal 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
371
llvm/llrt/llrt_x86.ll
Normal 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
371
llvm/llrt/llrt_x86_64.ll
Normal 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
|
||||||
|
}
|
||||||
|
|
@ -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
242
llvm/mc/__init__.py
Normal 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
|
||||||
362
llvm/passes.py
362
llvm/passes.py
|
|
@ -37,191 +37,180 @@ are available.
|
||||||
|
|
||||||
import llvm # top-level, for common stuff
|
import llvm # top-level, for common stuff
|
||||||
import llvm.core as core # module, function etc.
|
import llvm.core as core # module, function etc.
|
||||||
import llvm._core as _core # C wrappers
|
from llvmpy import api
|
||||||
import llvm._util as _util # Utility functions
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Pass manager builder
|
# Pass manager builder
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class PassManagerBuilder(object):
|
class PassManagerBuilder(llvm.Wrapper):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new():
|
def new():
|
||||||
return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate())
|
return PassManagerBuilder(api.llvm.PassManagerBuilder.new())
|
||||||
|
|
||||||
def __init__(self, ptr):
|
|
||||||
self.ptr = ptr
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
_core.LLVMPassManagerBuilderDispose(self.ptr)
|
|
||||||
|
|
||||||
def populate(self, pm):
|
def populate(self, pm):
|
||||||
if isinstance(pm, FunctionPassManager):
|
if isinstance(pm, FunctionPassManager):
|
||||||
return _core.LLVMPassManagerBuilderPopulateFunctionPassManager(
|
self._ptr.populateFunctionPassManager(pm._ptr)
|
||||||
self.ptr, pm.ptr)
|
|
||||||
else:
|
else:
|
||||||
return _core.LLVMPassManagerBuilderPopulateModulePassManager(
|
self._ptr.populateModulePassManager(pm._ptr)
|
||||||
self.ptr, 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):
|
@property
|
||||||
_core.LLVMPassManagerBuilderSetOptLevel(self.ptr, optlevel)
|
def loop_vectorize(self):
|
||||||
|
|
||||||
def _get_opt_level(self):
|
|
||||||
return _core.LLVMPassManagerBuilderGetOptLevel(self.ptr)
|
|
||||||
|
|
||||||
opt_level = property(_get_opt_level, _set_opt_level)
|
|
||||||
|
|
||||||
def _set_size_level(self, sizelevel):
|
|
||||||
_core.LLVMPassManagerBuilderSetSizeLevel(self.ptr, sizelevel)
|
|
||||||
|
|
||||||
def _get_size_level(self):
|
|
||||||
return _core.LLVMPassManagerBuilderGetSizeLevel(self.ptr)
|
|
||||||
|
|
||||||
size_level = property(_get_size_level, _set_size_level)
|
|
||||||
|
|
||||||
def _set_vectorize(self, enable):
|
|
||||||
_core.LLVMPassManagerBuilderSetVectorize(self.ptr, int(bool(enable)))
|
|
||||||
|
|
||||||
def _get_vectorize(self):
|
|
||||||
return bool(_core.LLVMPassManagerBuilderGetVectorize(self.ptr))
|
|
||||||
|
|
||||||
vectorize = property(_get_vectorize, _set_vectorize)
|
|
||||||
|
|
||||||
def _set_loop_vectorize(self, enable):
|
|
||||||
if llvm.version >= (3, 2):
|
|
||||||
_core.LLVMPassManagerBuilderSetLoopVectorize(self.ptr,
|
|
||||||
int(bool(enable)))
|
|
||||||
elif enable:
|
|
||||||
warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.")
|
|
||||||
|
|
||||||
def _get_loop_vectorize(self):
|
|
||||||
try:
|
try:
|
||||||
return bool(_core.LLVMPassManagerBuilderGetLoopVectorize(self.ptr))
|
return self._ptr.LoopVectorize
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return False
|
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):
|
@property
|
||||||
return _core.LLVMPassManagerBuilderSetDisableUnitAtATime(
|
def disable_unit_at_a_time(self):
|
||||||
self.ptr, disable)
|
return self._ptr.DisableUnitAtATime
|
||||||
|
|
||||||
def _get_disable_unit_at_a_time(self):
|
@disable_unit_at_a_time.setter
|
||||||
return _core.LLVMPassManagerBuilderGetDisableUnitAtATime(
|
def disable_unit_at_a_time(self, disable):
|
||||||
self.ptr)
|
self._ptr.DisableUnitAtATime = disable
|
||||||
|
|
||||||
disable_unit_at_a_time = property(_get_disable_unit_at_a_time,
|
@property
|
||||||
_set_disable_unit_at_a_time)
|
def disable_unroll_loops(self):
|
||||||
|
return self._ptr.DisableUnrollLoops
|
||||||
|
|
||||||
def _set_disable_unroll_loops(self, disable):
|
@disable_unroll_loops.setter
|
||||||
return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(
|
def disable_unroll_loops(self, disable):
|
||||||
self.ptr, disable)
|
self._ptr.DisableUnrollLoops = disable
|
||||||
|
|
||||||
def _get_disable_unroll_loops(self):
|
if llvm.version <= (3, 3):
|
||||||
return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(self.ptr)
|
@property
|
||||||
|
def disable_simplify_lib_calls(self):
|
||||||
|
return self._ptr.DisableSimplifyLibCalls
|
||||||
|
|
||||||
disable_unroll_loops = property(_get_disable_unroll_loops,
|
@disable_simplify_lib_calls.setter
|
||||||
_set_disable_unroll_loops)
|
def disable_simplify_lib_calls(self, disable):
|
||||||
|
self._ptr.DisableSimplifyLibCalls = disable
|
||||||
def _set_disable_simplify_lib_calls(self, disable):
|
|
||||||
return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(
|
|
||||||
self.ptr, disable)
|
|
||||||
|
|
||||||
def _get_disable_simplify_lib_calls(self):
|
|
||||||
return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(self.ptr)
|
|
||||||
|
|
||||||
disable_simplify_lib_calls = property(_get_disable_simplify_lib_calls,
|
|
||||||
_set_disable_simplify_lib_calls)
|
|
||||||
|
|
||||||
def use_inliner_with_threshold(self, threshold):
|
def use_inliner_with_threshold(self, threshold):
|
||||||
_core.LLVMPassManagerBuilderUseInlinerWithThreshold(self.ptr, threshold)
|
self._ptr.Inliner = api.llvm.createFunctionInliningPass(threshold)
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Pass manager
|
# Pass manager
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class PassManager(object):
|
class PassManager(llvm.Wrapper):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new():
|
def new():
|
||||||
return PassManager(_core.LLVMCreatePassManager())
|
return PassManager(api.llvm.PassManager.new())
|
||||||
|
|
||||||
def __init__(self, ptr):
|
|
||||||
self.ptr = ptr
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
_core.LLVMDisposePassManager(self.ptr)
|
|
||||||
|
|
||||||
def add(self, pass_obj):
|
def add(self, pass_obj):
|
||||||
'''Add a pass to the pass manager.
|
'''Add a pass to the pass manager.
|
||||||
|
|
||||||
pass_obj --- Either a Pass instance, a string name of a pass
|
pass_obj --- Either a Pass instance, a string name of a pass
|
||||||
'''
|
'''
|
||||||
if isinstance(pass_obj, Pass):
|
if isinstance(pass_obj, Pass):
|
||||||
_util.check_is_unowned(pass_obj)
|
self._ptr.add(pass_obj._ptr)
|
||||||
_core.LLVMAddPass(self.ptr, pass_obj.ptr)
|
|
||||||
pass_obj._own(self) # PassManager owns the pass
|
|
||||||
elif _util.isstring(pass_obj):
|
|
||||||
self._add_pass(pass_obj)
|
|
||||||
else:
|
else:
|
||||||
raise llvm.LLVMException("invalid pass_id (%s)" % pass_obj)
|
self._add_pass(str(pass_obj))
|
||||||
|
|
||||||
def _add_pass(self, pass_name):
|
def _add_pass(self, pass_name):
|
||||||
status = _core.LLVMAddPassByName(self.ptr, pass_name)
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
if not status:
|
a_pass = passreg.getPassInfo(pass_name).createPass()
|
||||||
|
if not a_pass:
|
||||||
assert pass_name not in PASSES, "Registered but not found?"
|
assert pass_name not in PASSES, "Registered but not found?"
|
||||||
raise llvm.LLVMException('Invalid pass name "%s"' % pass_name)
|
raise llvm.LLVMException('Invalid pass name "%s"' % pass_name)
|
||||||
|
self._ptr.add(a_pass)
|
||||||
|
|
||||||
def run(self, module):
|
def run(self, module):
|
||||||
core.check_is_module(module)
|
return self._ptr.run(module._ptr)
|
||||||
return _core.LLVMRunPassManager(self.ptr, module.ptr)
|
|
||||||
|
|
||||||
class FunctionPassManager(PassManager):
|
class FunctionPassManager(PassManager):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(module):
|
def new(module):
|
||||||
core.check_is_module(module)
|
ptr = api.llvm.FunctionPassManager.new(module._ptr)
|
||||||
ptr = _core.LLVMCreateFunctionPassManagerForModule(module.ptr)
|
|
||||||
return FunctionPassManager(ptr)
|
return FunctionPassManager(ptr)
|
||||||
|
|
||||||
def __init__(self, ptr):
|
def __init__(self, ptr):
|
||||||
PassManager.__init__(self, ptr)
|
PassManager.__init__(self, ptr)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
_core.LLVMInitializeFunctionPassManager(self.ptr)
|
self._ptr.doInitialization()
|
||||||
|
|
||||||
def run(self, fn):
|
def run(self, fn):
|
||||||
core.check_is_function(fn)
|
return self._ptr.run(fn._ptr)
|
||||||
return _core.LLVMRunFunctionPassManager(self.ptr, fn.ptr)
|
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
_core.LLVMFinalizeFunctionPassManager(self.ptr)
|
self._ptr.doFinalization()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Passes
|
# Passes
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class Pass(llvm.Ownable):
|
class Pass(llvm.Wrapper):
|
||||||
'''Pass Inferface
|
'''Pass Inferface
|
||||||
'''
|
'''
|
||||||
def __init__(self, ptr):
|
|
||||||
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass)
|
|
||||||
self.__name = ''
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(name):
|
def new(name):
|
||||||
'''Create a new pass by name.
|
'''Create a new pass by name.
|
||||||
|
|
||||||
Note: Not all pass has a default constructor. LLVM will kill
|
Note: Not all pass has a default constructor. LLVM will kill
|
||||||
the process if an the pass requires arguments to construct.
|
the process if an the pass requires arguments to construct.
|
||||||
The error cannot be caught.
|
The error cannot be caught.
|
||||||
'''
|
'''
|
||||||
ptr = _core.LLVMCreatePassByName(name)
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
p = Pass(ptr)
|
a_pass = passreg.getPassInfo(name).createPass()
|
||||||
|
p = Pass(a_pass)
|
||||||
p.__name = name
|
p.__name = name
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
@ -229,15 +218,17 @@ class Pass(llvm.Ownable):
|
||||||
def name(self):
|
def name(self):
|
||||||
'''The name used in PassRegistry.
|
'''The name used in PassRegistry.
|
||||||
'''
|
'''
|
||||||
return self.__name
|
try:
|
||||||
|
return self.__name
|
||||||
|
except AttributeError:
|
||||||
|
return
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return _core.LLVMGetPassName(self.ptr)
|
return self._ptr.getPassName()
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
return _core.LLVMPassDump(self.ptr)
|
return self._ptr.dump()
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Target data
|
# Target data
|
||||||
|
|
@ -247,67 +238,59 @@ class TargetData(Pass):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(strrep):
|
def new(strrep):
|
||||||
return TargetData(_core.LLVMCreateTargetData(strrep))
|
ptr = api.llvm.DataLayout.new(strrep)
|
||||||
|
return TargetData(ptr)
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
return TargetData.new(str(self))
|
return TargetData.new(str(self))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _core.LLVMTargetDataAsString(self.ptr)
|
return self._ptr.getStringRepresentation()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def byte_order(self):
|
def byte_order(self):
|
||||||
return _core.LLVMByteOrder(self.ptr)
|
if self._ptr.isLittleEndian():
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pointer_size(self):
|
def pointer_size(self):
|
||||||
return _core.LLVMPointerSize(self.ptr)
|
return self._ptr.getPointerSize()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_integer_type(self):
|
def target_integer_type(self):
|
||||||
ptr = _core.LLVMIntPtrType(self.ptr);
|
context = api.llvm.getGlobalContext()
|
||||||
return core.IntegerType(ptr, core.TYPE_INTEGER)
|
return api.llvm.IntegerType(api.llvm.Type.getInt32Ty(context))
|
||||||
|
|
||||||
def size(self, ty):
|
def size(self, ty):
|
||||||
core.check_is_type(ty)
|
return self._ptr.getTypeSizeInBits(ty._ptr)
|
||||||
return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr)
|
|
||||||
|
|
||||||
def store_size(self, ty):
|
def store_size(self, ty):
|
||||||
core.check_is_type(ty)
|
return self._ptr.getTypeStoreSize(ty._ptr)
|
||||||
return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr)
|
|
||||||
|
|
||||||
def abi_size(self, ty):
|
def abi_size(self, ty):
|
||||||
core.check_is_type(ty)
|
return self._ptr.getTypeAllocSize(ty._ptr)
|
||||||
return _core.LLVMABISizeOfType(self.ptr, ty.ptr)
|
|
||||||
|
|
||||||
def abi_alignment(self, ty):
|
def abi_alignment(self, ty):
|
||||||
core.check_is_type(ty)
|
return self._ptr.getABITypeAlignment(ty._ptr)
|
||||||
return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr)
|
|
||||||
|
|
||||||
def callframe_alignment(self, ty):
|
def callframe_alignment(self, ty):
|
||||||
core.check_is_type(ty)
|
return self._ptr.getCallFrameTypeAlignment(ty._ptr)
|
||||||
return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr)
|
|
||||||
|
|
||||||
def preferred_alignment(self, ty_or_gv):
|
def preferred_alignment(self, ty_or_gv):
|
||||||
if isinstance(ty_or_gv, core.Type):
|
if isinstance(ty_or_gv, core.Type):
|
||||||
return _core.LLVMPreferredAlignmentOfType(self.ptr,
|
return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr)
|
||||||
ty_or_gv.ptr)
|
|
||||||
elif isinstance(ty_or_gv, core.GlobalVariable):
|
elif isinstance(ty_or_gv, core.GlobalVariable):
|
||||||
return _core.LLVMPreferredAlignmentOfGlobal(self.ptr,
|
return self._ptr.getPreferredAlignment(ty_or_gv._ptr)
|
||||||
ty_or_gv.ptr)
|
|
||||||
else:
|
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):
|
def element_at_offset(self, ty, ofs):
|
||||||
core.check_is_type_struct(ty)
|
return self._ptr.getStructLayout(ty._ptr).getElementContainingOffset(ofs)
|
||||||
ofs = int(ofs) # ofs is unsigned long long
|
|
||||||
return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs)
|
|
||||||
|
|
||||||
def offset_of_element(self, ty, el):
|
def offset_of_element(self, ty, el):
|
||||||
core.check_is_type_struct(ty)
|
return self._ptr.getStructLayout(ty._ptr).getElementOffset(el)
|
||||||
el = int(el) # el should be an int
|
|
||||||
return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el)
|
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Target Library Info
|
# Target Library Info
|
||||||
|
|
@ -316,19 +299,20 @@ class TargetData(Pass):
|
||||||
class TargetLibraryInfo(Pass):
|
class TargetLibraryInfo(Pass):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(triple):
|
def new(triple):
|
||||||
ptr = _core.LLVMCreateTargetLibraryInfo(triple)
|
triple = api.llvm.Triple.new(str(triple))
|
||||||
|
ptr = api.llvm.TargetLibraryInfo.new(triple)
|
||||||
return TargetLibraryInfo(ptr)
|
return TargetLibraryInfo(ptr)
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Target Transform Info
|
# Target Transformation Info
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
class TargetTransformInfo(Pass):
|
class TargetTransformInfo(Pass):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new(targetmachine):
|
def new(targetmachine):
|
||||||
llvm.require_version_at_least(3, 2)
|
scalartti = targetmachine._ptr.getScalarTargetTransformInfo()
|
||||||
ptr = _core.LLVMCreateTargetTransformInfo(targetmachine.ptr)
|
vectortti = targetmachine._ptr.getVectorTargetTransformInfo()
|
||||||
|
ptr = api.llvm.TargetTransformInfo.new(scalartti, vectortti)
|
||||||
return TargetTransformInfo(ptr)
|
return TargetTransformInfo(ptr)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -336,21 +320,35 @@ class TargetTransformInfo(Pass):
|
||||||
# Helpers
|
# Helpers
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
|
def build_pass_managers(tm, opt=2, size=0, loop_vectorize=False,
|
||||||
inline_threshold=2000, pm=True, fpm=True, mod=None):
|
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.
|
|
||||||
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.
|
|
||||||
'''
|
'''
|
||||||
|
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:
|
if pm:
|
||||||
pm = PassManager.new()
|
pm = PassManager.new()
|
||||||
if fpm:
|
if fpm:
|
||||||
|
|
@ -363,27 +361,31 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
|
||||||
pmb.opt_level = opt
|
pmb.opt_level = opt
|
||||||
pmb.vectorize = vectorize
|
pmb.vectorize = vectorize
|
||||||
pmb.loop_vectorize = loop_vectorize
|
pmb.loop_vectorize = loop_vectorize
|
||||||
|
if llvm.version >= (3, 3):
|
||||||
|
pmb.slp_vectorize = slp_vectorize
|
||||||
if inline_threshold:
|
if inline_threshold:
|
||||||
pmb.use_inliner_with_threshold(inline_threshold)
|
pmb.use_inliner_with_threshold(inline_threshold)
|
||||||
if pm:
|
if pm:
|
||||||
pm.add(tm.target_data.clone())
|
pm.add(tm.target_data.clone())
|
||||||
pm.add(TargetLibraryInfo.new(tm.triple))
|
pm.add(TargetLibraryInfo.new(tm.triple))
|
||||||
if llvm.version >= (3, 2):
|
if llvm.version <= (3, 2):
|
||||||
pm.add(TargetTransformInfo.new(tm))
|
pm.add(TargetTransformInfo.new(tm))
|
||||||
|
else:
|
||||||
|
tm.add_analysis_passes(pm)
|
||||||
pmb.populate(pm)
|
pmb.populate(pm)
|
||||||
|
|
||||||
if fpm:
|
if fpm:
|
||||||
fpm.add(tm.target_data)
|
fpm.add(tm.target_data.clone())
|
||||||
fpm.add(TargetLibraryInfo.new(tm.triple))
|
fpm.add(TargetLibraryInfo.new(tm.triple))
|
||||||
if llvm.version >= (3, 2):
|
if llvm.version <= (3, 2):
|
||||||
fpm.add(TargetTransformInfo.new(tm))
|
fpm.add(TargetTransformInfo.new(tm))
|
||||||
|
else:
|
||||||
|
tm.add_analysis_passes(fpm)
|
||||||
pmb.populate(fpm)
|
pmb.populate(fpm)
|
||||||
fpm.initialize()
|
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm)
|
return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm)
|
||||||
|
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
# Misc.
|
# Misc.
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
@ -392,16 +394,26 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
|
||||||
PASSES = None
|
PASSES = None
|
||||||
|
|
||||||
def _dump_all_passes():
|
def _dump_all_passes():
|
||||||
passes_sep_by_line = _core.LLVMDumpPasses()
|
passreg = api.llvm.PassRegistry.getPassRegistry()
|
||||||
strip = lambda S : S.strip()
|
for name, desc in passreg.enumerate():
|
||||||
for line in passes_sep_by_line.splitlines():
|
yield name, desc
|
||||||
passarg, passname = map(strip, line.split('\t', 1))
|
|
||||||
if passarg:
|
|
||||||
yield passarg, passname
|
|
||||||
|
|
||||||
def _initialize_passes():
|
def _initialize_passes():
|
||||||
global 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())
|
PASSES = dict(_dump_all_passes())
|
||||||
|
|
||||||
# build globals
|
# build globals
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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
266
llvm/target.py
Normal 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()
|
||||||
|
|
||||||
|
|
@ -2,11 +2,11 @@ from llvm.core import *
|
||||||
|
|
||||||
class TBAABuilder(object):
|
class TBAABuilder(object):
|
||||||
'''Simplify creation of TBAA metadata.
|
'''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
|
User can create multiple TBAABuilder on a module
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, module, rootid):
|
def __init__(self, module, rootid):
|
||||||
'''
|
'''
|
||||||
module --- the module to use.
|
module --- the module to use.
|
||||||
|
|
@ -23,7 +23,7 @@ class TBAABuilder(object):
|
||||||
def get_node(self, name, parent=None, const=False):
|
def get_node(self, name, parent=None, const=False):
|
||||||
'''Returns a MetaData object representing a TBAA node.
|
'''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.
|
bind a type to a memory.
|
||||||
'''
|
'''
|
||||||
parent = parent or self.root
|
parent = parent or self.root
|
||||||
|
|
|
||||||
1217
llvm/test_llvmpy.py
1217
llvm/test_llvmpy.py
File diff suppressed because it is too large
Load diff
72
llvm/tests/__init__.py
Normal file
72
llvm/tests/__init__.py
Normal 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
78
llvm/tests/support.py
Normal 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
24
llvm/tests/test_alloca.py
Normal 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()
|
||||||
|
|
||||||
24
llvm/tests/test_arg_attr.py
Normal file
24
llvm/tests/test_arg_attr.py
Normal 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
73
llvm/tests/test_arith.py
Normal 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
58
llvm/tests/test_asm.py
Normal 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
85
llvm/tests/test_atomic.py
Normal 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
Loading…
Add table
Add a link
Reference in a new issue