Merge branch 'master' of github.com:llvmpy/llvmpy into llpython-dev
This commit is contained in:
commit
ca17b03180
57 changed files with 2235 additions and 186 deletions
|
|
@ -1,3 +1,10 @@
|
||||||
|
2013-8-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:
|
2013-03-05 0.11.1:
|
||||||
--------------------
|
--------------------
|
||||||
* fix test when cc is not available
|
* fix test when cc is not available
|
||||||
|
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
19
buildscripts/condarecipe/run_test.py
Normal file
19
buildscripts/condarecipe/run_test.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import sys
|
||||||
|
import platform
|
||||||
|
import llvm
|
||||||
|
|
||||||
|
from llvm.core import Module
|
||||||
|
from llvm.ee import EngineBuilder
|
||||||
|
m = Module.new('fjoidajfa')
|
||||||
|
eb = EngineBuilder.new(m)
|
||||||
|
target = eb.select_target()
|
||||||
|
|
||||||
|
print('target.triple=%r' % target.triple)
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
s = {'64bit': 'x86_64', '32bit': 'x86'}[platform.architecture()[0]]
|
||||||
|
assert target.triple.startswith(s + '-apple-darwin')
|
||||||
|
|
||||||
|
assert llvm.test(verbosity=2) == 0
|
||||||
|
|
||||||
|
print('llvm.__version__: %s' % llvm.__version__)
|
||||||
|
#assert llvm.__version__ == '0.12.0'
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -53,6 +53,7 @@ LLVMInterpreter
|
||||||
LLVMipa
|
LLVMipa
|
||||||
LLVMipo
|
LLVMipo
|
||||||
LLVMJIT
|
LLVMJIT
|
||||||
|
LLVMMCJIT
|
||||||
LLVMLinker
|
LLVMLinker
|
||||||
LLVMMC
|
LLVMMC
|
||||||
LLVMMCParser
|
LLVMMCParser
|
||||||
|
|
@ -71,6 +72,7 @@ LLVMX86Desc
|
||||||
LLVMX86Disassembler
|
LLVMX86Disassembler
|
||||||
LLVMX86Info
|
LLVMX86Info
|
||||||
LLVMX86Utils
|
LLVMX86Utils
|
||||||
|
LLVMDebugInfo
|
||||||
Advapi32
|
Advapi32
|
||||||
Shell32
|
Shell32
|
||||||
""".split():
|
""".split():
|
||||||
|
|
@ -106,7 +108,7 @@ def main():
|
||||||
|
|
||||||
elif option == '--includedir':
|
elif option == '--includedir':
|
||||||
incdir = join(find_llvm_prefix(), 'include')
|
incdir = join(find_llvm_prefix(), 'include')
|
||||||
ensure_file(join(incdir, 'llvm' , 'BasicBlock.h'))
|
ensure_file(join(incdir, 'llvm' , 'Linker.h'))
|
||||||
print(incdir)
|
print(incdir)
|
||||||
|
|
||||||
elif option == '--libdir':
|
elif option == '--libdir':
|
||||||
|
|
|
||||||
134
llvm/core.py
134
llvm/core.py
|
|
@ -325,11 +325,17 @@ class VisibilityEnum(Enum):
|
||||||
|
|
||||||
VisibilityEnum.declare()
|
VisibilityEnum.declare()
|
||||||
|
|
||||||
# parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h)
|
# parameter attributes
|
||||||
|
# LLVM 3.2 llvm::Attributes::AttrVal (see llvm/Attributes.h)
|
||||||
|
# LLVM 3.3 llvm::Attribute::AttrKind (see llvm/Attributes.h)
|
||||||
class AttrEnum(Enum):
|
class AttrEnum(Enum):
|
||||||
prefix = 'ATTR_'
|
prefix = 'ATTR_'
|
||||||
|
|
||||||
AttrVal = api.llvm.Attributes.AttrVal
|
if llvm.version >= (3, 3):
|
||||||
|
AttrVal = api.llvm.Attribute.AttrKind
|
||||||
|
else:
|
||||||
|
AttrVal = api.llvm.Attributes.AttrVal
|
||||||
|
|
||||||
ATTR_NONE = AttrVal.None_
|
ATTR_NONE = AttrVal.None_
|
||||||
ATTR_ZEXT = AttrVal.ZExt
|
ATTR_ZEXT = AttrVal.ZExt
|
||||||
ATTR_SEXT = AttrVal.SExt
|
ATTR_SEXT = AttrVal.SExt
|
||||||
|
|
@ -1031,6 +1037,9 @@ class Value(llvm.Wrapper):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self._ptr)
|
return str(self._ptr)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self._ptr)
|
||||||
|
|
||||||
def __eq__(self, rhs):
|
def __eq__(self, rhs):
|
||||||
if isinstance(rhs, Value):
|
if isinstance(rhs, Value):
|
||||||
return str(self) == str(rhs)
|
return str(self) == str(rhs)
|
||||||
|
|
@ -1436,29 +1445,55 @@ class Argument(Value):
|
||||||
_valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS,
|
_valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS,
|
||||||
ATTR_NO_CAPTURE, ATTR_STRUCT_RET])
|
ATTR_NO_CAPTURE, ATTR_STRUCT_RET])
|
||||||
|
|
||||||
def add_attribute(self, attr):
|
if llvm.version >= (3, 3):
|
||||||
context = api.llvm.getGlobalContext()
|
def add_attribute(self, attr):
|
||||||
attrbldr = api.llvm.AttrBuilder.new()
|
context = api.llvm.getGlobalContext()
|
||||||
attrbldr.addAttribute(attr)
|
attrbldr = api.llvm.AttrBuilder.new()
|
||||||
attrs = api.llvm.Attributes.get(context, attrbldr)
|
attrbldr.addAttribute(attr)
|
||||||
self._ptr.addAttr(attrs)
|
attrs = api.llvm.AttributeSet.get(context, 0, attrbldr)
|
||||||
if attr not in self:
|
self._ptr.addAttr(attrs)
|
||||||
raise ValueError("Attribute %s is not valid for arg %s" %
|
|
||||||
(attr, self))
|
if attr not in self:
|
||||||
|
raise ValueError("Attribute %r is not valid for arg %s" %
|
||||||
|
(attr, self))
|
||||||
|
|
||||||
def remove_attribute(self, attr):
|
def remove_attribute(self, attr):
|
||||||
context = api.llvm.getGlobalContext()
|
context = api.llvm.getGlobalContext()
|
||||||
attrbldr = api.llvm.AttrBuilder.new()
|
attrbldr = api.llvm.AttrBuilder.new()
|
||||||
attrbldr.addAttribute(attr)
|
attrbldr.addAttribute(attr)
|
||||||
attrs = api.llvm.Attributes.get(context, attrbldr)
|
attrs = api.llvm.AttributeSet.get(context, 0, attrbldr)
|
||||||
self._ptr.removeAttr(attrs)
|
self._ptr.removeAttr(attrs)
|
||||||
|
|
||||||
def _set_alignment(self, align):
|
def _set_alignment(self, align):
|
||||||
context = api.llvm.getGlobalContext()
|
context = api.llvm.getGlobalContext()
|
||||||
attrbldr = api.llvm.AttrBuilder.new()
|
attrbldr = api.llvm.AttrBuilder.new()
|
||||||
attrbldr.addAlignmentAttr(align)
|
attrbldr.addAlignmentAttr(align)
|
||||||
attrs = api.llvm.Attributes.get(context, attrbldr)
|
attrs = api.llvm.AttributeSet.get(context, 0, attrbldr)
|
||||||
self._ptr.addAttr(attrs)
|
self._ptr.addAttr(attrs)
|
||||||
|
else:
|
||||||
|
def add_attribute(self, attr):
|
||||||
|
context = api.llvm.getGlobalContext()
|
||||||
|
attrbldr = api.llvm.AttrBuilder.new()
|
||||||
|
attrbldr.addAttribute(attr)
|
||||||
|
attrs = api.llvm.Attributes.get(context, attrbldr)
|
||||||
|
self._ptr.addAttr(attrs)
|
||||||
|
if attr not in self:
|
||||||
|
raise ValueError("Attribute %r is not valid for arg %s" %
|
||||||
|
(attr, self))
|
||||||
|
|
||||||
|
def remove_attribute(self, attr):
|
||||||
|
context = api.llvm.getGlobalContext()
|
||||||
|
attrbldr = api.llvm.AttrBuilder.new()
|
||||||
|
attrbldr.addAttribute(attr)
|
||||||
|
attrs = api.llvm.Attributes.get(context, attrbldr)
|
||||||
|
self._ptr.removeAttr(attrs)
|
||||||
|
|
||||||
|
def _set_alignment(self, align):
|
||||||
|
context = api.llvm.getGlobalContext()
|
||||||
|
attrbldr = api.llvm.AttrBuilder.new()
|
||||||
|
attrbldr.addAlignmentAttr(align)
|
||||||
|
attrs = api.llvm.Attributes.get(context, attrbldr)
|
||||||
|
self._ptr.addAttr(attrs)
|
||||||
|
|
||||||
def _get_alignment(self):
|
def _get_alignment(self):
|
||||||
return self._ptr.getParamAlignment()
|
return self._ptr.getParamAlignment()
|
||||||
|
|
@ -1816,6 +1851,9 @@ class Instruction(User):
|
||||||
def erase_from_parent(self):
|
def erase_from_parent(self):
|
||||||
return self._ptr.eraseFromParent()
|
return self._ptr.eraseFromParent()
|
||||||
|
|
||||||
|
def replace_all_uses_with(self, inst):
|
||||||
|
self._ptr.replaceAllUsesWith(inst)
|
||||||
|
|
||||||
|
|
||||||
class CallOrInvokeInstruction(Instruction):
|
class CallOrInvokeInstruction(Instruction):
|
||||||
_type_ = api.llvm.CallInst, api.llvm.InvokeInst
|
_type_ = api.llvm.CallInst, api.llvm.InvokeInst
|
||||||
|
|
@ -2092,29 +2130,34 @@ class Builder(llvm.Wrapper):
|
||||||
|
|
||||||
# arithmethic, bitwise and logical
|
# arithmethic, bitwise and logical
|
||||||
|
|
||||||
def add(self, lhs, rhs, name=""):
|
def add(self, lhs, rhs, name="", nuw=False, nsw=False):
|
||||||
return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name,
|
||||||
|
nuw, nsw))
|
||||||
|
|
||||||
def fadd(self, lhs, rhs, name=""):
|
def fadd(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
||||||
def sub(self, lhs, rhs, name=""):
|
def sub(self, lhs, rhs, name="", nuw=False, nsw=False):
|
||||||
return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name,
|
||||||
|
nuw, nsw))
|
||||||
|
|
||||||
def fsub(self, lhs, rhs, name=""):
|
def fsub(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
||||||
def mul(self, lhs, rhs, name=""):
|
def mul(self, lhs, rhs, name="", nuw=False, nsw=False):
|
||||||
return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name,
|
||||||
|
nuw, nsw))
|
||||||
|
|
||||||
def fmul(self, lhs, rhs, name=""):
|
def fmul(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
||||||
def udiv(self, lhs, rhs, name=""):
|
def udiv(self, lhs, rhs, name="", exact=False):
|
||||||
return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name,
|
||||||
|
exact))
|
||||||
|
|
||||||
def sdiv(self, lhs, rhs, name=""):
|
def sdiv(self, lhs, rhs, name="", exact=False):
|
||||||
return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name,
|
||||||
|
exact))
|
||||||
|
|
||||||
def fdiv(self, lhs, rhs, name=""):
|
def fdiv(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
@ -2128,14 +2171,17 @@ class Builder(llvm.Wrapper):
|
||||||
def frem(self, lhs, rhs, name=""):
|
def frem(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
||||||
def shl(self, lhs, rhs, name=""):
|
def shl(self, lhs, rhs, name="", nuw=False, nsw=False):
|
||||||
return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name,
|
||||||
|
nuw, nsw))
|
||||||
|
|
||||||
def lshr(self, lhs, rhs, name=""):
|
def lshr(self, lhs, rhs, name="", exact=False):
|
||||||
return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name,
|
||||||
|
exact))
|
||||||
|
|
||||||
def ashr(self, lhs, rhs, name=""):
|
def ashr(self, lhs, rhs, name="", exact=False):
|
||||||
return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name,
|
||||||
|
exact))
|
||||||
|
|
||||||
def and_(self, lhs, rhs, name=""):
|
def and_(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
@ -2146,8 +2192,8 @@ class Builder(llvm.Wrapper):
|
||||||
def xor(self, lhs, rhs, name=""):
|
def xor(self, lhs, rhs, name=""):
|
||||||
return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name))
|
return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name))
|
||||||
|
|
||||||
def neg(self, val, name=""):
|
def neg(self, val, name="", nuw=False, nsw=False):
|
||||||
return _make_value(self._ptr.CreateNeg(val._ptr, name))
|
return _make_value(self._ptr.CreateNeg(val._ptr, name, nuw, nsw))
|
||||||
|
|
||||||
def not_(self, val, name=""):
|
def not_(self, val, name=""):
|
||||||
return _make_value(self._ptr.CreateNot(val._ptr, name))
|
return _make_value(self._ptr.CreateNot(val._ptr, name))
|
||||||
|
|
@ -2422,4 +2468,8 @@ if api.llvm.InitializeNativeTargetAsmPrinter():
|
||||||
# should this be an optional feature?
|
# should this be an optional feature?
|
||||||
# should user trigger the initialization?
|
# should user trigger the initialization?
|
||||||
raise llvm.LLVMException("No native asm printer!?")
|
raise llvm.LLVMException("No native asm printer!?")
|
||||||
|
if api.llvm.InitializeNativeTargetAsmParser():
|
||||||
|
# required by MCJIT?
|
||||||
|
# should this be an optional feature?
|
||||||
|
# should user trigger the initialization?
|
||||||
|
raise llvm.LLVMException("No native asm parser!?")
|
||||||
|
|
|
||||||
33
llvm/ee.py
33
llvm/ee.py
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
"Execution Engine and related classes."
|
"Execution Engine and related classes."
|
||||||
|
|
||||||
|
import sys
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
|
|
@ -150,9 +151,17 @@ class EngineBuilder(llvm.Wrapper):
|
||||||
'''
|
'''
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
engine = self._ptr.create(tm._ptr)
|
engine = self._ptr.create(tm._ptr)
|
||||||
|
elif (sys.platform.startswith('win32') and
|
||||||
|
getattr(self, '_use_mcjit', False)):
|
||||||
|
# force ELF generation on MCJIT on win32
|
||||||
|
triple = get_default_triple()
|
||||||
|
tm = TargetMachine.new('%s-elf' % triple)
|
||||||
|
engine = self._ptr.create(tm._ptr)
|
||||||
else:
|
else:
|
||||||
engine = self._ptr.create()
|
engine = self._ptr.create()
|
||||||
return ExecutionEngine(engine)
|
ee = ExecutionEngine(engine)
|
||||||
|
ee.finalize_object() # no effect for legacy JIT
|
||||||
|
return ee
|
||||||
|
|
||||||
def select_target(self, *args):
|
def select_target(self, *args):
|
||||||
'''get the corresponding target machine
|
'''get the corresponding target machine
|
||||||
|
|
@ -171,6 +180,7 @@ class EngineBuilder(llvm.Wrapper):
|
||||||
'''Enable/disable MCJIT
|
'''Enable/disable MCJIT
|
||||||
'''
|
'''
|
||||||
self._ptr.setUseMCJIT(enable)
|
self._ptr.setUseMCJIT(enable)
|
||||||
|
self._use_mcjit = True
|
||||||
return self
|
return self
|
||||||
|
|
||||||
#===----------------------------------------------------------------------===
|
#===----------------------------------------------------------------------===
|
||||||
|
|
@ -193,6 +203,9 @@ class ExecutionEngine(llvm.Wrapper):
|
||||||
ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args)))
|
ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args)))
|
||||||
return GenericValue(ptr)
|
return GenericValue(ptr)
|
||||||
|
|
||||||
|
def get_pointer_to_named_function(self, name, abort=True):
|
||||||
|
return self._ptr.getPointerToNamedFunction(name, abort)
|
||||||
|
|
||||||
def get_pointer_to_function(self, fn):
|
def get_pointer_to_function(self, fn):
|
||||||
return self._ptr.getPointerToFunction(fn._ptr)
|
return self._ptr.getPointerToFunction(fn._ptr)
|
||||||
|
|
||||||
|
|
@ -218,6 +231,9 @@ class ExecutionEngine(llvm.Wrapper):
|
||||||
def remove_module(self, module):
|
def remove_module(self, module):
|
||||||
return self._ptr.removeModule(module._ptr)
|
return self._ptr.removeModule(module._ptr)
|
||||||
|
|
||||||
|
def finalize_object(self):
|
||||||
|
return self._ptr.finalizeObject()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_data(self):
|
def target_data(self):
|
||||||
ptr = self._ptr.getDataLayout()
|
ptr = self._ptr.getDataLayout()
|
||||||
|
|
@ -232,7 +248,7 @@ def initialize_target(target, noraise=False):
|
||||||
It is safe to initialize the same target multiple times.
|
It is safe to initialize the same target multiple times.
|
||||||
"""
|
"""
|
||||||
prefix = 'LLVMInitialize'
|
prefix = 'LLVMInitialize'
|
||||||
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter']
|
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser']
|
||||||
try:
|
try:
|
||||||
for postfix in postfixes:
|
for postfix in postfixes:
|
||||||
getattr(api, '%s%s%s' % (prefix, target, postfix))()
|
getattr(api, '%s%s%s' % (prefix, target, postfix))()
|
||||||
|
|
@ -274,7 +290,7 @@ class TargetMachine(llvm.Wrapper):
|
||||||
with contextlib.closing(BytesIO()) as error:
|
with contextlib.closing(BytesIO()) as error:
|
||||||
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
|
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
|
||||||
if not target:
|
if not target:
|
||||||
raise llvm.LLVMException(error)
|
raise llvm.LLVMException(error.getvalue())
|
||||||
if not target.hasTargetMachine():
|
if not target.hasTargetMachine():
|
||||||
raise llvm.LLVMException(target, "No target machine.")
|
raise llvm.LLVMException(target, "No target machine.")
|
||||||
target_options = api.llvm.TargetOptions.new()
|
target_options = api.llvm.TargetOptions.new()
|
||||||
|
|
@ -366,3 +382,14 @@ class TargetMachine(llvm.Wrapper):
|
||||||
def feature_string(self):
|
def feature_string(self):
|
||||||
return self._ptr.getTargetFeatureString()
|
return self._ptr.getTargetFeatureString()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
# Dynamic Library
|
||||||
|
#===----------------------------------------------------------------------===
|
||||||
|
|
||||||
|
def dylib_add_symbol(name, ptr):
|
||||||
|
api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr)
|
||||||
|
|
||||||
|
def dylib_address_of_symbol(name):
|
||||||
|
return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name)
|
||||||
|
|
|
||||||
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
|
||||||
|
}
|
||||||
|
|
@ -70,13 +70,24 @@ class PassManagerBuilder(llvm.Wrapper):
|
||||||
def size_level(self, sizelevel):
|
def size_level(self, sizelevel):
|
||||||
self._ptr.SizeLevel = sizelevel
|
self._ptr.SizeLevel = sizelevel
|
||||||
|
|
||||||
@property
|
if llvm.version >= (3, 3):
|
||||||
def vectorize(self):
|
@property
|
||||||
return self._ptr.Vectorize
|
def bbvectorize(self):
|
||||||
|
return self._ptr.BBVectorize
|
||||||
|
|
||||||
@vectorize.setter
|
@bbvectorize.setter
|
||||||
def vectorize(self, enable):
|
def bbvectorize(self, enable):
|
||||||
self._ptr.Vectorize = enable
|
self._ptr.BBVectorize = enable
|
||||||
|
|
||||||
|
vectorize = bbvectorize
|
||||||
|
else:
|
||||||
|
@property
|
||||||
|
def vectorize(self):
|
||||||
|
return self._ptr.Vectorize
|
||||||
|
|
||||||
|
@vectorize.setter
|
||||||
|
def vectorize(self, enable):
|
||||||
|
self._ptr.Vectorize = enable
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -331,14 +342,14 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
|
||||||
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))
|
||||||
pmb.populate(pm)
|
pmb.populate(pm)
|
||||||
|
|
||||||
if fpm:
|
if fpm:
|
||||||
fpm.add(tm.target_data.clone())
|
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))
|
||||||
pmb.populate(fpm)
|
pmb.populate(fpm)
|
||||||
fpm.initialize()
|
fpm.initialize()
|
||||||
|
|
|
||||||
|
|
@ -1353,6 +1353,235 @@ class TestCmp(TestCase):
|
||||||
tests.append(TestCmp)
|
tests.append(TestCmp)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TestMCJIT(TestCase):
|
||||||
|
def test_mcjit(self):
|
||||||
|
m = Module.new('oidfjs')
|
||||||
|
fnty = Type.function(Type.int(), [Type.int(), Type.int()])
|
||||||
|
func = m.add_function(fnty, 'foo')
|
||||||
|
bb = func.append_basic_block('')
|
||||||
|
bldr = Builder.new(bb)
|
||||||
|
bldr.ret(bldr.add(*func.args))
|
||||||
|
|
||||||
|
func.verify()
|
||||||
|
|
||||||
|
engine = EngineBuilder.new(m).mcjit(True).create()
|
||||||
|
ptr = engine.get_pointer_to_function(func)
|
||||||
|
|
||||||
|
from ctypes import c_int, CFUNCTYPE
|
||||||
|
callee = CFUNCTYPE(c_int, c_int, c_int)(ptr)
|
||||||
|
self.assertEqual(321 + 123, callee(321, 123))
|
||||||
|
|
||||||
|
def test_multi_module_linking(self):
|
||||||
|
# generate external library module
|
||||||
|
m = Module.new('external-library-module')
|
||||||
|
fnty = Type.function(Type.int(), [Type.int(), Type.int()])
|
||||||
|
libfname = 'myadd'
|
||||||
|
func = m.add_function(fnty, libfname)
|
||||||
|
bb = func.append_basic_block('')
|
||||||
|
bldr = Builder.new(bb)
|
||||||
|
bldr.ret(bldr.add(*func.args))
|
||||||
|
func.verify()
|
||||||
|
|
||||||
|
# JIT the lib module and bind dynamic symbol
|
||||||
|
libengine = EngineBuilder.new(m).mcjit(True).create()
|
||||||
|
myadd_ptr = libengine.get_pointer_to_function(func)
|
||||||
|
le.dylib_add_symbol(libfname, myadd_ptr)
|
||||||
|
|
||||||
|
# reference external library
|
||||||
|
m = Module.new('user')
|
||||||
|
fnty = Type.function(Type.int(), [Type.int(), Type.int()])
|
||||||
|
func = m.add_function(fnty, 'foo')
|
||||||
|
bb = func.append_basic_block('')
|
||||||
|
bldr = Builder.new(bb)
|
||||||
|
extadd = m.get_or_insert_function(fnty, name=libfname)
|
||||||
|
bldr.ret(bldr.call(extadd, func.args))
|
||||||
|
func.verify()
|
||||||
|
|
||||||
|
# JIT the user module
|
||||||
|
engine = EngineBuilder.new(m).mcjit(True).create()
|
||||||
|
ptr = engine.get_pointer_to_function(func)
|
||||||
|
self.assertEqual(myadd_ptr,
|
||||||
|
engine.get_pointer_to_named_function(libfname))
|
||||||
|
|
||||||
|
from ctypes import c_int, CFUNCTYPE
|
||||||
|
callee = CFUNCTYPE(c_int, c_int, c_int)(ptr)
|
||||||
|
self.assertEqual(321 + 123, callee(321, 123))
|
||||||
|
|
||||||
|
|
||||||
|
if (llvm.version >= (3, 3) and
|
||||||
|
not (sys.platform.startswith('win32') and BITS == 64)):
|
||||||
|
# MCJIT broken in 3.2, the test will segfault in OSX?
|
||||||
|
# Compatbility problem on windows 7 64-bit?
|
||||||
|
tests.append(TestMCJIT)
|
||||||
|
|
||||||
|
|
||||||
|
class TestLLRT(TestCase):
|
||||||
|
def test_llrt_divmod(self):
|
||||||
|
from llvm import llrt
|
||||||
|
m = lc.Module.new('testllrt')
|
||||||
|
longlong = lc.Type.int(64)
|
||||||
|
lfunc = m.add_function(lc.Type.function(longlong, [longlong, longlong]), 'foo')
|
||||||
|
bldr = lc.Builder.new(lfunc.append_basic_block(''))
|
||||||
|
bldr.ret(bldr.udiv(*lfunc.args))
|
||||||
|
|
||||||
|
llrt.replace_divmod64(lfunc)
|
||||||
|
|
||||||
|
rt = llrt.LLRT()
|
||||||
|
rt.install_symbols()
|
||||||
|
|
||||||
|
engine = le.EngineBuilder.new(m).create()
|
||||||
|
pointer = engine.get_pointer_to_function(lfunc)
|
||||||
|
|
||||||
|
from ctypes import CFUNCTYPE, c_uint64, c_int64
|
||||||
|
func = CFUNCTYPE(c_uint64, c_uint64, c_uint64)(pointer)
|
||||||
|
a, b = 98342, 2231
|
||||||
|
self.assertEqual(func(98342, 2231), 98342 // 2231)
|
||||||
|
|
||||||
|
rt.uninstall_symbols()
|
||||||
|
|
||||||
|
tests.append(TestLLRT)
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
|
def test_div(self):
|
||||||
|
if BITS == 32:
|
||||||
|
print('skipped test for div')
|
||||||
|
print('known failure due to unresolved external symbol __udivdi3')
|
||||||
|
return
|
||||||
|
self.template('udiv', None) # 'fdiv')
|
||||||
|
|
||||||
|
def test_rem(self):
|
||||||
|
if BITS == 32:
|
||||||
|
print('skipped test for rem')
|
||||||
|
print('known failure due to unresolved external symbol __umoddi3')
|
||||||
|
return
|
||||||
|
self.template('urem', None) # 'frem')
|
||||||
|
|
||||||
|
if llvm.version >= (3, 3):
|
||||||
|
# MCJIT is broken in 3.2
|
||||||
|
tests.append(TestArith)
|
||||||
|
|
||||||
|
class TestNUWNSW(TestCase):
|
||||||
|
def make_module(self):
|
||||||
|
mod = Module.new('asdfa')
|
||||||
|
fnty = Type.function(Type.void(), [Type.int()] * 2)
|
||||||
|
func = mod.add_function(fnty, 'foo')
|
||||||
|
bldr = Builder.new(func.append_basic_block(''))
|
||||||
|
return mod, func, bldr
|
||||||
|
|
||||||
|
def has_nsw(self, inst, op):
|
||||||
|
self.assertTrue(('%s nsw' % op) in str(inst), "NSW flag does not work")
|
||||||
|
|
||||||
|
def has_nuw(self, inst, op):
|
||||||
|
self.assertTrue(('%s nuw' % op) in str(inst), "NUW flag does not work")
|
||||||
|
|
||||||
|
def _test_template(self, opf, opname):
|
||||||
|
mod, func, bldr = self.make_module()
|
||||||
|
a, b = func.args
|
||||||
|
self.has_nsw(opf(bldr, a, b, nsw=True), opname)
|
||||||
|
self.has_nuw(opf(bldr, a, b, nuw=True), opname)
|
||||||
|
|
||||||
|
def test_add_nuw_nsw(self):
|
||||||
|
self._test_template(Builder.add, 'add')
|
||||||
|
|
||||||
|
def test_sub_nuw_nsw(self):
|
||||||
|
self._test_template(Builder.sub, 'sub')
|
||||||
|
|
||||||
|
def test_mul_nuw_nsw(self):
|
||||||
|
self._test_template(Builder.mul, 'mul')
|
||||||
|
|
||||||
|
def test_shl_nuw_nsw(self):
|
||||||
|
self._test_template(Builder.shl, 'shl')
|
||||||
|
|
||||||
|
def test_neg_nuw_nsw(self):
|
||||||
|
mod, func, bldr = self.make_module()
|
||||||
|
a, b = func.args
|
||||||
|
self.has_nsw(bldr.neg(a, nsw=True), 'sub')
|
||||||
|
self.has_nuw(bldr.neg(a, nuw=True), 'sub')
|
||||||
|
|
||||||
|
|
||||||
|
tests.append(TestNUWNSW)
|
||||||
|
|
||||||
|
|
||||||
|
class TestExact(TestCase):
|
||||||
|
def make_module(self):
|
||||||
|
mod = Module.new('asdfa')
|
||||||
|
fnty = Type.function(Type.void(), [Type.int()] * 2)
|
||||||
|
func = mod.add_function(fnty, 'foo')
|
||||||
|
bldr = Builder.new(func.append_basic_block(''))
|
||||||
|
return mod, func, bldr
|
||||||
|
|
||||||
|
def has_exact(self, inst, op):
|
||||||
|
self.assertTrue(('%s exact' % op) in str(inst), "exact flag does not work")
|
||||||
|
|
||||||
|
def _test_template(self, opf, opname):
|
||||||
|
mod, func, bldr = self.make_module()
|
||||||
|
a, b = func.args
|
||||||
|
self.has_exact(opf(bldr, a, b, exact=True), opname)
|
||||||
|
|
||||||
|
def test_udiv_exact(self):
|
||||||
|
self._test_template(Builder.udiv, 'udiv')
|
||||||
|
|
||||||
|
def test_sdiv_exact(self):
|
||||||
|
self._test_template(Builder.sdiv, 'sdiv')
|
||||||
|
|
||||||
|
def test_lshr_exact(self):
|
||||||
|
self._test_template(Builder.lshr, 'lshr')
|
||||||
|
|
||||||
|
def test_ashr_exact(self):
|
||||||
|
self._test_template(Builder.ashr, 'ashr')
|
||||||
|
|
||||||
|
tests.append(TestExact)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def run(verbosity=1):
|
def run(verbosity=1):
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ def detect_osx_like():
|
||||||
stdout=subprocess.PIPE)
|
stdout=subprocess.PIPE)
|
||||||
except OSError:
|
except OSError:
|
||||||
return False
|
return False
|
||||||
|
features = info.stdout.read().decode('UTF8')
|
||||||
features = info.stdout.read()
|
|
||||||
features = features.split()
|
features = features.split()
|
||||||
return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features
|
return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
# README
|
|
||||||
|
|
||||||
This is a reimplementation of the LLVM binding, aiming to provide a more familiar interface to the C++ API whenever possible.
|
|
||||||
|
|
||||||
The implementation uses a custom DSL in python to describe the interface (under binding directory). The DSL serves as input to *gen.py* for generation of the .cpp and .py files for the actual binding.
|
|
||||||
151
llvmpy/README.md
Normal file
151
llvmpy/README.md
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
# README
|
||||||
|
|
||||||
|
This is a reimplementation of the LLVM binding, aiming to provide a more
|
||||||
|
familiar interface to the C++ API whenever possible.
|
||||||
|
|
||||||
|
The implementation uses a custom DSL in python to describe the interface.
|
||||||
|
The DSL serves as input to *gen/gen.py* for generation of the .cpp and .py files
|
||||||
|
for the actual binding.
|
||||||
|
|
||||||
|
# How to Add New Class
|
||||||
|
|
||||||
|
Let's use the `llvm::Module` as an example because it should be one of the most
|
||||||
|
familiar class in LLVM.
|
||||||
|
|
||||||
|
Reference code in https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Module.py
|
||||||
|
and see LLVM documentation at http://llvm.org/docs/doxygen/html/classllvm_1_1Module.html
|
||||||
|
|
||||||
|
1) Import binding helpers
|
||||||
|
|
||||||
|
```python
|
||||||
|
from binding import *
|
||||||
|
# Yes, it is bad practice to import star.
|
||||||
|
# I will fix it one day.
|
||||||
|
```
|
||||||
|
|
||||||
|
2) Import LLVM namespace
|
||||||
|
|
||||||
|
```python
|
||||||
|
from .namespace import llvm
|
||||||
|
```
|
||||||
|
|
||||||
|
3) Declare the class
|
||||||
|
|
||||||
|
```python
|
||||||
|
Module = llvm.Class()
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Import all the dependencies for the definition
|
||||||
|
|
||||||
|
5) Define the class
|
||||||
|
|
||||||
|
```python
|
||||||
|
@Module
|
||||||
|
class Module:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inside the definition...
|
||||||
|
|
||||||
|
5.1) Use the ``_include_`` attribute to add include files.
|
||||||
|
|
||||||
|
5.2) Use ``Enum`` to create an enumerator type.
|
||||||
|
|
||||||
|
5.3) Make constructor
|
||||||
|
|
||||||
|
Not every class needs to have a binding for the constructor.
|
||||||
|
Only add things that will be used.
|
||||||
|
|
||||||
|
```python
|
||||||
|
new = Constructor(cast(str, StringRef), ref(LLVMContext))
|
||||||
|
```
|
||||||
|
|
||||||
|
The constructor must be named as "new".
|
||||||
|
|
||||||
|
The args to ``Constructor`` are parameters of the signature.
|
||||||
|
The first parameter means cast Python string to a StringRef.
|
||||||
|
The second parameter means pass LLVMContext object as a value reference.
|
||||||
|
|
||||||
|
5.4) Make destructor
|
||||||
|
|
||||||
|
Not every class needs to have a binding for the destructor.
|
||||||
|
Only add things that will be used.
|
||||||
|
If it is always owned by another object, it usually does not need to have one.
|
||||||
|
|
||||||
|
```python
|
||||||
|
delete = Destructor()
|
||||||
|
```
|
||||||
|
|
||||||
|
The destructor must be named as "delete".
|
||||||
|
|
||||||
|
5.5) Add Simple Methods
|
||||||
|
|
||||||
|
```python
|
||||||
|
getFunction = Method(ptr(Function), cast(str, StringRef))
|
||||||
|
```
|
||||||
|
|
||||||
|
The first arg is the return type: a ponter to Function.
|
||||||
|
The rest of the args are for the parameters.
|
||||||
|
|
||||||
|
Note: ``cast(fromtype, totype)`` can be used as return-type as well.
|
||||||
|
In that case, the ``fromtype`` will usually refer to a LLVM object
|
||||||
|
and the ``totype`` will refer to the Python object.
|
||||||
|
|
||||||
|
5.6) Add custom methods defined in C++
|
||||||
|
|
||||||
|
The ``list_functions`` is created as a ``CustomMethod``.
|
||||||
|
|
||||||
|
```python
|
||||||
|
list_functions = CustomMethod('Module_list_functions', PyObjectPtr)
|
||||||
|
```
|
||||||
|
|
||||||
|
The first arg is the name that appears in C++.
|
||||||
|
The second argument is the return-type.
|
||||||
|
The rest of the arguments are parameters.
|
||||||
|
|
||||||
|
The definition of ``Module_list_functions`` is located in
|
||||||
|
"include/llvm_binding/extra.h".
|
||||||
|
|
||||||
|
5.7) Add custom python method
|
||||||
|
|
||||||
|
One can also add custom methods in Python, e.g. ``__str__``.
|
||||||
|
|
||||||
|
```python
|
||||||
|
@CustomPythonMethod
|
||||||
|
def __str__(self):
|
||||||
|
from llvmpy import extra
|
||||||
|
os = extra.make_raw_ostream_for_printing()
|
||||||
|
self.print_(os, None)
|
||||||
|
return os.str()
|
||||||
|
```
|
||||||
|
|
||||||
|
The body of ``__str__`` is directly copied to the Python output file.
|
||||||
|
Thus, it can't reference to anything in current file scope.
|
||||||
|
|
||||||
|
# Static Methods
|
||||||
|
|
||||||
|
``StaticMethod`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/PassRegistry.py
|
||||||
|
|
||||||
|
``CustomStaticMethod`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Support/TargetRegistry.py
|
||||||
|
|
||||||
|
|
||||||
|
# Namespace
|
||||||
|
|
||||||
|
``Namespace`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Support/CodeGen.py
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
``Function`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Assembly/Parser.py
|
||||||
|
|
||||||
|
``CustomFunction`` https://github.com/llvmpy/llvmpy/blob/master/llvmpy/src/Bitcode/ReaderWriter.py
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Other Things from the binding.py
|
||||||
|
|
||||||
|
https://github.com/llvmpy/llvmpy/blob/master/llvmpy/gen/binding.py
|
||||||
|
|
||||||
|
The list of C++ types: https://github.com/llvmpy/llvmpy/blob/master/llvmpy/gen/binding.py#L218
|
||||||
|
|
||||||
|
|
@ -3,11 +3,13 @@ from collections import defaultdict
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
NO_DEBUG = False
|
||||||
def silent_logger():
|
def silent_logger():
|
||||||
'''
|
'''
|
||||||
Silent logger for unless we have a error message.
|
Silent logger for unless we have a error message.
|
||||||
'''
|
'''
|
||||||
logger.setLevel(logging.ERROR)
|
logger.setLevel(logging.ERROR)
|
||||||
|
NO_DEBUG = True
|
||||||
|
|
||||||
# comment out the line below to re-enable logging at DEBUG level.
|
# comment out the line below to re-enable logging at DEBUG level.
|
||||||
silent_logger()
|
silent_logger()
|
||||||
|
|
@ -35,7 +37,11 @@ def _capsule_weakref_dtor(item):
|
||||||
if refct == 0:
|
if refct == 0:
|
||||||
dtor = _addr2dtor.pop((name, addr), None)
|
dtor = _addr2dtor.pop((name, addr), None)
|
||||||
if dtor is not None:
|
if dtor is not None:
|
||||||
logger.debug('Destroy %s %s', name, hex(addr))
|
if not NO_DEBUG:
|
||||||
|
# Some globals in logger could be removed by python GC
|
||||||
|
# at interpreter teardown.
|
||||||
|
# That can cause exception raised and ignored message.
|
||||||
|
logger.debug('Destroy %s %s', name, hex(addr))
|
||||||
dtor(item.capsule)
|
dtor(item.capsule)
|
||||||
|
|
||||||
class Capsule(object):
|
class Capsule(object):
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,8 @@ class Class(SubModule, _Type):
|
||||||
def __call__(self, defn):
|
def __call__(self, defn):
|
||||||
assert not self._is_defined
|
assert not self._is_defined
|
||||||
# process the definition in "defn"
|
# process the definition in "defn"
|
||||||
self.name = defn.__name__
|
self.name = getattr(defn, '_name_', defn.__name__)
|
||||||
|
|
||||||
for k, v in defn.__dict__.items():
|
for k, v in defn.__dict__.items():
|
||||||
if isinstance(v, Method):
|
if isinstance(v, Method):
|
||||||
self.methods.append(v)
|
self.methods.append(v)
|
||||||
|
|
@ -332,7 +333,7 @@ class Class(SubModule, _Type):
|
||||||
writer.die_if_false(raw, verbose=name)
|
writer.die_if_false(raw, verbose=name)
|
||||||
ptrty = ptr(self).fullname
|
ptrty = ptr(self).fullname
|
||||||
ty = self.fullname
|
ty = self.fullname
|
||||||
fmt = 'typecast< %(ty)s >::from(%(raw)s)'
|
fmt = 'unwrap_as<%(ty)s, %(name)s >::from(%(raw)s)'
|
||||||
casted = writer.declare(ptrty, fmt % locals())
|
casted = writer.declare(ptrty, fmt % locals())
|
||||||
writer.die_if_false(casted)
|
writer.die_if_false(casted)
|
||||||
return casted
|
return casted
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,8 @@ class CppCodeWriter(CodeWriterBase):
|
||||||
|
|
||||||
def pycapsule_new(self, ptr, name, clsname):
|
def pycapsule_new(self, ptr, name, clsname):
|
||||||
name_soften = mangle(name)
|
name_soften = mangle(name)
|
||||||
ret = self.call('pycapsule_new', 'PyObject*', ptr, quote(name),
|
cast_to_base = 'cast_to_base<%s >::from(%s)' % (name, ptr)
|
||||||
|
ret = self.call('pycapsule_new', 'PyObject*', cast_to_base, quote(name),
|
||||||
quote(clsname))
|
quote(clsname))
|
||||||
with self.block('if (!%(ret)s)' % locals()):
|
with self.block('if (!%(ret)s)' % locals()):
|
||||||
self.return_null()
|
self.return_null()
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,7 @@ template<class Td>
|
||||||
struct typecast {
|
struct typecast {
|
||||||
template<class Ts> static
|
template<class Ts> static
|
||||||
Td* from(Ts* src) {
|
Td* from(Ts* src) {
|
||||||
|
// check why this is only used in Python3
|
||||||
return llvm::dyn_cast<Td>(src);
|
return llvm::dyn_cast<Td>(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,3 +266,24 @@ struct typecast {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class Td, class Tbase>
|
||||||
|
struct unwrap_as {
|
||||||
|
static
|
||||||
|
Td* from(void* src) {
|
||||||
|
Tbase* base = static_cast<Tbase*>(src);
|
||||||
|
return static_cast<Td*>(base);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Td>
|
||||||
|
struct cast_to_base {
|
||||||
|
template<class Ts> static
|
||||||
|
Td* from(Ts* src){
|
||||||
|
return static_cast<Td*>(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Ts> static
|
||||||
|
const Td* from(const Ts* src){
|
||||||
|
return static_cast<const Td*>(src);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,22 @@
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <llvm/ADT/SmallVector.h>
|
#include <llvm/ADT/SmallVector.h>
|
||||||
#include <llvm/Value.h>
|
#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 3
|
||||||
#include <llvm/DerivedTypes.h>
|
#include <llvm/IR/Value.h>
|
||||||
#include <llvm/Function.h>
|
#include <llvm/IR/DerivedTypes.h>
|
||||||
|
#include <llvm/IR/Function.h>
|
||||||
|
#include <llvm/IR/Module.h>
|
||||||
|
#include <llvm/IR/Constants.h>
|
||||||
|
#include <llvm/IR/Intrinsics.h>
|
||||||
|
#include <llvm/IR/IRBuilder.h>
|
||||||
|
#else
|
||||||
|
#include <llvm/Value.h>
|
||||||
|
#include <llvm/DerivedTypes.h>
|
||||||
|
#include <llvm/Function.h>
|
||||||
|
#include <llvm/Module.h>
|
||||||
|
#include <llvm/Constants.h>
|
||||||
|
#include <llvm/Intrinsics.h>
|
||||||
|
#include <llvm/IRBuilder.h>
|
||||||
|
#endif
|
||||||
#include <llvm/Support/raw_ostream.h>
|
#include <llvm/Support/raw_ostream.h>
|
||||||
#include <llvm/Support/FormattedStream.h>
|
#include <llvm/Support/FormattedStream.h>
|
||||||
#include <llvm/Support/MemoryBuffer.h>
|
#include <llvm/Support/MemoryBuffer.h>
|
||||||
|
|
@ -12,14 +26,11 @@
|
||||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||||
#include <llvm/ExecutionEngine/GenericValue.h>
|
#include <llvm/ExecutionEngine/GenericValue.h>
|
||||||
#include <llvm/Linker.h>
|
#include <llvm/Linker.h>
|
||||||
#include <llvm/Module.h>
|
|
||||||
#include <llvm/Analysis/Verifier.h>
|
#include <llvm/Analysis/Verifier.h>
|
||||||
#include <llvm/Constants.h>
|
|
||||||
#include <llvm/Intrinsics.h>
|
|
||||||
#include <llvm/IRBuilder.h>
|
|
||||||
#include <llvm/PassRegistry.h>
|
#include <llvm/PassRegistry.h>
|
||||||
#include <llvm/Support/Host.h>
|
#include <llvm/Support/Host.h>
|
||||||
|
|
||||||
|
#include <llvm/ExecutionEngine/MCJIT.h> // to make MCJIT working
|
||||||
|
|
||||||
#include "auto_pyobject.h"
|
#include "auto_pyobject.h"
|
||||||
|
|
||||||
|
|
@ -56,6 +67,15 @@ namespace extra{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PyObject* callwrite(PyObject* self, PyObject* arg)
|
||||||
|
{
|
||||||
|
char meth[] = "write";
|
||||||
|
char fmt[] = "O";
|
||||||
|
return PyObject_CallMethod(self, meth, fmt, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args)
|
PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
|
|
@ -271,7 +291,7 @@ llvm::ExecutionEngine* ExecutionEngine_create(
|
||||||
&ErrorStr, OptLevel,
|
&ErrorStr, OptLevel,
|
||||||
GVsWithCode);
|
GVsWithCode);
|
||||||
auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str());
|
auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str());
|
||||||
if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){
|
if (errout && NULL == callwrite(errout, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,7 +318,7 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT(
|
||||||
ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL,
|
ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL,
|
||||||
GCsWithCode, RM, CMM);
|
GCsWithCode, RM, CMM);
|
||||||
auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str());
|
auto_pyobject buf = PyBytes_FromString(ErrorStr.c_str());
|
||||||
if (errout && NULL == PyObject_CallMethod(errout, "write", "O", *buf)){
|
if (errout && NULL == callwrite(errout, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// PyFile_WriteString(ErrorStr.c_str(), errout);
|
// PyFile_WriteString(ErrorStr.c_str(), errout);
|
||||||
|
|
@ -483,7 +503,7 @@ PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx,
|
||||||
std::string ErrStr;
|
std::string ErrStr;
|
||||||
M = ParseBitcodeFile(MB, Ctx, &ErrStr);
|
M = ParseBitcodeFile(MB, Ctx, &ErrStr);
|
||||||
auto_pyobject buf = PyBytes_FromString(ErrStr.c_str());
|
auto_pyobject buf = PyBytes_FromString(ErrStr.c_str());
|
||||||
if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){
|
if (NULL == callwrite(FObj, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
|
// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
|
||||||
|
|
@ -507,7 +527,7 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj)
|
||||||
rso.flush();
|
rso.flush();
|
||||||
StringRef ref = rso.str();
|
StringRef ref = rso.str();
|
||||||
auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size());
|
auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size());
|
||||||
return PyObject_CallMethod(FObj, "write", "O", *buf);
|
return callwrite(FObj, *buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
|
@ -522,7 +542,7 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf,
|
||||||
std::string ErrStr;
|
std::string ErrStr;
|
||||||
Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr);
|
Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr);
|
||||||
auto_pyobject buf = PyBytes_FromString(ErrStr.c_str());
|
auto_pyobject buf = PyBytes_FromString(ErrStr.c_str());
|
||||||
if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){
|
if (NULL == callwrite(FObj, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
|
// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
|
||||||
|
|
@ -594,19 +614,19 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker,
|
||||||
PyObject* ErrMsg)
|
PyObject* ErrMsg)
|
||||||
{
|
{
|
||||||
std::string errmsg;
|
std::string errmsg;
|
||||||
|
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3
|
||||||
|
bool failed = Linker->linkInModule(Mod, &errmsg);
|
||||||
|
#else
|
||||||
bool failed = Linker->LinkInModule(Mod, &errmsg);
|
bool failed = Linker->LinkInModule(Mod, &errmsg);
|
||||||
|
#endif
|
||||||
if (! failed) {
|
if (! failed) {
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
||||||
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
|
if (NULL == callwrite(ErrMsg, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
|
|
||||||
// return NULL;
|
|
||||||
// }
|
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -623,7 +643,7 @@ PyObject* Linker_LinkModules(llvm::Module* Dest,
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
} else {
|
} else {
|
||||||
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
||||||
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
|
if (NULL == callwrite(ErrMsg, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
|
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
|
||||||
|
|
@ -689,7 +709,7 @@ PyObject* llvm_verifyModule(const llvm::Module& Fn,
|
||||||
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
||||||
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
|
if (NULL == callwrite(ErrMsg, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -819,7 +839,7 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename,
|
||||||
failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg);
|
failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg);
|
||||||
if (failed) {
|
if (failed) {
|
||||||
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
|
||||||
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
|
if (NULL == callwrite(ErrMsg, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
|
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
|
||||||
|
|
@ -869,7 +889,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Triple,
|
||||||
if (!target) {
|
if (!target) {
|
||||||
// PyFile_WriteString(error.c_str(), Error);
|
// PyFile_WriteString(error.c_str(), Error);
|
||||||
auto_pyobject buf = PyBytes_FromString(error.c_str());
|
auto_pyobject buf = PyBytes_FromString(error.c_str());
|
||||||
if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){
|
if (NULL == callwrite(Error, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -891,7 +911,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch,
|
||||||
if (!target) {
|
if (!target) {
|
||||||
// PyFile_WriteString(error.c_str(), Error);
|
// PyFile_WriteString(error.c_str(), Error);
|
||||||
auto_pyobject buf = PyBytes_FromString(error.c_str());
|
auto_pyobject buf = PyBytes_FromString(error.c_str());
|
||||||
if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){
|
if (NULL == callwrite(Error, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -910,7 +930,7 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error)
|
||||||
const Target* target = TargetRegistry::getClosestTargetForJIT(error);
|
const Target* target = TargetRegistry::getClosestTargetForJIT(error);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
auto_pyobject buf = PyBytes_FromString(error.c_str());
|
auto_pyobject buf = PyBytes_FromString(error.c_str());
|
||||||
if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){
|
if (NULL == callwrite(Error, *buf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -945,3 +965,22 @@ PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 3
|
||||||
|
static
|
||||||
|
PyObject* llvm_sys_isLittleEndianHost()
|
||||||
|
{
|
||||||
|
if (llvm::sys::IsLittleEndianHost)
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
else
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PyObject* llvm_sys_isBigEndianHost()
|
||||||
|
{
|
||||||
|
if (llvm::sys::IsBigEndianHost)
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
else
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,27 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from .namespace import llvm
|
from .namespace import llvm
|
||||||
from .Value import Argument, Value
|
from .Value import Argument, Value
|
||||||
from .Attributes import Attributes
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
from .Attributes import AttributeSet, Attribute
|
||||||
|
else:
|
||||||
|
from .Attributes import Attributes
|
||||||
|
|
||||||
@Argument
|
@Argument
|
||||||
class Argument:
|
class Argument:
|
||||||
_include_ = 'llvm/Argument.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/Argument.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/Argument.h'
|
||||||
|
|
||||||
_downcast_ = Value
|
_downcast_ = Value
|
||||||
|
|
||||||
addAttr = Method(Void, ref(Attributes))
|
if LLVM_VERSION >= (3, 3):
|
||||||
removeAttr = Method(Void, ref(Attributes))
|
addAttr = Method(Void, ref(AttributeSet))
|
||||||
|
removeAttr = Method(Void, ref(AttributeSet))
|
||||||
|
else:
|
||||||
|
addAttr = Method(Void, ref(Attributes))
|
||||||
|
removeAttr = Method(Void, ref(Attributes))
|
||||||
|
|
||||||
getParamAlignment = Method(cast(Unsigned, int))
|
getParamAlignment = Method(cast(Unsigned, int))
|
||||||
|
|
||||||
getArgNo = Method(cast(Unsigned, int))
|
getArgNo = Method(cast(Unsigned, int))
|
||||||
|
|
|
||||||
|
|
@ -2,38 +2,91 @@ from binding import *
|
||||||
from .namespace import llvm
|
from .namespace import llvm
|
||||||
from .LLVMContext import LLVMContext
|
from .LLVMContext import LLVMContext
|
||||||
|
|
||||||
llvm.includes.add('llvm/Attributes.h')
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
llvm.includes.add('llvm/IR/Attributes.h')
|
||||||
|
else:
|
||||||
|
llvm.includes.add('llvm/Attributes.h')
|
||||||
|
|
||||||
|
|
||||||
Attributes = llvm.Class()
|
|
||||||
AttrBuilder = llvm.Class()
|
AttrBuilder = llvm.Class()
|
||||||
|
|
||||||
|
if LLVM_VERSION >= (3, 3):
|
||||||
@Attributes
|
Attribute = llvm.Class()
|
||||||
class Attributes:
|
AttributeSet = llvm.Class()
|
||||||
AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline,
|
else:
|
||||||
ByVal, InlineHint, InReg, MinSize,
|
Attributes = llvm.Class()
|
||||||
Naked, Nest, NoAlias, NoCapture,
|
|
||||||
NoImplicitFloat, NoInline, NonLazyBind, NoRedZone,
|
|
||||||
NoReturn, NoUnwind, OptimizeForSize, ReadNone,
|
|
||||||
ReadOnly, ReturnsTwice, SExt, StackAlignment,
|
|
||||||
StackProtect, StackProtectReq, StructRet, UWTable, ZExt''')
|
|
||||||
|
|
||||||
delete = Destructor()
|
|
||||||
|
|
||||||
get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder))
|
|
||||||
|
|
||||||
|
|
||||||
@AttrBuilder
|
if LLVM_VERSION >= (3, 3):
|
||||||
class AttrBuilder:
|
@Attribute
|
||||||
|
class Attribute:
|
||||||
|
AttrKind = Enum('''None, Alignment, AlwaysInline,
|
||||||
|
ByVal, InlineHint, InReg,
|
||||||
|
MinSize, Naked, Nest, NoAlias,
|
||||||
|
NoBuiltin, NoCapture, NoDuplicate, NoImplicitFloat,
|
||||||
|
NoInline, NonLazyBind, NoRedZone, NoReturn,
|
||||||
|
NoUnwind, OptimizeForSize, ReadNone, ReadOnly,
|
||||||
|
Returned, ReturnsTwice, SExt, StackAlignment,
|
||||||
|
StackProtect, StackProtectReq, StackProtectStrong, StructRet,
|
||||||
|
SanitizeAddress, SanitizeThread, SanitizeMemory, UWTable,
|
||||||
|
ZExt, EndAttrKinds''')
|
||||||
|
|
||||||
new = Constructor()
|
delete = Destructor()
|
||||||
delete = Destructor()
|
|
||||||
|
|
||||||
clear = Method()
|
get = StaticMethod(Attribute,
|
||||||
|
ref(LLVMContext),
|
||||||
|
AttrKind,
|
||||||
|
cast(int, Uint64)).require_only(2)
|
||||||
|
|
||||||
addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal)
|
@AttrBuilder
|
||||||
removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal)
|
class AttrBuilder:
|
||||||
|
|
||||||
addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned))
|
new = Constructor()
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
|
clear = Method()
|
||||||
|
|
||||||
|
addAttribute = Method(ref(AttrBuilder), Attribute.AttrKind)
|
||||||
|
removeAttribute = Method(ref(AttrBuilder), Attribute.AttrKind)
|
||||||
|
|
||||||
|
addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned))
|
||||||
|
|
||||||
|
@AttributeSet
|
||||||
|
class AttributeSet:
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
|
get = StaticMethod(AttributeSet,
|
||||||
|
ref(LLVMContext),
|
||||||
|
cast(int, Unsigned),
|
||||||
|
ref(AttrBuilder))
|
||||||
|
|
||||||
|
else:
|
||||||
|
@Attributes
|
||||||
|
class Attributes:
|
||||||
|
AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline,
|
||||||
|
ByVal, InlineHint, InReg, MinSize,
|
||||||
|
Naked, Nest, NoAlias, NoCapture,
|
||||||
|
NoImplicitFloat, NoInline, NonLazyBind, NoRedZone,
|
||||||
|
NoReturn, NoUnwind, OptimizeForSize, ReadNone,
|
||||||
|
ReadOnly, ReturnsTwice, SExt, StackAlignment,
|
||||||
|
StackProtect, StackProtectReq, StructRet, UWTable, ZExt''')
|
||||||
|
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
|
get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder))
|
||||||
|
|
||||||
|
|
||||||
|
@AttrBuilder
|
||||||
|
class AttrBuilder:
|
||||||
|
|
||||||
|
new = Constructor()
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
|
clear = Method()
|
||||||
|
|
||||||
|
addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal)
|
||||||
|
removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal)
|
||||||
|
|
||||||
|
addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,17 +124,31 @@ class DIBuilder:
|
||||||
ptr(MDNode), # TemplateParms = 0
|
ptr(MDNode), # TemplateParms = 0
|
||||||
).require_only(10)
|
).require_only(10)
|
||||||
|
|
||||||
createStructType = Method(DIType,
|
if LLVM_VERSION >= (3, 3):
|
||||||
ref(DIDescriptor), # Scope
|
createStructType = Method(DIType,
|
||||||
stringref_arg, # Name
|
ref(DIDescriptor), # Scope
|
||||||
ref(DIFile), # File
|
stringref_arg, # Name
|
||||||
unsigned_arg, # LineNumber
|
ref(DIFile), # File
|
||||||
uint64_arg, # SizeInBits
|
unsigned_arg, # LineNumber
|
||||||
uint64_arg, # AlignInBits
|
uint64_arg, # SizeInBits
|
||||||
unsigned_arg, # Flags
|
uint64_arg, # AlignInBits
|
||||||
ref(DIArray), # Elements
|
unsigned_arg, # Flags
|
||||||
unsigned_arg, # RunTimeLang = 0
|
ref(DIType), # DerivedFrom
|
||||||
).require_only(8)
|
ref(DIArray), # Elements
|
||||||
|
unsigned_arg, # RunTimeLang = 0
|
||||||
|
).require_only(9)
|
||||||
|
else:
|
||||||
|
createStructType = Method(DIType,
|
||||||
|
ref(DIDescriptor), # Scope
|
||||||
|
stringref_arg, # Name
|
||||||
|
ref(DIFile), # File
|
||||||
|
unsigned_arg, # LineNumber
|
||||||
|
uint64_arg, # SizeInBits
|
||||||
|
uint64_arg, # AlignInBits
|
||||||
|
unsigned_arg, # Flags
|
||||||
|
ref(DIArray), # Elements
|
||||||
|
unsigned_arg, # RunTimeLang = 0
|
||||||
|
).require_only(8)
|
||||||
|
|
||||||
createUnionType = Method(DIType,
|
createUnionType = Method(DIType,
|
||||||
ref(DIDescriptor), # Scope
|
ref(DIDescriptor), # Scope
|
||||||
|
|
@ -186,7 +200,7 @@ class DIBuilder:
|
||||||
ref(DIType), # Ty
|
ref(DIType), # Ty
|
||||||
)
|
)
|
||||||
|
|
||||||
createTemporaryType = Method(DIType, ref(DIFile)).require_only(0)
|
#createTemporaryType = Method(DIType, ref(DIFile)).require_only(0)
|
||||||
|
|
||||||
createForwardDecl = Method(DIType,
|
createForwardDecl = Method(DIType,
|
||||||
unsigned_arg, # Tag
|
unsigned_arg, # Tag
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@ from .GlobalVariable import GlobalVariable
|
||||||
|
|
||||||
@DataLayout
|
@DataLayout
|
||||||
class DataLayout:
|
class DataLayout:
|
||||||
_include_ = 'llvm/DataLayout.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/DataLayout.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/DataLayout.h'
|
||||||
|
|
||||||
_new_string = Constructor(cast(str, StringRef))
|
_new_string = Constructor(cast(str, StringRef))
|
||||||
_new_module = Constructor(ptr(Module))
|
_new_module = Constructor(ptr(Module))
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ FunctionType = llvm.Class(Type)
|
||||||
|
|
||||||
@FunctionType
|
@FunctionType
|
||||||
class FunctionType:
|
class FunctionType:
|
||||||
_include_ = 'llvm/DerivedTypes.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/DerivedTypes.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/DerivedTypes.h'
|
||||||
_downcast_ = Type
|
_downcast_ = Type
|
||||||
|
|
||||||
_get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool))
|
_get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool))
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,5 @@ class ExecutionEngine:
|
||||||
unwrapped = list(map(capsule.unwrap, args))
|
unwrapped = list(map(capsule.unwrap, args))
|
||||||
return self._runFunction(fn, tuple(unwrapped))
|
return self._runFunction(fn, tuple(unwrapped))
|
||||||
|
|
||||||
|
finalizeObject = Method(Void)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ from .Value import GlobalValue, Constant, Function, Argument, Value
|
||||||
from .Module import Module
|
from .Module import Module
|
||||||
from .BasicBlock import BasicBlock
|
from .BasicBlock import BasicBlock
|
||||||
from .ValueSymbolTable import ValueSymbolTable
|
from .ValueSymbolTable import ValueSymbolTable
|
||||||
from .Attributes import Attributes
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
from .Attributes import Attribute, AttributeSet
|
||||||
|
else:
|
||||||
|
from .Attributes import Attributes
|
||||||
from .Type import Type
|
from .Type import Type
|
||||||
from .DerivedTypes import FunctionType
|
from .DerivedTypes import FunctionType
|
||||||
from .LLVMContext import LLVMContext
|
from .LLVMContext import LLVMContext
|
||||||
|
|
@ -12,7 +15,11 @@ from .CallingConv import CallingConv
|
||||||
|
|
||||||
@Function
|
@Function
|
||||||
class Function:
|
class Function:
|
||||||
_include_ = 'llvm/Function.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/Function.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/Function.h'
|
||||||
|
|
||||||
_downcast_ = GlobalValue, Constant, Value
|
_downcast_ = GlobalValue, Constant, Value
|
||||||
|
|
||||||
getReturnType = Method(ptr(Type))
|
getReturnType = Method(ptr(Type))
|
||||||
|
|
@ -48,10 +55,17 @@ class Function:
|
||||||
|
|
||||||
deleteBody = Method()
|
deleteBody = Method()
|
||||||
viewCFG = Method()
|
viewCFG = Method()
|
||||||
|
|
||||||
viewCFGOnly = Method()
|
viewCFGOnly = Method()
|
||||||
|
|
||||||
addFnAttr = Method(Void, Attributes.AttrVal)
|
if LLVM_VERSION >= (3, 3):
|
||||||
removeFnAttr = Method(Void, ref(Attributes))
|
addFnAttr = Method(Void, Attribute.AttrKind)
|
||||||
|
addAttributes = Method(Void, cast(int, Unsigned), ref(AttributeSet))
|
||||||
|
removeAttributes = Method(Void, cast(int, Unsigned), ref(AttributeSet))
|
||||||
|
#removeFnAttr = Method(Void, Attribute.AttrKind) # 3.4?
|
||||||
|
else:
|
||||||
|
addFnAttr = Method(Void, Attributes.AttrVal)
|
||||||
|
removeFnAttr = Method(Void, ref(Attributes))
|
||||||
#hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal)
|
#hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal)
|
||||||
|
|
||||||
Create = StaticMethod(ptr(Function),
|
Create = StaticMethod(ptr(Function),
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ from .ADT.StringRef import StringRef
|
||||||
|
|
||||||
@GlobalValue
|
@GlobalValue
|
||||||
class GlobalValue:
|
class GlobalValue:
|
||||||
_include_ = 'llvm/GlobalValue.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/GlobalValue.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/GlobalValue.h'
|
||||||
|
|
||||||
LinkageTypes = Enum('''
|
LinkageTypes = Enum('''
|
||||||
ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage,
|
ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,11 @@ IRBuilder = llvm.Class()
|
||||||
|
|
||||||
@IRBuilder
|
@IRBuilder
|
||||||
class IRBuilder:
|
class IRBuilder:
|
||||||
_include_ = 'llvm/IRBuilder.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/IRBuilder.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/IRBuilder.h'
|
||||||
|
|
||||||
_realname_ = 'IRBuilder<>'
|
_realname_ = 'IRBuilder<>'
|
||||||
|
|
||||||
new = Constructor(ref(LLVMContext))
|
new = Constructor(ref(LLVMContext))
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ from .Value import Value
|
||||||
from .DerivedTypes import FunctionType
|
from .DerivedTypes import FunctionType
|
||||||
from .ADT.StringRef import StringRef
|
from .ADT.StringRef import StringRef
|
||||||
|
|
||||||
llvm.includes.add('llvm/InlineAsm.h')
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
llvm.includes.add('llvm/IR/InlineAsm.h')
|
||||||
|
else:
|
||||||
|
llvm.includes.add('llvm/InlineAsm.h')
|
||||||
|
|
||||||
InlineAsm = llvm.Class(Value)
|
InlineAsm = llvm.Class(Value)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,10 @@ SynchronizationScope = llvm.Enum('SynchronizationScope',
|
||||||
|
|
||||||
from .ADT.StringRef import StringRef
|
from .ADT.StringRef import StringRef
|
||||||
from .CallingConv import CallingConv
|
from .CallingConv import CallingConv
|
||||||
from .Attributes import Attributes
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
from .Attributes import AttributeSet, Attribute
|
||||||
|
else:
|
||||||
|
from .Attributes import Attributes
|
||||||
from .Type import Type
|
from .Type import Type
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -142,8 +145,12 @@ class CallInst:
|
||||||
getCallingConv = Method(CallingConv.ID)
|
getCallingConv = Method(CallingConv.ID)
|
||||||
setCallingConv = Method(Void, CallingConv.ID)
|
setCallingConv = Method(Void, CallingConv.ID)
|
||||||
getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned))
|
getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned))
|
||||||
addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
if LLVM_VERSION >= (3, 3):
|
||||||
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
addAttribute = Method(Void, cast(int, Unsigned), Attribute.AttrKind)
|
||||||
|
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attribute))
|
||||||
|
else:
|
||||||
|
addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
||||||
|
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
||||||
getCalledFunction = Method(ptr(Function))
|
getCalledFunction = Method(ptr(Function))
|
||||||
getCalledValue = Method(ptr(Value))
|
getCalledValue = Method(ptr(Value))
|
||||||
setCalledFunction = Method(Void, ptr(Function))
|
setCalledFunction = Method(Void, ptr(Function))
|
||||||
|
|
@ -264,7 +271,10 @@ class UnaryInstruction:
|
||||||
|
|
||||||
@IntrinsicInst
|
@IntrinsicInst
|
||||||
class IntrinsicInst:
|
class IntrinsicInst:
|
||||||
_include_ = 'llvm/IntrinsicInst.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/IntrinsicInst.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/IntrinsicInst.h'
|
||||||
_downcast_ = Value, User, Instruction
|
_downcast_ = Value, User, Instruction
|
||||||
|
|
||||||
#compare
|
#compare
|
||||||
|
|
@ -292,8 +302,12 @@ class InvokeInst:
|
||||||
getCallingConv = Method(CallingConv.ID)
|
getCallingConv = Method(CallingConv.ID)
|
||||||
setCallingConv = Method(Void, CallingConv.ID)
|
setCallingConv = Method(Void, CallingConv.ID)
|
||||||
getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned))
|
getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned))
|
||||||
addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
if LLVM_VERSION >= (3, 3):
|
||||||
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
addAttribute = Method(Void, cast(int, Unsigned), Attribute.AttrKind)
|
||||||
|
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attribute))
|
||||||
|
else:
|
||||||
|
addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
||||||
|
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
|
||||||
getCalledFunction = Method(ptr(Function))
|
getCalledFunction = Method(ptr(Function))
|
||||||
getCalledValue = Method(ptr(Value))
|
getCalledValue = Method(ptr(Value))
|
||||||
setCalledFunction = Method(Void, ptr(Function))
|
setCalledFunction = Method(Void, ptr(Function))
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ from .namespace import llvm
|
||||||
|
|
||||||
@llvm.Class()
|
@llvm.Class()
|
||||||
class LLVMContext:
|
class LLVMContext:
|
||||||
_include_ = "llvm/LLVMContext.h"
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = "llvm/IR/LLVMContext.h"
|
||||||
|
else:
|
||||||
|
_include_ = "llvm/LLVMContext.h"
|
||||||
|
|
||||||
llvm.Function('getGlobalContext', ref(LLVMContext))
|
llvm.Function('getGlobalContext', ref(LLVMContext))
|
||||||
|
|
|
||||||
|
|
@ -10,30 +10,33 @@ Linker = llvm.Class()
|
||||||
|
|
||||||
@Linker
|
@Linker
|
||||||
class Linker:
|
class Linker:
|
||||||
ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors')
|
#ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors')
|
||||||
LinkerMode = Enum('DestroySource, PreserveSource')
|
LinkerMode = Enum('DestroySource, PreserveSource')
|
||||||
|
|
||||||
_new_w_empty = Constructor(cast(str, StringRef),
|
if LLVM_VERSION >= (3, 3):
|
||||||
cast(str, StringRef),
|
new = Constructor(ptr(Module))
|
||||||
ref(LLVMContext),
|
else:
|
||||||
cast(int, Unsigned)).require_only(3)
|
_new_w_empty = Constructor(cast(str, StringRef),
|
||||||
|
cast(str, StringRef),
|
||||||
|
ref(LLVMContext),
|
||||||
|
cast(int, Unsigned)).require_only(3)
|
||||||
|
|
||||||
_new_w_existing = Constructor(cast(str, StringRef),
|
_new_w_existing = Constructor(cast(str, StringRef),
|
||||||
ptr(Module),
|
ptr(Module),
|
||||||
cast(int, Unsigned)).require_only(2)
|
cast(int, Unsigned)).require_only(2)
|
||||||
|
|
||||||
@CustomPythonStaticMethod
|
@CustomPythonStaticMethod
|
||||||
def new(progname, module_or_name, *args):
|
def new(progname, module_or_name, *args):
|
||||||
if isinstance(module_or_name, Module):
|
if isinstance(module_or_name, Module):
|
||||||
return _new_w_existing(progname, module_or_name, *args)
|
return _new_w_existing(progname, module_or_name, *args)
|
||||||
else:
|
else:
|
||||||
return _new_w_empty(progname, module_or_name, *args)
|
return _new_w_empty(progname, module_or_name, *args)
|
||||||
|
|
||||||
delete = Destructor()
|
delete = Destructor()
|
||||||
|
|
||||||
getModule = Method(ptr(Module))
|
getModule = Method(ptr(Module))
|
||||||
releaseModule = Method(ptr(Module))
|
#releaseModule = Method(ptr(Module))
|
||||||
getLastError = Method(cast(ConstStdString, str))
|
#getLastError = Method(cast(ConstStdString, str))
|
||||||
|
|
||||||
LinkInModule = CustomMethod('Linker_LinkInModule',
|
LinkInModule = CustomMethod('Linker_LinkInModule',
|
||||||
PyObjectPtr, # boolean
|
PyObjectPtr, # boolean
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,10 @@ from .Metadata import NamedMDNode
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
class Module:
|
class Module:
|
||||||
_include_ = "llvm/Module.h"
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = "llvm/IR/Module.h"
|
||||||
|
else:
|
||||||
|
_include_ = "llvm/Module.h"
|
||||||
# Enumerators
|
# Enumerators
|
||||||
Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
|
Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
|
||||||
PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64')
|
PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64')
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,29 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from src.namespace import sys
|
from src.namespace import sys
|
||||||
|
|
||||||
isLittleEndianHost = sys.Function('isLittleEndianHost',
|
|
||||||
cast(Bool, bool))
|
|
||||||
|
|
||||||
isBigEndianHost = sys.Function('isBigEndianHost',
|
|
||||||
cast(Bool, bool))
|
|
||||||
|
|
||||||
getDefaultTargetTriple = sys.Function('getDefaultTargetTriple',
|
getDefaultTargetTriple = sys.Function('getDefaultTargetTriple',
|
||||||
cast(ConstStdString, str))
|
cast(ConstStdString, str))
|
||||||
|
|
||||||
# llvm 3.3
|
if LLVM_VERSION >= (3, 3):
|
||||||
#getProcessTriple = sys.Function('getProcessTriple',
|
getProcessTriple = sys.Function('getProcessTriple',
|
||||||
# cast(ConstStdString, str))
|
cast(ConstStdString, str))
|
||||||
|
|
||||||
|
isLittleEndianHost = sys.CustomFunction('isLittleEndianHost',
|
||||||
|
'llvm_sys_isLittleEndianHost',
|
||||||
|
cast(Bool, bool))
|
||||||
|
|
||||||
|
isBigEndianHost = sys.CustomFunction('isBigEndianHost',
|
||||||
|
'llvm_sys_isBigEndianHost',
|
||||||
|
cast(Bool, bool))
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
isLittleEndianHost = sys.Function('isLittleEndianHost',
|
||||||
|
cast(Bool, bool))
|
||||||
|
|
||||||
|
isBigEndianHost = sys.Function('isBigEndianHost',
|
||||||
|
cast(Bool, bool))
|
||||||
|
|
||||||
|
|
||||||
getHostCPUName = sys.Function('getHostCPUName',
|
getHostCPUName = sys.Function('getHostCPUName',
|
||||||
cast(ConstStdString, str))
|
cast(ConstStdString, str))
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt
|
||||||
|
|
||||||
@Target
|
@Target
|
||||||
class Target:
|
class Target:
|
||||||
getNext = Method(const(ptr(Target)))
|
getNext = Method(const(ownedptr(Target)))
|
||||||
|
|
||||||
getName = Method(cast(StdString, str))
|
getName = Method(cast(StdString, str))
|
||||||
getShortDescription = Method(cast(StdString, str))
|
getShortDescription = Method(cast(StdString, str))
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,10 @@ from src.ADT.StringRef import StringRef
|
||||||
from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc
|
from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc
|
||||||
from src.GlobalValue import GlobalValue
|
from src.GlobalValue import GlobalValue
|
||||||
from src.DataLayout import DataLayout
|
from src.DataLayout import DataLayout
|
||||||
from src.TargetTransformInfo import (ScalarTargetTransformInfo,
|
|
||||||
VectorTargetTransformInfo)
|
if LLVM_VERSION < (3, 3):
|
||||||
|
from src.TargetTransformInfo import (ScalarTargetTransformInfo,
|
||||||
|
VectorTargetTransformInfo)
|
||||||
from src.PassManager import PassManagerBase
|
from src.PassManager import PassManagerBase
|
||||||
from src.Support.FormattedStream import formatted_raw_ostream
|
from src.Support.FormattedStream import formatted_raw_ostream
|
||||||
|
|
||||||
|
|
@ -39,9 +41,11 @@ class TargetMachine:
|
||||||
setMCUseDwarfDirectory = Method(Void, cast(bool, Bool))
|
setMCUseDwarfDirectory = Method(Void, cast(bool, Bool))
|
||||||
|
|
||||||
getDataLayout = Method(const(ownedptr(DataLayout)))
|
getDataLayout = Method(const(ownedptr(DataLayout)))
|
||||||
getScalarTargetTransformInfo = Method(const(
|
|
||||||
|
if LLVM_VERSION < (3, 3):
|
||||||
|
getScalarTargetTransformInfo = Method(const(
|
||||||
ownedptr(ScalarTargetTransformInfo)))
|
ownedptr(ScalarTargetTransformInfo)))
|
||||||
getVectorTargetTransformInfo = Method(const(
|
getVectorTargetTransformInfo = Method(const(
|
||||||
ownedptr(VectorTargetTransformInfo)))
|
ownedptr(VectorTargetTransformInfo)))
|
||||||
|
|
||||||
addPassesToEmitFile = Method(cast(bool, Bool),
|
addPassesToEmitFile = Method(cast(bool, Bool),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ from binding import *
|
||||||
from src.namespace import llvm
|
from src.namespace import llvm
|
||||||
from src.Pass import ImmutablePass
|
from src.Pass import ImmutablePass
|
||||||
|
|
||||||
llvm.includes.add('llvm/TargetTransformInfo.h')
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
llvm.includes.add('llvm/Analysis/TargetTransformInfo.h')
|
||||||
|
else:
|
||||||
|
llvm.includes.add('llvm/TargetTransformInfo.h')
|
||||||
|
|
||||||
TargetTransformInfo = llvm.Class(ImmutablePass)
|
TargetTransformInfo = llvm.Class(ImmutablePass)
|
||||||
ScalarTargetTransformInfo = llvm.Class()
|
ScalarTargetTransformInfo = llvm.Class()
|
||||||
|
|
@ -11,14 +14,17 @@ VectorTargetTransformInfo = llvm.Class()
|
||||||
|
|
||||||
@ScalarTargetTransformInfo
|
@ScalarTargetTransformInfo
|
||||||
class ScalarTargetTransformInfo:
|
class ScalarTargetTransformInfo:
|
||||||
delete = Destructor()
|
if LLVM_VERSION < (3, 3):
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
@VectorTargetTransformInfo
|
@VectorTargetTransformInfo
|
||||||
class VectorTargetTransformInfo:
|
class VectorTargetTransformInfo:
|
||||||
delete = Destructor()
|
if LLVM_VERSION < (3, 3):
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
@TargetTransformInfo
|
@TargetTransformInfo
|
||||||
class TargetTransformInfo:
|
class TargetTransformInfo:
|
||||||
new = Constructor(ptr(ScalarTargetTransformInfo),
|
if LLVM_VERSION < (3, 3):
|
||||||
ptr(VectorTargetTransformInfo))
|
new = Constructor(ptr(ScalarTargetTransformInfo),
|
||||||
|
ptr(VectorTargetTransformInfo))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,11 @@ class PassManagerBuilder:
|
||||||
DisableSimplifyLibCalls = _attr_bool()
|
DisableSimplifyLibCalls = _attr_bool()
|
||||||
DisableUnitAtATime = _attr_bool()
|
DisableUnitAtATime = _attr_bool()
|
||||||
DisableUnrollLoops = _attr_bool()
|
DisableUnrollLoops = _attr_bool()
|
||||||
Vectorize = _attr_bool()
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
BBVectorize = _attr_bool()
|
||||||
|
SLPVectorize = _attr_bool()
|
||||||
|
else:
|
||||||
|
Vectorize = _attr_bool()
|
||||||
LoopVectorize = _attr_bool()
|
LoopVectorize = _attr_bool()
|
||||||
|
|
||||||
LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo),
|
LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@ VectorType = llvm.Class(SequentialType)
|
||||||
|
|
||||||
@Type
|
@Type
|
||||||
class Type:
|
class Type:
|
||||||
_include_ = 'llvm/Type.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/Type.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/Type.h'
|
||||||
|
|
||||||
TypeID = Enum('''
|
TypeID = Enum('''
|
||||||
VoidTyID, HalfTyID, FloatTyID, DoubleTyID,
|
VoidTyID, HalfTyID, FloatTyID, DoubleTyID,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ from .ADT.StringRef import StringRef
|
||||||
|
|
||||||
@ValueSymbolTable
|
@ValueSymbolTable
|
||||||
class ValueSymbolTable:
|
class ValueSymbolTable:
|
||||||
_include_ = 'llvm/ValueSymbolTable.h'
|
if LLVM_VERSION >= (3, 3):
|
||||||
|
_include_ = 'llvm/IR/ValueSymbolTable.h'
|
||||||
|
else:
|
||||||
|
_include_ = 'llvm/ValueSymbolTable.h'
|
||||||
new = Constructor()
|
new = Constructor()
|
||||||
delete = Destructor()
|
delete = Destructor()
|
||||||
lookup = Method(ptr(Value), cast(str, StringRef))
|
lookup = Method(ptr(Value), cast(str, StringRef))
|
||||||
|
|
|
||||||
13
setup.py
13
setup.py
|
|
@ -36,6 +36,7 @@ def run_llvm_config(extra_args):
|
||||||
return stdout.decode().strip()
|
return stdout.decode().strip()
|
||||||
|
|
||||||
llvm_version = run_llvm_config(['--version'])
|
llvm_version = run_llvm_config(['--version'])
|
||||||
|
|
||||||
print('LLVM version = %r' % llvm_version)
|
print('LLVM version = %r' % llvm_version)
|
||||||
|
|
||||||
targets_built = run_llvm_config(['--targets-built'])
|
targets_built = run_llvm_config(['--targets-built'])
|
||||||
|
|
@ -61,7 +62,12 @@ def auto_intrinsic_gen(incdir):
|
||||||
# let's do auto intrinsic generation
|
# let's do auto intrinsic generation
|
||||||
print("Generate intrinsic IDs")
|
print("Generate intrinsic IDs")
|
||||||
from tools import intrgen
|
from tools import intrgen
|
||||||
path = "%s/llvm/Intrinsics.gen" % incdir
|
|
||||||
|
if llvm_version.startswith('3.3'):
|
||||||
|
path = "%s/llvm/IR/Intrinsics.gen" % incdir
|
||||||
|
else:
|
||||||
|
path = "%s/llvm/Intrinsics.gen" % incdir
|
||||||
|
|
||||||
with open('llvm/_intrinsic_ids.py', 'w') as fout:
|
with open('llvm/_intrinsic_ids.py', 'w') as fout:
|
||||||
intrgen.gen(path, fout)
|
intrgen.gen(path, fout)
|
||||||
|
|
||||||
|
|
@ -119,7 +125,7 @@ else:
|
||||||
extra_components = list(extra_components & enabled_components)
|
extra_components = list(extra_components & enabled_components)
|
||||||
|
|
||||||
libs_core, objs_core = get_libs_and_objs(
|
libs_core, objs_core = get_libs_and_objs(
|
||||||
['core', 'analysis', 'scalaropts', 'executionengine',
|
['core', 'analysis', 'scalaropts', 'executionengine', 'mcjit',
|
||||||
'jit', 'native', 'interpreter', 'bitreader', 'bitwriter',
|
'jit', 'native', 'interpreter', 'bitreader', 'bitwriter',
|
||||||
'instrumentation', 'ipa', 'ipo', 'transformutils',
|
'instrumentation', 'ipa', 'ipo', 'transformutils',
|
||||||
'asmparser', 'linker', 'support', 'vectorize']
|
'asmparser', 'linker', 'support', 'vectorize']
|
||||||
|
|
@ -181,7 +187,8 @@ setup(
|
||||||
'llvm_cbuilder',
|
'llvm_cbuilder',
|
||||||
'llpython',
|
'llpython',
|
||||||
'llvm_array',
|
'llvm_array',
|
||||||
'llvmpy.api', 'llvmpy.api.llvm'],
|
'llvmpy.api', 'llvmpy.api.llvm',],
|
||||||
|
package_data = {'llvm': ['llrt/*.ll']},
|
||||||
py_modules = ['llvmpy',
|
py_modules = ['llvmpy',
|
||||||
'llvmpy._capsule',
|
'llvmpy._capsule',
|
||||||
'llvmpy._api',
|
'llvmpy._api',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue