Add printf() and friends.
Disable logging in old tests.
This commit is contained in:
parent
673ada6a4e
commit
0654e00ab1
5 changed files with 105 additions and 7 deletions
|
|
@ -6,7 +6,6 @@ import contextlib
|
||||||
import llvm.core as lc
|
import llvm.core as lc
|
||||||
import llvm.ee as le
|
import llvm.ee as le
|
||||||
|
|
||||||
|
|
||||||
def _is_int(ty):
|
def _is_int(ty):
|
||||||
return isinstance(ty, lc.IntegerType)
|
return isinstance(ty, lc.IntegerType)
|
||||||
|
|
||||||
|
|
@ -31,6 +30,9 @@ def _is_cstruct(ty):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _list_values(iterable):
|
||||||
|
return [i.value for i in iterable]
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _change_block_temporarily(builder, bb):
|
def _change_block_temporarily(builder, bb):
|
||||||
origbb = builder.basic_block
|
origbb = builder.basic_block
|
||||||
|
|
@ -111,7 +113,6 @@ class _Loop(object):
|
||||||
def close(self):
|
def close(self):
|
||||||
self.parent.builder.position_at_end(self._bbend)
|
self.parent.builder.position_at_end(self._bbend)
|
||||||
|
|
||||||
|
|
||||||
class CBuilder(object):
|
class CBuilder(object):
|
||||||
'''
|
'''
|
||||||
A wrapper class for features in llvm-py package
|
A wrapper class for features in llvm-py package
|
||||||
|
|
@ -136,6 +137,32 @@ class CBuilder(object):
|
||||||
func = mod.add_function(functype, name=name)
|
func = mod.add_function(functype, name=name)
|
||||||
return CBuilder(func)
|
return CBuilder(func)
|
||||||
|
|
||||||
|
def printf(self, fmt, *args):
|
||||||
|
mod = self.function.module
|
||||||
|
int_t = lc.Type.int()
|
||||||
|
char_ptr_t = lc.Type.pointer(lc.Type.int(8))
|
||||||
|
functype = lc.Type.function(int_t, [char_ptr_t], True)
|
||||||
|
printf = mod.get_or_insert_function(functype, name='printf')
|
||||||
|
ret = self.builder.call(printf, [fmt.value]+_list_values(args))
|
||||||
|
return CTemp(self, ret)
|
||||||
|
|
||||||
|
def debug(self, *args):
|
||||||
|
type_mapper = {
|
||||||
|
'i32': '%d',
|
||||||
|
'double': '%e',
|
||||||
|
}
|
||||||
|
itemsfmt = []
|
||||||
|
items = []
|
||||||
|
for i in args:
|
||||||
|
if isinstance(i, str):
|
||||||
|
itemsfmt.append(i.replace('%', '%%'))
|
||||||
|
else:
|
||||||
|
ty = type_mapper[str(i.type)]
|
||||||
|
itemsfmt.append(ty)
|
||||||
|
items.append(i)
|
||||||
|
fmt = ' '.join(itemsfmt) + '\n'
|
||||||
|
return self.printf(self.constant_string(fmt), *items)
|
||||||
|
|
||||||
def var(self, ty, value=None, name=''):
|
def var(self, ty, value=None, name=''):
|
||||||
'''
|
'''
|
||||||
Only allocate in the first block
|
Only allocate in the first block
|
||||||
|
|
@ -150,7 +177,7 @@ class CBuilder(object):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
if isinstance(value, CValue):
|
if isinstance(value, CValue):
|
||||||
value = value.value
|
value = value.value
|
||||||
if not isinstance(value, lc.Value):
|
elif not isinstance(value, lc.Value):
|
||||||
value = self.constant(ty, value).value
|
value = self.constant(ty, value).value
|
||||||
self.builder.store(value, ptr)
|
self.builder.store(value, ptr)
|
||||||
if is_cstruct:
|
if is_cstruct:
|
||||||
|
|
@ -213,6 +240,16 @@ class CBuilder(object):
|
||||||
res = lc.Constant.null(ty)
|
res = lc.Constant.null(ty)
|
||||||
return CTemp(self, res)
|
return CTemp(self, res)
|
||||||
|
|
||||||
|
def constant_string(self, string):
|
||||||
|
mod = self.function.module
|
||||||
|
name = '.conststr.%x' % hash(string)
|
||||||
|
content = lc.Constant.stringz(string)
|
||||||
|
globalstr = mod.add_global_variable(content.type, name=name)
|
||||||
|
globalstr.initializer = content
|
||||||
|
ptr = mod.add_global_variable(lc.Type.pointer(content.type.element),
|
||||||
|
name=name+".ptr")
|
||||||
|
return CTemp(self, globalstr.bitcast(lc.Type.pointer(content.type.element)))
|
||||||
|
|
||||||
def get_intrinsic(self, intrinsic_id, tys):
|
def get_intrinsic(self, intrinsic_id, tys):
|
||||||
lfunc = lc.Function.intrinsic(self.function.module, intrinsic_id, tys)
|
lfunc = lc.Function.intrinsic(self.function.module, intrinsic_id, tys)
|
||||||
return CFunc(self, lfunc)
|
return CFunc(self, lfunc)
|
||||||
|
|
@ -515,7 +552,7 @@ class CFunc(CValue):
|
||||||
self.function = func
|
self.function = func
|
||||||
|
|
||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
arg_value = list(map(lambda x: x.value, args))
|
arg_value = _list_values(args)
|
||||||
res = self.parent.builder.call(self.function, arg_value)
|
res = self.parent.builder.call(self.function, arg_value)
|
||||||
return CTemp(self.parent, res)
|
return CTemp(self.parent, res)
|
||||||
|
|
||||||
|
|
@ -667,3 +704,4 @@ class CStruct(CValue):
|
||||||
gep = self.parent.builder.gep(ptr, [makeind(0), makeind(i)])
|
gep = self.parent.builder.gep(ptr, [makeind(0), makeind(i)])
|
||||||
setattr(self, fd, CVar(self.parent, gep))
|
setattr(self, fd, CVar(self.parent, gep))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from llvm_cbuilder import *
|
||||||
import llvm_cbuilder.shortnames as C
|
import llvm_cbuilder.shortnames as C
|
||||||
import unittest, logging
|
import unittest, logging
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
# logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
NUM_OF_THREAD = 4
|
NUM_OF_THREAD = 4
|
||||||
REPEAT = 10000
|
REPEAT = 10000
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from llvm_cbuilder import *
|
||||||
import llvm_cbuilder.shortnames as C
|
import llvm_cbuilder.shortnames as C
|
||||||
import unittest, logging
|
import unittest, logging
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
# logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
NUM_OF_THREAD = 4
|
NUM_OF_THREAD = 4
|
||||||
REPEAT = 10000
|
REPEAT = 10000
|
||||||
|
|
|
||||||
60
tests/test_print.py
Normal file
60
tests/test_print.py
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
from llvm.core import *
|
||||||
|
from llvm.passes import *
|
||||||
|
from llvm.ee import *
|
||||||
|
from llvm_cbuilder import *
|
||||||
|
import llvm_cbuilder.shortnames as C
|
||||||
|
import sys, unittest, logging
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
def gen_debugprint(mod):
|
||||||
|
functype = Type.function(C.void, [])
|
||||||
|
func = mod.add_function(functype, 'debugprint')
|
||||||
|
|
||||||
|
cb = CBuilder(func)
|
||||||
|
fmt = cb.constant_string("Show %d %.3f %.3e\n")
|
||||||
|
|
||||||
|
an_int = cb.constant(C.int, 123)
|
||||||
|
a_float = cb.constant(C.double, 1.234)
|
||||||
|
a_double = cb.constant(C.double, 1e-31)
|
||||||
|
cb.printf(fmt, an_int, a_float, a_double)
|
||||||
|
|
||||||
|
cb.debug('an_int =', an_int, 'a_float =', a_float, 'a_double =', a_double)
|
||||||
|
|
||||||
|
cb.ret()
|
||||||
|
cb.close()
|
||||||
|
return func
|
||||||
|
|
||||||
|
def main_debugprint():
|
||||||
|
# generate code
|
||||||
|
mod = Module.new(__name__)
|
||||||
|
lfunc = gen_debugprint(mod)
|
||||||
|
logging.debug(mod)
|
||||||
|
mod.verify()
|
||||||
|
# run
|
||||||
|
exe = CExecutor(mod)
|
||||||
|
func = exe.get_ctype_function(lfunc, 'void')
|
||||||
|
func()
|
||||||
|
|
||||||
|
class TestPrint(unittest.TestCase):
|
||||||
|
def test_debugprint(self):
|
||||||
|
p = Popen(["python", "test_print.py", "-child"], stdout=PIPE)
|
||||||
|
p.wait()
|
||||||
|
|
||||||
|
lines = p.stdout.read().decode().splitlines(False)
|
||||||
|
|
||||||
|
expect = [
|
||||||
|
'Show 123 1.234 1.000e-31',
|
||||||
|
'an_int = 123 a_float = 1.234000e+00 a_double = 1.000000e-31',
|
||||||
|
]
|
||||||
|
self.assertEqual(expect, lines)
|
||||||
|
|
||||||
|
p.stdout.close()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
if sys.argv[1] == '-child':
|
||||||
|
main_debugprint()
|
||||||
|
except IndexError:
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@ from llvm_cbuilder import *
|
||||||
import llvm_cbuilder.shortnames as C
|
import llvm_cbuilder.shortnames as C
|
||||||
import unittest, logging
|
import unittest, logging
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
# logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
NUM_OF_THREAD = 4
|
NUM_OF_THREAD = 4
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue