Merge branch 'master' of github.com:llvmpy/llvmpy into llpython-dev

This commit is contained in:
Jon Riehl 2013-09-09 16:04:55 -05:00
commit ca17b03180
57 changed files with 2235 additions and 186 deletions

View file

@ -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:
--------------------
* fix test when cc is not available

View file

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

View file

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

View file

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

View file

@ -0,0 +1,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
View file

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

25
llrtc/README.md Normal file
View file

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

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

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

66
llrtc/lib/Makefile Normal file
View file

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

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

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

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

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

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

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

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

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

View file

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

View file

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

View file

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

View file

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

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

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

View file

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

View file

@ -53,6 +53,7 @@ LLVMInterpreter
LLVMipa
LLVMipo
LLVMJIT
LLVMMCJIT
LLVMLinker
LLVMMC
LLVMMCParser
@ -71,6 +72,7 @@ LLVMX86Desc
LLVMX86Disassembler
LLVMX86Info
LLVMX86Utils
LLVMDebugInfo
Advapi32
Shell32
""".split():
@ -106,7 +108,7 @@ def main():
elif option == '--includedir':
incdir = join(find_llvm_prefix(), 'include')
ensure_file(join(incdir, 'llvm' , 'BasicBlock.h'))
ensure_file(join(incdir, 'llvm' , 'Linker.h'))
print(incdir)
elif option == '--libdir':

View file

@ -325,11 +325,17 @@ class VisibilityEnum(Enum):
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):
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_ZEXT = AttrVal.ZExt
ATTR_SEXT = AttrVal.SExt
@ -1031,6 +1037,9 @@ class Value(llvm.Wrapper):
def __str__(self):
return str(self._ptr)
def __hash__(self):
return hash(self._ptr)
def __eq__(self, rhs):
if isinstance(rhs, Value):
return str(self) == str(rhs)
@ -1436,29 +1445,55 @@ class Argument(Value):
_valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS,
ATTR_NO_CAPTURE, ATTR_STRUCT_RET])
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 %s is not valid for arg %s" %
(attr, self))
if llvm.version >= (3, 3):
def add_attribute(self, attr):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAttribute(attr)
attrs = api.llvm.AttributeSet.get(context, 0, attrbldr)
self._ptr.addAttr(attrs)
if attr not in self:
raise ValueError("Attribute %r is not valid for arg %s" %
(attr, self))
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 remove_attribute(self, attr):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAttribute(attr)
attrs = api.llvm.AttributeSet.get(context, 0, 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 _set_alignment(self, align):
context = api.llvm.getGlobalContext()
attrbldr = api.llvm.AttrBuilder.new()
attrbldr.addAlignmentAttr(align)
attrs = api.llvm.AttributeSet.get(context, 0, attrbldr)
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):
return self._ptr.getParamAlignment()
@ -1816,6 +1851,9 @@ class Instruction(User):
def erase_from_parent(self):
return self._ptr.eraseFromParent()
def replace_all_uses_with(self, inst):
self._ptr.replaceAllUsesWith(inst)
class CallOrInvokeInstruction(Instruction):
_type_ = api.llvm.CallInst, api.llvm.InvokeInst
@ -2092,29 +2130,34 @@ class Builder(llvm.Wrapper):
# arithmethic, bitwise and logical
def add(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name))
def add(self, lhs, rhs, name="", nuw=False, nsw=False):
return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name,
nuw, nsw))
def fadd(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name))
def sub(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name))
def sub(self, lhs, rhs, name="", nuw=False, nsw=False):
return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name,
nuw, nsw))
def fsub(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name))
def mul(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name))
def mul(self, lhs, rhs, name="", nuw=False, nsw=False):
return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name,
nuw, nsw))
def fmul(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name))
def udiv(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name))
def udiv(self, lhs, rhs, name="", exact=False):
return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name,
exact))
def sdiv(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name))
def sdiv(self, lhs, rhs, name="", exact=False):
return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name,
exact))
def fdiv(self, lhs, rhs, 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=""):
return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name))
def shl(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name))
def shl(self, lhs, rhs, name="", nuw=False, nsw=False):
return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name,
nuw, nsw))
def lshr(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name))
def lshr(self, lhs, rhs, name="", exact=False):
return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name,
exact))
def ashr(self, lhs, rhs, name=""):
return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name))
def ashr(self, lhs, rhs, name="", exact=False):
return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name,
exact))
def and_(self, lhs, rhs, 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=""):
return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name))
def neg(self, val, name=""):
return _make_value(self._ptr.CreateNeg(val._ptr, name))
def neg(self, val, name="", nuw=False, nsw=False):
return _make_value(self._ptr.CreateNeg(val._ptr, name, nuw, nsw))
def not_(self, val, 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 user trigger the initialization?
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!?")

View file

@ -30,6 +30,7 @@
"Execution Engine and related classes."
import sys
from io import BytesIO
import contextlib
@ -150,9 +151,17 @@ class EngineBuilder(llvm.Wrapper):
'''
if tm is not None:
engine = self._ptr.create(tm._ptr)
elif (sys.platform.startswith('win32') and
getattr(self, '_use_mcjit', False)):
# force ELF generation on MCJIT on win32
triple = get_default_triple()
tm = TargetMachine.new('%s-elf' % triple)
engine = self._ptr.create(tm._ptr)
else:
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):
'''get the corresponding target machine
@ -171,6 +180,7 @@ class EngineBuilder(llvm.Wrapper):
'''Enable/disable MCJIT
'''
self._ptr.setUseMCJIT(enable)
self._use_mcjit = True
return self
#===----------------------------------------------------------------------===
@ -193,6 +203,9 @@ class ExecutionEngine(llvm.Wrapper):
ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args)))
return GenericValue(ptr)
def get_pointer_to_named_function(self, name, abort=True):
return self._ptr.getPointerToNamedFunction(name, abort)
def get_pointer_to_function(self, fn):
return self._ptr.getPointerToFunction(fn._ptr)
@ -218,6 +231,9 @@ class ExecutionEngine(llvm.Wrapper):
def remove_module(self, module):
return self._ptr.removeModule(module._ptr)
def finalize_object(self):
return self._ptr.finalizeObject()
@property
def target_data(self):
ptr = self._ptr.getDataLayout()
@ -232,7 +248,7 @@ def initialize_target(target, noraise=False):
It is safe to initialize the same target multiple times.
"""
prefix = 'LLVMInitialize'
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter']
postfixes = ['Target', 'TargetInfo', 'TargetMC', 'AsmPrinter', 'AsmParser']
try:
for postfix in postfixes:
getattr(api, '%s%s%s' % (prefix, target, postfix))()
@ -274,7 +290,7 @@ class TargetMachine(llvm.Wrapper):
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error)
raise llvm.LLVMException(error.getvalue())
if not target.hasTargetMachine():
raise llvm.LLVMException(target, "No target machine.")
target_options = api.llvm.TargetOptions.new()
@ -366,3 +382,14 @@ class TargetMachine(llvm.Wrapper):
def feature_string(self):
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
View file

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

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

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

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

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

View file

@ -70,13 +70,24 @@ class PassManagerBuilder(llvm.Wrapper):
def size_level(self, sizelevel):
self._ptr.SizeLevel = sizelevel
@property
def vectorize(self):
return self._ptr.Vectorize
if llvm.version >= (3, 3):
@property
def bbvectorize(self):
return self._ptr.BBVectorize
@vectorize.setter
def vectorize(self, enable):
self._ptr.Vectorize = enable
@bbvectorize.setter
def bbvectorize(self, 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
@ -331,14 +342,14 @@ def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False,
if pm:
pm.add(tm.target_data.clone())
pm.add(TargetLibraryInfo.new(tm.triple))
if llvm.version >= (3, 2):
if llvm.version == (3, 2):
pm.add(TargetTransformInfo.new(tm))
pmb.populate(pm)
if fpm:
fpm.add(tm.target_data.clone())
fpm.add(TargetLibraryInfo.new(tm.triple))
if llvm.version >= (3, 2):
if llvm.version == (3, 2):
fpm.add(TargetTransformInfo.new(tm))
pmb.populate(fpm)
fpm.initialize()

View file

@ -1353,6 +1353,235 @@ class TestCmp(TestCase):
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):

View file

@ -50,8 +50,7 @@ def detect_osx_like():
stdout=subprocess.PIPE)
except OSError:
return False
features = info.stdout.read()
features = info.stdout.read().decode('UTF8')
features = features.split()
return 'AVX1.0' in features and 'OSXSAVE' in features and 'XSAVE' in features

View file

@ -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
View 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

View file

@ -3,11 +3,13 @@ from collections import defaultdict
import logging
logger = logging.getLogger(__name__)
NO_DEBUG = False
def silent_logger():
'''
Silent logger for unless we have a error message.
'''
logger.setLevel(logging.ERROR)
NO_DEBUG = True
# comment out the line below to re-enable logging at DEBUG level.
silent_logger()
@ -35,7 +37,11 @@ def _capsule_weakref_dtor(item):
if refct == 0:
dtor = _addr2dtor.pop((name, addr), 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)
class Capsule(object):

View file

@ -247,7 +247,8 @@ class Class(SubModule, _Type):
def __call__(self, defn):
assert not self._is_defined
# process the definition in "defn"
self.name = defn.__name__
self.name = getattr(defn, '_name_', defn.__name__)
for k, v in defn.__dict__.items():
if isinstance(v, Method):
self.methods.append(v)
@ -332,7 +333,7 @@ class Class(SubModule, _Type):
writer.die_if_false(raw, verbose=name)
ptrty = ptr(self).fullname
ty = self.fullname
fmt = 'typecast< %(ty)s >::from(%(raw)s)'
fmt = 'unwrap_as<%(ty)s, %(name)s >::from(%(raw)s)'
casted = writer.declare(ptrty, fmt % locals())
writer.die_if_false(casted)
return casted

View file

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

View file

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

View file

@ -1,8 +1,22 @@
#include <Python.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Value.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 3
#include <llvm/IR/Value.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/FormattedStream.h>
#include <llvm/Support/MemoryBuffer.h>
@ -12,14 +26,11 @@
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/Linker.h>
#include <llvm/Module.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Constants.h>
#include <llvm/Intrinsics.h>
#include <llvm/IRBuilder.h>
#include <llvm/PassRegistry.h>
#include <llvm/Support/Host.h>
#include <llvm/ExecutionEngine/MCJIT.h> // to make MCJIT working
#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
PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args)
{
@ -271,7 +291,7 @@ llvm::ExecutionEngine* ExecutionEngine_create(
&ErrorStr, OptLevel,
GVsWithCode);
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;
}
@ -298,7 +318,7 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT(
ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL,
GCsWithCode, RM, CMM);
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;
}
// PyFile_WriteString(ErrorStr.c_str(), errout);
@ -483,7 +503,7 @@ PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx,
std::string ErrStr;
M = ParseBitcodeFile(MB, Ctx, &ErrStr);
auto_pyobject buf = PyBytes_FromString(ErrStr.c_str());
if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){
if (NULL == callwrite(FObj, *buf)){
return NULL;
}
// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
@ -507,7 +527,7 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj)
rso.flush();
StringRef ref = rso.str();
auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size());
return PyObject_CallMethod(FObj, "write", "O", *buf);
return callwrite(FObj, *buf);
}
static
@ -522,7 +542,7 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf,
std::string ErrStr;
Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr);
auto_pyobject buf = PyBytes_FromString(ErrStr.c_str());
if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){
if (NULL == callwrite(FObj, *buf)){
return NULL;
}
// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
@ -594,19 +614,19 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker,
PyObject* 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);
#endif
if (! failed) {
Py_RETURN_FALSE;
} else {
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
if (NULL == callwrite(ErrMsg, *buf)){
return NULL;
}
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
// return NULL;
// }
Py_RETURN_TRUE;
}
}
@ -623,7 +643,7 @@ PyObject* Linker_LinkModules(llvm::Module* Dest,
Py_RETURN_FALSE;
} else {
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
if (NULL == callwrite(ErrMsg, *buf)){
return NULL;
}
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
@ -689,7 +709,7 @@ PyObject* llvm_verifyModule(const llvm::Module& Fn,
if (failed) {
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
if (NULL == callwrite(ErrMsg, *buf)){
return NULL;
}
@ -819,7 +839,7 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename,
failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg);
if (failed) {
auto_pyobject buf = PyBytes_FromString(errmsg.c_str());
if (NULL == PyObject_CallMethod(ErrMsg, "write", "O", *buf)){
if (NULL == callwrite(ErrMsg, *buf)){
return NULL;
}
// if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
@ -869,7 +889,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Triple,
if (!target) {
// PyFile_WriteString(error.c_str(), Error);
auto_pyobject buf = PyBytes_FromString(error.c_str());
if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){
if (NULL == callwrite(Error, *buf)){
return NULL;
}
@ -891,7 +911,7 @@ PyObject* TargetRegistry_lookupTarget(const std::string &Arch,
if (!target) {
// PyFile_WriteString(error.c_str(), Error);
auto_pyobject buf = PyBytes_FromString(error.c_str());
if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){
if (NULL == callwrite(Error, *buf)){
return NULL;
}
@ -910,7 +930,7 @@ PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error)
const Target* target = TargetRegistry::getClosestTargetForJIT(error);
if (!target) {
auto_pyobject buf = PyBytes_FromString(error.c_str());
if (NULL == PyObject_CallMethod(Error, "write", "O", *buf)){
if (NULL == callwrite(Error, *buf)){
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

View file

@ -1,16 +1,27 @@
from binding import *
from .namespace import llvm
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
class Argument:
_include_ = 'llvm/Argument.h'
if LLVM_VERSION >= (3, 3):
_include_ = 'llvm/IR/Argument.h'
else:
_include_ = 'llvm/Argument.h'
_downcast_ = Value
addAttr = Method(Void, ref(Attributes))
removeAttr = Method(Void, ref(Attributes))
if LLVM_VERSION >= (3, 3):
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))
getArgNo = Method(cast(Unsigned, int))

View file

@ -2,38 +2,91 @@ from binding import *
from .namespace import llvm
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()
@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))
if LLVM_VERSION >= (3, 3):
Attribute = llvm.Class()
AttributeSet = llvm.Class()
else:
Attributes = llvm.Class()
@AttrBuilder
class AttrBuilder:
if LLVM_VERSION >= (3, 3):
@Attribute
class Attribute:
AttrKind = Enum('''None, Alignment, AlwaysInline,
ByVal, InlineHint, InReg,
MinSize, Naked, Nest, NoAlias,
NoBuiltin, NoCapture, NoDuplicate, NoImplicitFloat,
NoInline, NonLazyBind, NoRedZone, NoReturn,
NoUnwind, OptimizeForSize, ReadNone, ReadOnly,
Returned, ReturnsTwice, SExt, StackAlignment,
StackProtect, StackProtectReq, StackProtectStrong, StructRet,
SanitizeAddress, SanitizeThread, SanitizeMemory, UWTable,
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)
removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal)
@AttrBuilder
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))

View file

@ -124,17 +124,31 @@ class DIBuilder:
ptr(MDNode), # TemplateParms = 0
).require_only(10)
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)
if LLVM_VERSION >= (3, 3):
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(DIType), # DerivedFrom
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,
ref(DIDescriptor), # Scope
@ -186,7 +200,7 @@ class DIBuilder:
ref(DIType), # Ty
)
createTemporaryType = Method(DIType, ref(DIFile)).require_only(0)
#createTemporaryType = Method(DIType, ref(DIFile)).require_only(0)
createForwardDecl = Method(DIType,
unsigned_arg, # Tag

View file

@ -15,7 +15,10 @@ from .GlobalVariable import GlobalVariable
@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_module = Constructor(ptr(Module))

View file

@ -8,7 +8,10 @@ FunctionType = llvm.Class(Type)
@FunctionType
class FunctionType:
_include_ = 'llvm/DerivedTypes.h'
if LLVM_VERSION >= (3, 3):
_include_ = 'llvm/IR/DerivedTypes.h'
else:
_include_ = 'llvm/DerivedTypes.h'
_downcast_ = Type
_get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool))

View file

@ -101,3 +101,5 @@ class ExecutionEngine:
unwrapped = list(map(capsule.unwrap, args))
return self._runFunction(fn, tuple(unwrapped))
finalizeObject = Method(Void)

View file

@ -4,7 +4,10 @@ from .Value import GlobalValue, Constant, Function, Argument, Value
from .Module import Module
from .BasicBlock import BasicBlock
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 .DerivedTypes import FunctionType
from .LLVMContext import LLVMContext
@ -12,7 +15,11 @@ from .CallingConv import CallingConv
@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
getReturnType = Method(ptr(Type))
@ -48,10 +55,17 @@ class Function:
deleteBody = Method()
viewCFG = Method()
viewCFGOnly = Method()
addFnAttr = Method(Void, Attributes.AttrVal)
removeFnAttr = Method(Void, ref(Attributes))
if LLVM_VERSION >= (3, 3):
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)
Create = StaticMethod(ptr(Function),

View file

@ -6,7 +6,10 @@ from .ADT.StringRef import StringRef
@GlobalValue
class GlobalValue:
_include_ = 'llvm/GlobalValue.h'
if LLVM_VERSION >= (3, 3):
_include_ = 'llvm/IR/GlobalValue.h'
else:
_include_ = 'llvm/GlobalValue.h'
LinkageTypes = Enum('''
ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage,

View file

@ -18,7 +18,11 @@ IRBuilder = llvm.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<>'
new = Constructor(ref(LLVMContext))

View file

@ -4,7 +4,10 @@ from .Value import Value
from .DerivedTypes import FunctionType
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)

View file

@ -65,7 +65,10 @@ SynchronizationScope = llvm.Enum('SynchronizationScope',
from .ADT.StringRef import StringRef
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
@ -142,8 +145,12 @@ class CallInst:
getCallingConv = Method(CallingConv.ID)
setCallingConv = Method(Void, CallingConv.ID)
getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned))
addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
if LLVM_VERSION >= (3, 3):
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))
getCalledValue = Method(ptr(Value))
setCalledFunction = Method(Void, ptr(Function))
@ -264,7 +271,10 @@ class UnaryInstruction:
@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
#compare
@ -292,8 +302,12 @@ class InvokeInst:
getCallingConv = Method(CallingConv.ID)
setCallingConv = Method(Void, CallingConv.ID)
getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned))
addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes))
if LLVM_VERSION >= (3, 3):
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))
getCalledValue = Method(ptr(Value))
setCalledFunction = Method(Void, ptr(Function))

View file

@ -3,6 +3,9 @@ from .namespace import llvm
@llvm.Class()
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))

View file

@ -10,30 +10,33 @@ Linker = llvm.Class()
@Linker
class Linker:
ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors')
#ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors')
LinkerMode = Enum('DestroySource, PreserveSource')
_new_w_empty = Constructor(cast(str, StringRef),
cast(str, StringRef),
ref(LLVMContext),
cast(int, Unsigned)).require_only(3)
if LLVM_VERSION >= (3, 3):
new = Constructor(ptr(Module))
else:
_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),
ptr(Module),
cast(int, Unsigned)).require_only(2)
_new_w_existing = Constructor(cast(str, StringRef),
ptr(Module),
cast(int, Unsigned)).require_only(2)
@CustomPythonStaticMethod
def new(progname, module_or_name, *args):
if isinstance(module_or_name, Module):
return _new_w_existing(progname, module_or_name, *args)
else:
return _new_w_empty(progname, module_or_name, *args)
@CustomPythonStaticMethod
def new(progname, module_or_name, *args):
if isinstance(module_or_name, Module):
return _new_w_existing(progname, module_or_name, *args)
else:
return _new_w_empty(progname, module_or_name, *args)
delete = Destructor()
getModule = Method(ptr(Module))
releaseModule = Method(ptr(Module))
getLastError = Method(cast(ConstStdString, str))
#releaseModule = Method(ptr(Module))
#getLastError = Method(cast(ConstStdString, str))
LinkInModule = CustomMethod('Linker_LinkInModule',
PyObjectPtr, # boolean

View file

@ -16,7 +16,10 @@ from .Metadata import NamedMDNode
@Module
class Module:
_include_ = "llvm/Module.h"
if LLVM_VERSION >= (3, 3):
_include_ = "llvm/IR/Module.h"
else:
_include_ = "llvm/Module.h"
# Enumerators
Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64')

View file

@ -1,18 +1,29 @@
from binding import *
from src.namespace import sys
isLittleEndianHost = sys.Function('isLittleEndianHost',
cast(Bool, bool))
isBigEndianHost = sys.Function('isBigEndianHost',
cast(Bool, bool))
getDefaultTargetTriple = sys.Function('getDefaultTargetTriple',
cast(ConstStdString, str))
# llvm 3.3
#getProcessTriple = sys.Function('getProcessTriple',
# cast(ConstStdString, str))
if LLVM_VERSION >= (3, 3):
getProcessTriple = sys.Function('getProcessTriple',
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',
cast(ConstStdString, str))

View file

@ -14,7 +14,7 @@ from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt
@Target
class Target:
getNext = Method(const(ptr(Target)))
getNext = Method(const(ownedptr(Target)))
getName = Method(cast(StdString, str))
getShortDescription = Method(cast(StdString, str))

View file

@ -8,8 +8,10 @@ from src.ADT.StringRef import StringRef
from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc
from src.GlobalValue import GlobalValue
from src.DataLayout import DataLayout
from src.TargetTransformInfo import (ScalarTargetTransformInfo,
VectorTargetTransformInfo)
if LLVM_VERSION < (3, 3):
from src.TargetTransformInfo import (ScalarTargetTransformInfo,
VectorTargetTransformInfo)
from src.PassManager import PassManagerBase
from src.Support.FormattedStream import formatted_raw_ostream
@ -39,9 +41,11 @@ class TargetMachine:
setMCUseDwarfDirectory = Method(Void, cast(bool, Bool))
getDataLayout = Method(const(ownedptr(DataLayout)))
getScalarTargetTransformInfo = Method(const(
if LLVM_VERSION < (3, 3):
getScalarTargetTransformInfo = Method(const(
ownedptr(ScalarTargetTransformInfo)))
getVectorTargetTransformInfo = Method(const(
getVectorTargetTransformInfo = Method(const(
ownedptr(VectorTargetTransformInfo)))
addPassesToEmitFile = Method(cast(bool, Bool),

View file

@ -2,7 +2,10 @@ from binding import *
from src.namespace import llvm
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)
ScalarTargetTransformInfo = llvm.Class()
@ -11,14 +14,17 @@ VectorTargetTransformInfo = llvm.Class()
@ScalarTargetTransformInfo
class ScalarTargetTransformInfo:
delete = Destructor()
if LLVM_VERSION < (3, 3):
delete = Destructor()
@VectorTargetTransformInfo
class VectorTargetTransformInfo:
delete = Destructor()
if LLVM_VERSION < (3, 3):
delete = Destructor()
@TargetTransformInfo
class TargetTransformInfo:
new = Constructor(ptr(ScalarTargetTransformInfo),
ptr(VectorTargetTransformInfo))
if LLVM_VERSION < (3, 3):
new = Constructor(ptr(ScalarTargetTransformInfo),
ptr(VectorTargetTransformInfo))

View file

@ -36,7 +36,11 @@ class PassManagerBuilder:
DisableSimplifyLibCalls = _attr_bool()
DisableUnitAtATime = _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()
LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo),

View file

@ -15,7 +15,10 @@ VectorType = llvm.Class(SequentialType)
@Type
class Type:
_include_ = 'llvm/Type.h'
if LLVM_VERSION >= (3, 3):
_include_ = 'llvm/IR/Type.h'
else:
_include_ = 'llvm/Type.h'
TypeID = Enum('''
VoidTyID, HalfTyID, FloatTyID, DoubleTyID,

View file

@ -4,7 +4,10 @@ from .ADT.StringRef import StringRef
@ValueSymbolTable
class ValueSymbolTable:
_include_ = 'llvm/ValueSymbolTable.h'
if LLVM_VERSION >= (3, 3):
_include_ = 'llvm/IR/ValueSymbolTable.h'
else:
_include_ = 'llvm/ValueSymbolTable.h'
new = Constructor()
delete = Destructor()
lookup = Method(ptr(Value), cast(str, StringRef))

View file

@ -36,6 +36,7 @@ def run_llvm_config(extra_args):
return stdout.decode().strip()
llvm_version = run_llvm_config(['--version'])
print('LLVM version = %r' % llvm_version)
targets_built = run_llvm_config(['--targets-built'])
@ -61,7 +62,12 @@ def auto_intrinsic_gen(incdir):
# let's do auto intrinsic generation
print("Generate intrinsic IDs")
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:
intrgen.gen(path, fout)
@ -119,7 +125,7 @@ else:
extra_components = list(extra_components & enabled_components)
libs_core, objs_core = get_libs_and_objs(
['core', 'analysis', 'scalaropts', 'executionengine',
['core', 'analysis', 'scalaropts', 'executionengine', 'mcjit',
'jit', 'native', 'interpreter', 'bitreader', 'bitwriter',
'instrumentation', 'ipa', 'ipo', 'transformutils',
'asmparser', 'linker', 'support', 'vectorize']
@ -181,7 +187,8 @@ setup(
'llvm_cbuilder',
'llpython',
'llvm_array',
'llvmpy.api', 'llvmpy.api.llvm'],
'llvmpy.api', 'llvmpy.api.llvm',],
package_data = {'llvm': ['llrt/*.ll']},
py_modules = ['llvmpy',
'llvmpy._capsule',
'llvmpy._api',