llvmpy/test/constants.py
Siu Kwan Lam a09394cacd Fix a lots of bugs in the newbinding to pass all the tests.
NOTE: debug info has not been implemented yet.
2013-02-13 15:52:53 -06:00

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()