def test_func_simple(): # -------------------- flowgraph building -------------------- # def f(x): # return x+1 x = Variable("x") x.concretetype = Signed result = Variable("result") result.concretetype = Signed one = Constant(1) one.concretetype = Signed op = SpaceOperation("int_add", [x, one], result) block = Block([x]) graph = FunctionGraph("f", block) block.operations.append(op) block.closeblock(Link([result], graph.returnblock)) graph.getreturnvar().concretetype = Signed # -------------------- end -------------------- F = FuncType([Signed], Signed) f = functionptr(F, "f", graph=graph) db = LowLevelDatabase() db.get(f) db.complete() dump_on_stdout(db) S = GcStruct('testing', ('fptr', Ptr(F))) s = malloc(S) s.fptr = f db = LowLevelDatabase() db.get(s) db.complete() dump_on_stdout(db)
def test_primitive(): db = LowLevelDatabase() if is_emulated_long: assert db.get(5) == '5LL' else: assert db.get(5) == '5L' assert db.get(True) == '1'
def generate_macro_wrapper(name, macro, functype, eci): """Wraps a function-like macro inside a real function, and expose it with llexternal.""" # Generate the function call from rpython.translator.c.database import LowLevelDatabase from rpython.translator.c.support import cdecl wrapper_name = 'pypy_macro_wrapper_%s' % (name,) argnames = ['arg%d' % (i,) for i in range(len(functype.ARGS))] db = LowLevelDatabase() implementationtypename = db.gettype(functype, argnames=argnames) if functype.RESULT is lltype.Void: pattern = '%s%s { %s(%s); }' else: pattern = '%s%s { return %s(%s); }' source = pattern % ( 'RPY_EXTERN ', cdecl(implementationtypename, wrapper_name), macro, ', '.join(argnames)) # Now stuff this source into a "companion" eci that will be used # by ll2ctypes. We replace eci._with_ctypes, so that only one # shared library is actually compiled (when ll2ctypes calls the # first function) ctypes_eci = eci.merge(ExternalCompilationInfo( separate_module_sources=[source], )) if hasattr(eci, '_with_ctypes'): ctypes_eci = eci._with_ctypes.merge(ctypes_eci) eci._with_ctypes = ctypes_eci func = llexternal(wrapper_name, functype.ARGS, functype.RESULT, compilation_info=eci, _nowrapper=True) # _nowrapper=True returns a pointer which is not hashable return lambda *args: func(*args)
def test_recursive_struct(): S = GcForwardReference() S.become(GcStruct('testing', ('p', Ptr(S)))) p = malloc(S) p.p = p db = LowLevelDatabase() db.get(p) db.complete() dump_on_stdout(db)
def test_struct(): db = LowLevelDatabase() pfx = db.namespace.global_prefix + 'g_' S = GcStruct('test', ('x', Signed)) s = malloc(S) s.x = 42 assert db.get(s).startswith('(&' + pfx) assert db.containernodes.keys() == [s._obj] assert db.structdefnodes.keys() == [S]
def test_array_of_char(): A = GcArray(Char) a = malloc(A, 11) for i, c in zip(range(11), 'hello world'): a[i] = c db = LowLevelDatabase() db.get(a) db.complete() dump_on_stdout(db)
def test_name_gcref(): from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.rtyper import rclass from rpython.translator.c import primitive from rpython.translator.c.database import LowLevelDatabase x = lltype.cast_int_to_ptr(rclass.OBJECTPTR, 19) y = lltype.cast_opaque_ptr(llmemory.GCREF, x) db = LowLevelDatabase() assert primitive.name_gcref(y, db) == "((void*) 19)"
def build_database(self): translator = self.translator gcpolicyclass = self.get_gcpolicyclass() if self.config.translation.gcrootfinder == "asmgcc": if not self.standalone: raise NotImplementedError("--gcrootfinder=asmgcc requires standalone") exctransformer = translator.getexceptiontransformer() db = LowLevelDatabase(translator, standalone=self.standalone, gcpolicyclass=gcpolicyclass, gchooks=self.gchooks, exctransformer=exctransformer, thread_enabled=self.config.translation.thread, sandbox=self.config.translation.sandbox, split_gc_address_space= self.config.translation.split_gc_address_space, reverse_debugger= self.config.translation.reverse_debugger) self.db = db # give the gc a chance to register interest in the start-up functions it # need (we call this for its side-effects of db.get()) list(db.gcpolicy.gc_startup_code()) # build entrypoint and eventually other things to expose pf = self.getentrypointptr() if isinstance(pf, list): for one_pf in pf: db.get(one_pf) self.c_entrypoint_name = None else: pfname = db.get(pf) for func, _ in self.secondary_entrypoints: bk = translator.annotator.bookkeeper db.get(getfunctionptr(bk.getdesc(func).getuniquegraph())) self.c_entrypoint_name = pfname if self.config.translation.reverse_debugger: from rpython.translator.revdb import gencsupp gencsupp.prepare_database(db) for obj in exports.EXPORTS_obj2name.keys(): db.getcontainernode(obj) exports.clear() for ll_func in db.translator._call_at_startup: db.get(ll_func) db.complete() self.collect_compilation_info(db) return db
def test_typedef(): A = Typedef(Signed, 'test4') db = LowLevelDatabase() assert db.gettype(A) == "test4 @" PA = CArrayPtr(A) assert db.gettype(PA) == "test4 *@" F = FuncType((A, ), A) assert db.gettype(F) == "test4 (@)(test4)"
def test_inlined_struct(): db = LowLevelDatabase() pfx = db.namespace.global_prefix + 'g_' S = GcStruct('test', ('x', Struct('subtest', ('y', Signed)))) s = malloc(S) s.x.y = 42 assert db.get(s).startswith('(&' + pfx) assert db.containernodes.keys() == [s._obj] db.complete() assert len(db.structdefnodes) == 2 assert S in db.structdefnodes assert S.x in db.structdefnodes
def test_typedef(self, space): from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() assert PyPy_TypedefTest1.api_func.get_c_restype(db) == 'Signed' assert PyPy_TypedefTest1.api_func.get_c_args(db) == 'Signed arg0' assert PyPy_TypedefTest2.api_func.get_c_restype(db) == 'Signed *' assert PyPy_TypedefTest2.api_func.get_c_args(db) == 'Signed *arg0' PyPy_TypedefTest1(space, 0) ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw') ppos[0] = 0 PyPy_TypedefTest2(space, ppos) lltype.free(ppos, flavor='raw')
def test_write_func(): db = LowLevelDatabase() cdef = """ typedef ssize_t Py_ssize_t; """ cts = parse_source(cdef) cdecl = "Py_ssize_t * some_func(Py_ssize_t*)" decl = cts.parse_func(cdecl) api_function = ApiFunction( decl.get_llargs(cts), decl.get_llresult(cts), lambda space, x: None, cdecl=decl) assert (api_function.get_api_decl('some_func', db) == "PyAPI_FUNC(Py_ssize_t *) some_func(Py_ssize_t * arg0);")
def test_codegen_2(): db = LowLevelDatabase() A = GcArray(('x', Signed)) S = GcStruct('test', ('aptr', Ptr(A))) a = malloc(A, 3) a[0].x = 100 a[1].x = 101 a[2].x = 102 s = malloc(S) s.aptr = a db.get(s) db.complete() dump_on_stdout(db)
def test_codegen(): db = LowLevelDatabase() U = Struct('inlined', ('z', Signed)) T = Struct('subtest', ('y', Signed)) S = Struct('test', ('x', Ptr(T)), ('u', U), ('p', Ptr(U))) s = malloc(S, immortal=True) s.x = malloc(T, immortal=True) s.x.y = 42 s.u.z = -100 s.p = s.u db.get(s) db.complete() dump_on_stdout(db)
def test_typedef(self, space): from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() assert (api.c_function_signature( db, api.FUNCTIONS['PyPy_TypedefTest1']) == ('Py_ssize_t', 'Py_ssize_t arg0')) assert (api.c_function_signature( db, api.FUNCTIONS['PyPy_TypedefTest2']) == ('Py_ssize_t *', 'Py_ssize_t *arg0')) PyPy_TypedefTest1(space, 0) ppos = lltype.malloc(api.Py_ssize_tP.TO, 1, flavor='raw') ppos[0] = 0 PyPy_TypedefTest2(space, ppos) lltype.free(ppos, flavor='raw')
def test_function_call(): def g(x, y): return x - y def f(x): return g(1, x) t, graph = makegraph(f, [int]) F = FuncType([Signed], Signed) f = functionptr(F, "f", graph=graph) db = LowLevelDatabase(t, exctransformer=t.getexceptiontransformer()) db.get(f) db.complete() dump_on_stdout(db)
def test_malloc(): S = GcStruct('testing', ('x', Signed), ('y', Signed)) def ll_f(x): p = malloc(S) p.x = x p.y = x + 1 return p.x * p.y t, graph = makegraph(ll_f, [int]) db = LowLevelDatabase(t, exctransformer=t.getexceptiontransformer()) db.get(getfunctionptr(graph)) db.complete() dump_on_stdout(db)
def test_codegen_3(): db = LowLevelDatabase() A = Struct('varsizedstuff', ('x', Signed), ('y', Array(('i', Signed)))) S = Struct('test', ('aptr', Ptr(A)), ('anitem', Ptr(A.y.OF)), ('anarray', Ptr(A.y))) a = malloc(A, 3, immortal=True) a.x = 99 a.y[0].i = 100 a.y[1].i = 101 a.y[2].i = 102 s = malloc(S, immortal=True) s.aptr = a s.anitem = a.y[1] s.anarray = a.y db.get(s) db.complete() dump_on_stdout(db)
def setup_library(space): "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() generate_macros(export_symbols, prefix='PyPy') functions = generate_decls_and_callbacks(db, [], api_struct=False) code = "#include <Python.h>\n" + "\n".join(functions) eci = build_eci(False, export_symbols, code) space.fromcache(State).install_dll(eci) run_bootstrap_functions(space) setup_va_functions(eci) # populate static data for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") if name.startswith('PyExc_'): name = '_' + name from pypy.module import cpyext w_obj = eval(expr) if typ in ('PyObject*', 'PyTypeObject*'): struct_ptr = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': continue else: assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) for name, func in FUNCTIONS.iteritems(): newname = mangle_name('PyPy', name) or name deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, relax=True) deco(func.get_wrapper(space)) setup_init_functions(eci, translating=True) trunk_include = pypydir.dirpath() / 'include' copy_header_files(trunk_include)
def test_multiple_malloc(): S1 = GcStruct('testing1', ('x', Signed), ('y', Signed)) S = GcStruct('testing', ('ptr1', Ptr(S1)), ('ptr2', Ptr(S1)), ('z', Signed)) def ll_f(x): ptr1 = malloc(S1) ptr1.x = x ptr2 = malloc(S1) ptr2.x = x + 1 s = malloc(S) s.ptr1 = ptr1 s.ptr2 = ptr2 return s.ptr1.x * s.ptr2.x t, graph = makegraph(ll_f, [int]) db = LowLevelDatabase(t, exctransformer=t.getexceptiontransformer()) db.get(getfunctionptr(graph)) db.complete() dump_on_stdout(db)
def build_bridge(space): "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() generate_macros(export_symbols, prefix='cpyexttest') # Structure declaration code members = [] structindex = {} for name, func in sorted(FUNCTIONS.iteritems()): restype, args = c_function_signature(db, func) members.append('%s (*%s)(%s);' % (restype, name, args)) structindex[name] = len(structindex) structmembers = '\n'.join(members) struct_declaration_code = """\ struct PyPyAPI { %(members)s } _pypyAPI; RPY_EXTERN struct PyPyAPI* pypyAPI = &_pypyAPI; """ % dict(members=structmembers) functions = generate_decls_and_callbacks(db, export_symbols) global_objects = [] for name, (typ, expr) in GLOBALS.iteritems(): if "#" in name: continue if typ == 'PyDateTime_CAPI*': continue elif name.startswith('PyExc_'): global_objects.append('%s _%s;' % (typ[:-1], name)) else: global_objects.append('%s %s = NULL;' % (typ, name)) global_code = '\n'.join(global_objects) prologue = ("#include <Python.h>\n" "#include <src/thread.c>\n") code = (prologue + struct_declaration_code + global_code + '\n' + '\n'.join(functions)) eci = build_eci(True, export_symbols, code) eci = eci.compile_shared_lib( outputfilename=str(udir / "module_cache" / "pypyapi")) modulename = py.path.local(eci.libraries[-1]) run_bootstrap_functions(space) # load the bridge, and init structure import ctypes bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL) space.fromcache(State).install_dll(eci) # populate static data for name, (typ, expr) in GLOBALS.iteritems(): from pypy.module import cpyext w_obj = eval(expr) if name.endswith('#'): name = name[:-1] isptr = False else: isptr = True if name.startswith('PyExc_'): isptr = False INTERPLEVEL_API[name] = w_obj name = name.replace('Py', 'cpyexttest') if isptr: ptr = ctypes.c_void_p.in_dll(bridge, name) if typ == 'PyObject*': value = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': value = w_obj else: assert False, "Unknown static pointer: %s %s" % (typ, name) ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value), ctypes.c_void_p).value elif typ in ('PyObject*', 'PyTypeObject*'): if name.startswith('PyPyExc_') or name.startswith('cpyexttestExc_'): # we already have the pointer in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll) else: # we have a structure, get its address in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name) py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll)) from pypy.module.cpyext.pyobject import ( track_reference, get_typedescr) w_type = space.type(w_obj) typedescr = get_typedescr(w_type.instancetypedef) py_obj.c_ob_refcnt = 1 py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) typedescr.attach(space, py_obj, w_obj) track_reference(space, py_obj, w_obj) else: assert False, "Unknown static object: %s %s" % (typ, name) pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI') # implement structure initialization code for name, func in FUNCTIONS.iteritems(): if name.startswith('cpyext_'): # XXX hack continue pypyAPI[structindex[name]] = ctypes.cast( ll2ctypes.lltype2ctypes(func.get_llhelper(space)), ctypes.c_void_p) setup_va_functions(eci) setup_init_functions(eci, translating=False) return modulename.new(ext='')
def test_primitive(): db = LowLevelDatabase() assert db.get(5) == '5L' assert db.get(True) == '1'
def test_intlong_unique(): A = INT_real B = Signed db = LowLevelDatabase() assert db.gettype(A) == "int @" assert db.gettype(B) == "Signed @"
def test_voidp(): A = VOIDP db = LowLevelDatabase() assert db.gettype(A) == "void *@"