def convert_array(container, carray=None): ARRAY = container._TYPE if carray is None: # if 'container' is an inlined substructure, convert the whole # bigger structure at once parent, parentindex = lltype.parentlink(container) if parent is not None: convert_struct(parent) return # regular case: allocate a new ctypes array of the proper type cls = get_ctypes_type(ARRAY) carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): # fish that we have enough space ctypes_array = ctypes.cast(carray.items, ctypes.POINTER(carray.items._type_)) for i in range(container.getlength()): item_value = container.items[i] # fish fish ctypes_array[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) for i in range(container.getlength()): item_ptr = container.items[i] # fish fish convert_struct(item_ptr, carray.items[i])
def setup(self): for value in self._getvalues(): self.db.prepare_constant(lltype.typeOf(value), value) p, c = lltype.parentlink(self.value) if p is not None: self.db.prepare_constant(lltype.typeOf(p), p)
def ref(self, firstitemptr): A = lltype.typeOf(firstitemptr).TO if A == self.TYPE: # for array of containers parent, index = lltype.parentlink(firstitemptr._obj) assert parent, "%r is not within a container" % (firstitemptr, ) assert isinstance( lltype.typeOf(parent), (lltype.Array, lltype.FixedSizeArray)), ("%r is not within an array" % (firstitemptr, )) if isinstance(index, str): assert index.startswith('item') # itemN => N index = int(index[4:]) index += self.repeat if index == parent.getlength(): # for references exactly to the end of the array try: endmarker = _end_markers[parent] except KeyError: endmarker = _endmarker_struct(A, parent=parent, parentindex=index) _end_markers[parent] = endmarker return endmarker._as_ptr() else: return parent.getitem(index)._as_ptr() elif (isinstance(A, lltype.FixedSizeArray) and array_item_type_match(A.OF, self.TYPE)): # for array of primitives or pointers return lltype.direct_ptradd(firstitemptr, self.repeat) else: raise TypeError('got %r, expected %r' % (A, self.TYPE))
def setup(self): if isinstance(self.value, lltype._subarray): p, c = lltype.parentlink(self.value) if p is not None: self.db.prepare_constant(lltype.typeOf(p), p) else: super(FixedSizeArrayNode, self).setup()
def convert_struct(container, cstruct=None): STRUCT = container._TYPE if cstruct is None: # if 'container' is an inlined substructure, convert the whole # bigger structure at once parent, parentindex = lltype.parentlink(container) if parent is not None: convert_struct(parent) return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) cstruct = cls._malloc() add_storage(container, _struct_mixin, cstruct) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) field_value = getattr(container, field_name) if not isinstance(FIELDTYPE, lltype.ContainerType): # regular field setattr(cstruct, field_name, lltype2ctypes(field_value)) else: # inlined substructure/subarray if isinstance(FIELDTYPE, lltype.Struct): csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) else: raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container)
def ref(self, firstitemptr): A = lltype.typeOf(firstitemptr).TO if A == self.TYPE: # for array of containers parent, index = lltype.parentlink(firstitemptr._obj) assert parent, "%r is not within a container" % (firstitemptr,) assert isinstance(lltype.typeOf(parent), (lltype.Array, lltype.FixedSizeArray)), ( "%r is not within an array" % (firstitemptr,)) if isinstance(index, str): assert index.startswith('item') # itemN => N index = int(index[4:]) index += self.repeat if index == parent.getlength(): # for references exactly to the end of the array try: endmarker = _end_markers[parent] except KeyError: endmarker = _endmarker_struct(A, parent=parent, parentindex=index) _end_markers[parent] = endmarker return endmarker._as_ptr() else: return parent.getitem(index)._as_ptr() elif (isinstance(A, lltype.FixedSizeArray) and array_item_type_match(A.OF, self.TYPE)): # for array of primitives or pointers return lltype.direct_ptradd(firstitemptr, self.repeat) else: raise TypeError('got %r, expected %r' % (A, self.TYPE))
def convert_struct(container, cstruct=None): STRUCT = container._TYPE if cstruct is None: # if 'container' is an inlined substructure, convert the whole # bigger structure at once parent, parentindex = lltype.parentlink(container) if parent is not None: convert_struct(parent) return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) if STRUCT._arrayfld is not None: n = getattr(container, STRUCT._arrayfld).getlength() else: n = None cstruct = cls._malloc(n) add_storage(container, _struct_mixin, ctypes.pointer(cstruct)) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) field_value = getattr(container, field_name) if not isinstance(FIELDTYPE, lltype.ContainerType): # regular field if FIELDTYPE != lltype.Void: setattr(cstruct, field_name, lltype2ctypes(field_value)) else: # inlined substructure/subarray if isinstance(FIELDTYPE, lltype.Struct): csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) elif field_name == STRUCT._arrayfld: # inlined var-sized part csubarray = getattr(cstruct, field_name) convert_array(field_value, csubarray) else: raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container)
def convert_array(container, carray=None): ARRAY = container._TYPE if carray is None: # if 'container' is an inlined substructure, convert the whole # bigger structure at once parent, parentindex = lltype.parentlink(container) if parent is not None: convert_struct(parent) return # regular case: allocate a new ctypes array of the proper type cls = get_ctypes_type(ARRAY) carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, ctypes.pointer(carray)) if not isinstance(ARRAY.OF, lltype.ContainerType): # fish that we have enough space ctypes_array = ctypes.cast(carray.items, ctypes.POINTER(carray.items._type_)) for i in range(container.getlength()): item_value = container.items[i] # fish fish ctypes_array[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) for i in range(container.getlength()): item_ptr = container.items[i] # fish fish convert_struct(item_ptr, carray.items[i])
def to_getelementptr(self, value): # so we build the thing up instead p = value children = [] while True: p, c = lltype.parentlink(p) if p is None: break children.append((p, c)) children.reverse() TYPE = lltype.typeOf(children[0][0]) parentnode = self.obj2node[children[0][0]] indices = [("i32", 0)] for _, ii in children: typedefnode = self.obj2node[TYPE] if isinstance(ii, str): TYPE = typedefnode.fieldname_to_getelementptr(indices, ii) else: TYPE = typedefnode.indexref_to_getelementptr(indices, ii) indices_str = ', '.join ([('%s %s' % (x,y)) for x, y in indices]) ref = "getelementptr(%s* %s, %s)" % ( parentnode.get_typerepr(), parentnode.ref, indices_str) return ref
def setup(self): for item in self.value.items: self.db.prepare_constant(self.arraytype, item) p, c = lltype.parentlink(self.value) if p is not None: self.db.prepare_constant(lltype.typeOf(p), p)
def get_pbcref(self, toptr): ref = self.ref p, c = lltype.parentlink(self.value) assert p is None, "child PBC arrays are NOT needed by rtyper" fromptr = "%s*" % self.get_typerepr() ref = "cast(%s %s to %s)" % (fromptr, ref, toptr) return ref
def setup(self): for name, T in self._get_types: assert T is not lltype.Void value = getattr(self.value, name) self.db.prepare_constant(T, value) p, c = lltype.parentlink(self.value) if p is not None: self.db.prepare_constant(lltype.typeOf(p), p)
def setup(self): for value in self.db.gcpolicy.gcheader_initdata(self.value): self.db.prepare_constant(lltype.typeOf(value), value) for item in self.value.items: self.db.prepare_constant(self.arraytype, item) p, c = lltype.parentlink(self.value) if p is not None: self.db.prepare_constant(lltype.typeOf(p), p)
def get_pbcref(self, toptr): """ Returns a reference as used per pbc. """ ref = self.ref p, c = lltype.parentlink(self.value) assert p is None, "child varsize struct are NOT needed by rtyper" fromptr = "%s*" % self.get_typerepr() refptr = "getelementptr(%s %s, int 0)" % (fromptr, ref) ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr) return ref
def pyobj_initexpr(self): parent, parentindex = parentlink(self.obj) typenode = self.db.getcontainernode(self.obj.ob_type._obj) typenode.where_to_copy_me.append('(PyObject **) & %s.ob_type' % ( self.name,)) if typeOf(parent)._hints.get('inline_head'): return 'PyObject_HEAD_INIT(NULL)' else: return '{ PyObject_HEAD_INIT(NULL) },'
def get_ref(self): """ Returns a reference as used for operations in blocks. """ if self._get_ref_cache: return self._get_ref_cache p, c = lltype.parentlink(self.value) if p is None: ref = self.ref else: ref = self.db.get_childref(p, c) self._get_ref_cache = ref return ref
def get_ref(self): p, c = lltype.parentlink(self.value) if p is None: ref = self.ref else: ref = self.db.get_childref(p, c) if isinstance(self.value, lltype._subarray): # ptr -> array of len 1 ref = "cast(%s* %s to %s*)" % (self.db.repr_type(self.arraytype), ref, self.db.repr_type(lltype.typeOf(self.value))) return ref
def get_ref(self): typeval = self.db.repr_type(lltype.typeOf(self.value)) p, c = lltype.parentlink(self.value) if p is None: ref = self.ref else: ref = self.db.get_childref(p, c) ref = "cast(%s* %s to %s*)" % (self.get_typerepr(), ref, typeval) return ref
def get_ref(self): """ Returns a reference as used for operations in blocks. """ # XXX cache here is **dangerous** considering it can return different values :-( # XXX should write a test to prove this #if self._get_ref_cache: # return self._get_ref_cache p, c = lltype.parentlink(self.value) if p is None: ref = self.ref else: ref = self.db.get_childref(p, c) #XXXself._get_ref_cache = ref return ref
def reccollect(constants, llvalue): if isinstance(llvalue, lltype._abstract_ptr) and llvalue._obj is not None and llvalue._obj not in constants: TYPE = llvalue._T constants[llvalue._obj] = True if isinstance(TYPE, lltype.Struct): for name in TYPE._names: reccollect(constants, getattr(llvalue, name)) elif isinstance(TYPE, lltype.Array): for llitem in llvalue: reccollect(constants, llitem) parent, parentindex = lltype.parentlink(llvalue._obj) if parent is not None: reccollect(constants, parent._as_ptr())
def _find_parent(llobj): parent, parentindex = lltype.parentlink(llobj) if parent is None: return llobj, 0 next_p, next_i = _find_parent(parent) if isinstance(parentindex, int): c_tp = get_ctypes_type(lltype.typeOf(parent)) sizeof = ctypes.sizeof(get_ctypes_type(lltype.typeOf(parent).OF)) ofs = c_tp.items.offset + parentindex * sizeof return next_p, next_i + ofs else: c_tp = get_ctypes_type(lltype.typeOf(parent)) ofs = getattr(c_tp, parentindex).offset return next_p, next_i + ofs
def reccollect(constants, llvalue): if (isinstance(llvalue, lltype._abstract_ptr) and llvalue._obj is not None and llvalue._obj not in constants): TYPE = llvalue._T constants[llvalue._obj] = True if isinstance(TYPE, lltype.Struct): for name in TYPE._names: reccollect(constants, getattr(llvalue, name)) elif isinstance(TYPE, lltype.Array): for llitem in llvalue: reccollect(constants, llitem) parent, parentindex = lltype.parentlink(llvalue._obj) if parent is not None: reccollect(constants, parent._as_ptr())
def parentchain(container): current = container links = [] while True: link = lltype.parentlink(current) if link[0] is None: try: addr = ctypes.addressof(container._storage) actual = _parent_cache[addr] if len(links) < len(actual): return actual except KeyError: pass return links links.append(link) current = link[0]
def dump_pbcs(self): r = "" for k, v in self.obj2node.iteritems(): if isinstance(k, lltype.LowLevelType): continue assert isinstance(lltype.typeOf(k), lltype.ContainerType) # Only dump top levels p, _ = lltype.parentlink(k) if p is None: ref = v.get_ref() pbc_ref = v.get_ref() r += "\ndump_pbcs %s (%s)\n" \ "getref -> %s \n" \ "pbcref -> %s \n" % (v, k, ref, pbc_ref) return r
def ref(self, firstitemptr): A = lltype.typeOf(firstitemptr).TO if A == self.TYPE: # for array of containers parent, index = lltype.parentlink(firstitemptr._obj) assert parent, "%r is not within a container" % (firstitemptr,) assert isinstance(lltype.typeOf(parent), (lltype.Array, lltype.FixedSizeArray)), ( "%r is not within an array" % (firstitemptr,)) if isinstance(index, str): assert index.startswith('item') # itemN => N index = int(index[4:]) return parent.getitem(index + self.repeat)._as_ptr() elif isinstance(A, lltype.FixedSizeArray) and A.OF == self.TYPE: # for array of primitives or pointers return lltype.direct_ptradd(firstitemptr, self.repeat) else: raise TypeError('got %r, expected %r' % (A, self.TYPE))
def dump_pbcs(self): r = "" for k, v in self.obj2node.iteritems(): if isinstance(v, FuncImplNode): continue if isinstance(k, lltype.LowLevelType): continue assert isinstance(lltype.typeOf(k), lltype.ContainerType) # Only dump top levels p, _ = lltype.parentlink(k) type_ = self.repr_type(lltype.Ptr(lltype.typeOf(k))) r += "\ndump_pbcs %s (%s)\n" \ "parent %s\n" \ "type %s\n" \ "ref -> %s \n" % (v, k, p, type_, v.ref) return r
def __init__(self, db, T, obj): self.db = db self.T = T self.obj = obj # self.dependencies = {} self.typename = db.gettype(T) # , who_asks=self) self.implementationtypename = db.gettype(T, varlength=self.getlength()) parent, parentindex = parentlink(obj) if parent is None: self.name = db.namespace.uniquename("g_" + self.basename()) self.globalcontainer = True else: self.globalcontainer = False parentnode = db.getcontainernode(parent) defnode = db.gettypedefnode(parentnode.T) self.name = defnode.access_expr(parentnode.name, parentindex) self.ptrname = "(&%s)" % self.name if self.typename != self.implementationtypename: ptrtypename = db.gettype(Ptr(T)) self.ptrname = "((%s)(void*)%s)" % (cdecl(ptrtypename, ""), self.ptrname)
def __init__(self, db, T, obj): self.db = db self.T = T self.obj = obj #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) self.implementationtypename = db.gettype(T, varlength=self.getlength()) parent, parentindex = parentlink(obj) if parent is None: self.name = db.namespace.uniquename('g_' + self.basename()) self.globalcontainer = True else: self.globalcontainer = False parentnode = db.getcontainernode(parent) defnode = db.gettypedefnode(parentnode.T) self.name = defnode.access_expr(parentnode.name, parentindex) self.ptrname = '(&%s)' % self.name if self.typename != self.implementationtypename: ptrtypename = db.gettype(Ptr(T)) self.ptrname = '((%s)(void*)%s)' % (cdecl(ptrtypename, ''), self.ptrname)
def __init__(self, db, T, obj): self.db = db self.obj = obj #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) self.implementationtypename = db.gettype(T, varlength=self.getlength()) parent, parentindex = parentlink(obj) if obj in exports.EXPORTS_obj2name: self.name = exports.EXPORTS_obj2name[obj] self.globalcontainer = True elif parent is None: self.name = db.namespace.uniquename('g_' + self.basename()) self.globalcontainer = True else: self.globalcontainer = False parentnode = db.getcontainernode(parent) defnode = db.gettypedefnode(parentnode.getTYPE()) self.name = defnode.access_expr(parentnode.name, parentindex) if self.typename != self.implementationtypename: if db.gettypedefnode(T).extra_union_for_varlength: self.name += '.b'
def __init__(self, db, T, obj): self.db = db self.obj = obj #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) self.implementationtypename = db.gettype(T, varlength=self.getlength()) parent, parentindex = parentlink(obj) if obj in exports.EXPORTS_obj2name: self.name = exports.EXPORTS_obj2name[obj] self.globalcontainer = True elif parent is None: self.name = db.namespace.uniquename('g_' + self.basename()) self.globalcontainer = True else: self.globalcontainer = False parentnode = db.getcontainernode(parent) defnode = db.gettypedefnode(parentnode.getTYPE()) self.name = defnode.access_expr(parentnode.name, parentindex) if self.typename != self.implementationtypename: if db.gettypedefnode(T).extra_union_for_varlength: self.name += '.b' self._funccodegen_owner = None
def prepare_arg_value(self, const_or_var): """if const_or_var is not already in a dictionary self.obj2node, the appropriate node gets constructed and gets added to self._pendingsetup and to self.obj2node""" if isinstance(const_or_var, Constant): ct = const_or_var.concretetype if isinstance(ct, lltype.Primitive): # special cases for address if ct is llmemory.Address: fakedaddress = const_or_var.value if fakedaddress: ptrvalue = fakedaddress.ptr ct = lltype.typeOf(ptrvalue) else: return elif ct is llmemory.WeakGcAddress: return # XXX sometime soon else: return else: assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" ptrvalue = const_or_var.value value = ptrvalue._obj if isinstance(value, int): return # Only prepare root values at this point if isinstance(ct, lltype.Array) or isinstance(ct, lltype.Struct): p, c = lltype.parentlink(value) if p is None: #log.prepareargvalue("skipping preparing non root", value) return if value is not None and value not in self.obj2node: self.addpending(value, self.create_constant_node(ct.TO, value)) else: assert isinstance(const_or_var, Variable)
def convert_struct(container, cstruct=None): STRUCT = container._TYPE if cstruct is None: # if 'container' is an inlined substructure, convert the whole # bigger structure at once parent, parentindex = lltype.parentlink(container) if parent is not None: convert_struct(parent) return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) if STRUCT._arrayfld is not None: n = getattr(container, STRUCT._arrayfld).getlength() else: n = None cstruct = cls._malloc(n) add_storage(container, _struct_mixin, cstruct) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) field_value = getattr(container, field_name) if not isinstance(FIELDTYPE, lltype.ContainerType): # regular field if FIELDTYPE != lltype.Void: setattr(cstruct, field_name, lltype2ctypes(field_value)) else: # inlined substructure/subarray if isinstance(FIELDTYPE, lltype.Struct): csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) subcontainer = getattr(container, field_name) substorage = subcontainer._storage update_parent_cache(substorage, subcontainer) elif field_name == STRUCT._arrayfld: # inlined var-sized part csubarray = getattr(cstruct, field_name) convert_array(field_value, csubarray) else: raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container)
def get_ref(self, value): node = self.obj2node[value] T = lltype.typeOf(value) p, c = lltype.parentlink(value) if p is None: ref = node.ref VT = var_size_type(T) if VT and VT is not lltype.Void: ref = "bitcast(%s* %s to %s*)" % (node.get_typerepr(), ref, self.repr_type(T)) else: ref = self.to_getelementptr(value) if isinstance(node, FixedSizeArrayNode): assert isinstance(value, lltype._subarray) # XXX UGLY (but needs fixing outside of genllvm) # ptr -> array of len 1 (for now, since operations expect this) ref = "bitcast(%s* %s to %s*)" % (self.repr_type(T.OF), ref, self.repr_type(T)) return ref
# container has regular lltype storage, convert it to ctypes if isinstance(T.TO, lltype.Struct): convert_struct(container) elif isinstance(T.TO, lltype.Array): convert_array(container) elif isinstance(T.TO, lltype.OpaqueType): if T.TO != lltype.RuntimeTypeInfo: cbuf = ctypes.create_string_buffer(T.TO.hints['getsize']()) else: cbuf = ctypes.create_string_buffer("\x00") add_storage(container, _parentable_mixin, cbuf) else: raise NotImplementedError(T) container._ctypes_storage_was_allocated() storage = container._storage if lltype.parentlink(container)[0] is not None: update_parent_cache(storage, container) p = ctypes.pointer(storage) if index: p = ctypes.cast(p, ctypes.c_void_p) p = ctypes.c_void_p(p.value + index) c_tp = get_ctypes_type(T.TO) storage._normalized_ctype = c_tp if normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) if lltype.typeOf(llobj) == llmemory.GCREF: p = ctypes.cast(p, ctypes.c_void_p) return p if isinstance(llobj, Symbolic): if isinstance(llobj, llmemory.ItemOffset):
def writeglobalconstants(self, codewriter): p, c = lltype.parentlink(self.value) if p is None: codewriter.globalinstance(self.ref, self.constantvalue())
def writeglobalconstants(self, codewriter): p, c = lltype.parentlink(self.value) if p is None: codewriter.globalinstance(self.ref, self.constantvalue()) codewriter.newline() codewriter.newline()