1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
import types
from rpython.flowspace.model import FunctionGraph
from rpython.rtyper.lltypesystem import lltype, rstr, rlist
from rpython.rtyper.lltypesystem.rstr import STR, mallocstr
from rpython.translator.c.support import cdecl
def find_list_of_str(rtyper):
for r in rtyper.reprs.itervalues():
if isinstance(r, rlist.ListRepr) and r.item_repr is rstr.string_repr:
return r.lowleveltype.TO
return None
def predeclare_common_types(db, rtyper):
# Common types
yield ('RPyString', STR)
LIST_OF_STR = find_list_of_str(rtyper)
if LIST_OF_STR is not None:
yield ('RPyListOfString', LIST_OF_STR)
def predeclare_utility_functions(db, rtyper):
# Common utility functions
def RPyString_New(length=lltype.Signed):
return mallocstr(length)
# !!!
# be extremely careful passing a gc tracked object
# from such an helper result to another one
# as argument, this could result in leaks
# Such result should be only from C code
# returned directly as results
LIST_OF_STR = find_list_of_str(rtyper)
if LIST_OF_STR is not None:
p = lltype.Ptr(LIST_OF_STR)
def _RPyListOfString_New(length=lltype.Signed):
return LIST_OF_STR.ll_newlist(length)
def _RPyListOfString_SetItem(l=p,
index=lltype.Signed,
newstring=lltype.Ptr(STR)):
rlist.ll_setitem_nonneg(rlist.dum_nocheck, l, index, newstring)
def _RPyListOfString_GetItem(l=p,
index=lltype.Signed):
return rlist.ll_getitem_fast(l, index)
def _RPyListOfString_Length(l=p):
return rlist.ll_length(l)
for fname, f in locals().items():
if isinstance(f, types.FunctionType):
# XXX this is painful :(
if (LIST_OF_STR, fname) in db.helper2ptr:
yield (fname, db.helper2ptr[LIST_OF_STR, fname])
else:
# hack: the defaults give the type of the arguments
graph = rtyper.annotate_helper(f, f.func_defaults)
db.helper2ptr[LIST_OF_STR, fname] = graph
yield (fname, graph)
def predeclare_extfuncs(db, rtyper):
modules = {}
def module_name(c_name):
frags = c_name[3:].split('_')
if frags[0] == '':
return '_' + frags[1]
else:
return frags[0]
for func, funcobj in db.externalfuncs.items():
# construct a define LL_NEED_<modname> to make it possible to isolate in-development externals and headers
modname = module_name(func)
if modname not in modules:
modules[modname] = True
yield 'LL_NEED_%s' % modname.upper(), 1
funcptr = funcobj._as_ptr()
yield func, funcptr
def predeclare_exception_data(db, rtyper):
# Exception-related types and constants
exceptiondata = rtyper.exceptiondata
exctransformer = db.exctransformer
yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type)
yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value)
yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.fn_exception_match)
yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.fn_type_of_exc_inst)
yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occured_ptr.value)
yield ('RPyFetchExceptionType', exctransformer.rpyexc_fetch_type_ptr.value)
yield ('RPyFetchExceptionValue', exctransformer.rpyexc_fetch_value_ptr.value)
yield ('RPyClearException', exctransformer.rpyexc_clear_ptr.value)
yield ('RPyRaiseException', exctransformer.rpyexc_raise_ptr.value)
for exccls in exceptiondata.standardexceptions:
exc_llvalue = exceptiondata.get_standard_ll_exc_instance_by_class(
exccls)
# strange naming here because the macro name must be
# a substring of PyExc_%s
name = exccls.__name__
if exccls.__module__ != 'exceptions':
name = '%s_%s' % (exccls.__module__.replace('.', '__'), name)
yield ('RPyExc_%s' % name, exc_llvalue)
def predeclare_all(db, rtyper):
for fn in [predeclare_common_types,
predeclare_utility_functions,
predeclare_exception_data,
predeclare_extfuncs,
]:
for t in fn(db, rtyper):
yield t
def get_all(db, rtyper):
for fn in [predeclare_common_types,
predeclare_utility_functions,
predeclare_exception_data,
predeclare_extfuncs,
]:
for t in fn(db, rtyper):
yield t[1]
# ____________________________________________________________
def do_the_getting(db, rtyper):
decls = list(get_all(db, rtyper))
rtyper.specialize_more_blocks()
for obj in decls:
if isinstance(obj, lltype.LowLevelType):
db.gettype(obj)
elif isinstance(obj, FunctionGraph):
db.get(rtyper.getcallable(obj))
else:
db.get(obj)
def pre_include_code_lines(db, rtyper):
# generate some #defines that go before the #include to provide
# predeclared well-known names for constant objects, functions and
# types. These names are then used by the #included files, like
# g_exception.h.
def predeclare(c_name, lowlevelobj):
llname = db.get(lowlevelobj)
assert '\n' not in llname
return '#define\t%s\t%s' % (c_name, llname)
def predeclaretype(c_typename, lowleveltype):
typename = db.gettype(lowleveltype)
return 'typedef %s;' % cdecl(typename, c_typename)
yield '#define HAVE_RTYPER'
decls = list(predeclare_all(db, rtyper))
for c_name, obj in decls:
if isinstance(obj, lltype.LowLevelType):
yield predeclaretype(c_name, obj)
elif isinstance(obj, FunctionGraph):
yield predeclare(c_name, rtyper.getcallable(obj))
else:
yield predeclare(c_name, obj)
|