297 lines
8.9 KiB
Python
297 lines
8.9 KiB
Python
#! /usr/bin/env python
|
|
'''
|
|
Test and stress Constants.
|
|
'''
|
|
import unittest
|
|
import logging
|
|
|
|
from llvm.core import *
|
|
from llvm.ee import *
|
|
from ctypes import *
|
|
|
|
|
|
# logging.basicConfig(level=logging.DEBUG)
|
|
|
|
def _build_test_module(datatype, constants):
|
|
mod = Module.new('module_test_const_%s' % datatype)
|
|
fnty_callback = Type.function(Type.void(), [datatype])
|
|
fnty_subject = Type.function(Type.void(), [Type.pointer(fnty_callback)])
|
|
func_subject = mod.add_function(fnty_subject, 'test_const_%s' % datatype)
|
|
|
|
bb_entry = func_subject.append_basic_block('entry')
|
|
builder = Builder.new(bb_entry)
|
|
|
|
for k in constants:
|
|
builder.call(func_subject.args[0], [k])
|
|
|
|
builder.ret_void()
|
|
|
|
func_subject.verify()
|
|
|
|
return mod, func_subject
|
|
|
|
def _build_test_module_array(datatype, constants):
|
|
mod = Module.new('module_test_const_%s' % datatype)
|
|
fnty_callback = Type.function(Type.void(), [datatype])
|
|
fnty_subject = Type.function(Type.void(), [Type.pointer(fnty_callback)])
|
|
func_subject = mod.add_function(fnty_subject, 'test_const_%s' % datatype)
|
|
|
|
bb_entry = func_subject.append_basic_block('entry')
|
|
builder = Builder.new(bb_entry)
|
|
|
|
|
|
for k in constants:
|
|
ptr = builder.alloca(k.type)
|
|
builder.store(k, ptr)
|
|
builder.call(func_subject.args[0],
|
|
[builder.gep(ptr, [Constant.int(Type.int(), 0)]*2)])
|
|
|
|
builder.ret_void()
|
|
|
|
func_subject.verify()
|
|
|
|
return mod, func_subject
|
|
|
|
def _build_test_module_struct(datatype, constants):
|
|
mod = Module.new('module_test_const_%s' % datatype)
|
|
fnty_callback = Type.function(Type.void(), [datatype])
|
|
fnty_subject = Type.function(Type.void(), [Type.pointer(fnty_callback)])
|
|
func_subject = mod.add_function(fnty_subject, 'test_const_%s' % datatype)
|
|
|
|
bb_entry = func_subject.append_basic_block('entry')
|
|
builder = Builder.new(bb_entry)
|
|
|
|
for k in constants:
|
|
ptr = builder.alloca(k.type)
|
|
builder.store(k, ptr)
|
|
builder.call(func_subject.args[0], [ptr])
|
|
|
|
builder.ret_void()
|
|
|
|
func_subject.verify()
|
|
|
|
return mod, func_subject
|
|
|
|
class TestConstants(unittest.TestCase):
|
|
def test_const_int(self):
|
|
from random import randint
|
|
values = [0, -1, 1, 0xfffffffe, 0xffffffff, 0x100000000]
|
|
values += [randint(0, 0xffffffff) for x in range(100)]
|
|
|
|
constant_list = map(lambda X: Constant.int(Type.int(), X), values)
|
|
mod, func_subject = _build_test_module(Type.int(), constant_list)
|
|
|
|
# done function generation
|
|
logging.debug(func_subject)
|
|
|
|
# prepare execution
|
|
ee = ExecutionEngine.new(mod)
|
|
|
|
cf_callback = CFUNCTYPE(None, c_uint32)
|
|
cf_test = CFUNCTYPE(None, cf_callback)
|
|
|
|
test_subject = cf_test(ee.get_pointer_to_function(func_subject))
|
|
|
|
# setup callback
|
|
results = []
|
|
def callback(value):
|
|
results.append(value)
|
|
|
|
test_subject(cf_callback(callback))
|
|
|
|
# check result
|
|
for result, golden in zip(results, values):
|
|
self.assertEqual(result, golden & 0xffffffff)
|
|
|
|
def test_const_float(self):
|
|
from random import random
|
|
values = [0., 1., -1.] + [random() for x in range(100)]
|
|
|
|
constant_list = map(lambda X: Constant.real(Type.float(), X), values)
|
|
mod, func_subject = _build_test_module(Type.float(), constant_list)
|
|
|
|
# done function generation
|
|
logging.debug(func_subject)
|
|
|
|
# prepare execution
|
|
ee = ExecutionEngine.new(mod)
|
|
|
|
cf_callback = CFUNCTYPE(None, c_float)
|
|
cf_test = CFUNCTYPE(None, cf_callback)
|
|
|
|
test_subject = cf_test(ee.get_pointer_to_function(func_subject))
|
|
|
|
# setup callback
|
|
results = []
|
|
def callback(value):
|
|
results.append(value)
|
|
|
|
test_subject(cf_callback(callback))
|
|
|
|
# check result
|
|
for result, golden in zip(results, values):
|
|
if golden == 0:
|
|
self.assertEqual(result, golden)
|
|
else:
|
|
self.assert_(abs(result-golden)/golden < 1e-7)
|
|
|
|
def test_const_double(self):
|
|
from random import random
|
|
values = [0., 1., -1.] + [random() for x in range(100)]
|
|
|
|
constant_list = map(lambda X: Constant.real(Type.double(), X), values)
|
|
mod, func_subject = _build_test_module(Type.double(), constant_list)
|
|
|
|
# done function generation
|
|
logging.debug(func_subject)
|
|
|
|
# prepare execution
|
|
ee = ExecutionEngine.new(mod)
|
|
|
|
cf_callback = CFUNCTYPE(None, c_double)
|
|
cf_test = CFUNCTYPE(None, cf_callback)
|
|
|
|
test_subject = cf_test(ee.get_pointer_to_function(func_subject))
|
|
|
|
# setup callback
|
|
results = []
|
|
def callback(value):
|
|
results.append(value)
|
|
|
|
test_subject(cf_callback(callback))
|
|
|
|
# check result
|
|
for result, golden in zip(results, values):
|
|
self.assertEqual(result, golden)
|
|
|
|
def test_const_string(self):
|
|
values = ["hello", "world", "", "\n"]
|
|
|
|
constant_list = map(Constant.stringz, values)
|
|
mod, func_subject = _build_test_module_array(Type.pointer(Type.int(8)),
|
|
constant_list)
|
|
|
|
# done function generation
|
|
logging.debug(func_subject)
|
|
|
|
# prepare execution
|
|
ee = ExecutionEngine.new(mod)
|
|
|
|
cf_callback = CFUNCTYPE(None, c_char_p)
|
|
cf_test = CFUNCTYPE(None, cf_callback)
|
|
|
|
test_subject = cf_test(ee.get_pointer_to_function(func_subject))
|
|
|
|
# setup callback
|
|
results = []
|
|
def callback(value):
|
|
results.append(value)
|
|
|
|
test_subject(cf_callback(callback))
|
|
|
|
# check result
|
|
for result, golden in zip(results, values):
|
|
self.assertEqual(result.decode(), golden)
|
|
|
|
def test_const_struct(self):
|
|
from random import randint, random
|
|
values = [
|
|
(0, 0., 0.),
|
|
(-1, -1., -1.),
|
|
(1, 1., 1.),
|
|
] + [(randint(0, 0xffffffff), random(), random()) for _ in range(100)]
|
|
|
|
struct_type = Type.struct([Type.int(), Type.float(), Type.double()])
|
|
|
|
def map_constant(packed_values):
|
|
vi, vf, vd = packed_values
|
|
return Constant.struct([
|
|
Constant.int(Type.int(), vi),
|
|
Constant.real(Type.float(), vf),
|
|
Constant.real(Type.double(), vd),
|
|
])
|
|
|
|
constant_list = map(map_constant, values)
|
|
|
|
mod, func_subject = _build_test_module_struct(Type.pointer(struct_type),
|
|
constant_list)
|
|
|
|
# done function generation
|
|
logging.debug(func_subject)
|
|
|
|
# prepare execution
|
|
ee = ExecutionEngine.new(mod)
|
|
|
|
class c_struct_type(Structure):
|
|
_fields_ = [ ('vi', c_uint32),
|
|
('vf', c_float),
|
|
('vd', c_double), ]
|
|
|
|
def __iter__(self):
|
|
return iter([self.vi, self.vf, self.vd])
|
|
|
|
cf_callback = CFUNCTYPE(None, POINTER(c_struct_type))
|
|
cf_test = CFUNCTYPE(None, cf_callback)
|
|
|
|
test_subject = cf_test(ee.get_pointer_to_function(func_subject))
|
|
|
|
# setup callback
|
|
results = []
|
|
def callback(value):
|
|
results.append(tuple(value[0]))
|
|
|
|
test_subject(cf_callback(callback))
|
|
|
|
# check result
|
|
for result, golden in zip(results, values):
|
|
self.assertEqual(result[0], golden[0] & 0xffffffff)
|
|
if golden[1] == 0:
|
|
self.assertEqual(result[1], golden[1])
|
|
else:
|
|
self.assert_(abs(result[1]-golden[1])/golden[1] < 1e-7)
|
|
self.assertEqual(result[2], golden[2])
|
|
|
|
def test_const_vector(self):
|
|
from random import randint
|
|
randgen = lambda: randint(0, 0xffffffff)
|
|
values = [
|
|
(0, 0, 0, 0),
|
|
(1, 1, 1, 1),
|
|
(-1, -1, -1, -1),
|
|
] + [ (randgen(), randgen(), randgen(), randgen()) for _ in range(100) ]
|
|
|
|
def map_constant(packed_values):
|
|
consts = [ Constant.int(Type.int(), i) for i in packed_values ]
|
|
return Constant.vector(consts)
|
|
|
|
constant_list = map(map_constant, values)
|
|
mod, func_subject = _build_test_module_array(Type.pointer(Type.int()),
|
|
constant_list)
|
|
|
|
# done function generation
|
|
logging.debug(func_subject)
|
|
|
|
# prepare execution
|
|
ee = ExecutionEngine.new(mod)
|
|
|
|
cf_callback = CFUNCTYPE(None, POINTER(c_uint32))
|
|
cf_test = CFUNCTYPE(None, cf_callback)
|
|
|
|
test_subject = cf_test(ee.get_pointer_to_function(func_subject))
|
|
|
|
# setup callback
|
|
results = []
|
|
def callback(value):
|
|
results.append(tuple(value[0:4]))
|
|
|
|
test_subject(cf_callback(callback))
|
|
|
|
# check result
|
|
for result, golden in zip(results, values):
|
|
self.assertEqual(result,
|
|
tuple(map(lambda X: X & 0xffffffff, golden)))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|
|
|