def visitor_lines(self, prefix, on_item): assert self.varlength == 1 ARRAY = self.ARRAY # we need a unique name for this C variable, or at least one that does # not collide with the expression in 'prefix' i = 0 varname = 'p0' while prefix.find(varname) >= 0: i += 1 varname = 'p%d' % i body = list(on_item('(*%s)' % varname, ARRAY.OF)) if body: yield '{' yield '\t%s = %s.items;' % (cdecl(self.itemtypename, '*' + varname), prefix) yield '\t%s = %s + %s.length;' % (cdecl(self.itemtypename, '*%s_end' % varname), varname, prefix) yield '\twhile (%s != %s_end) {' % (varname, varname) for line in body: yield '\t\t' + line yield '\t\t%s++;' % varname yield '\t}' yield '}'
def get(self, obj, funcgen=None): if isinstance(obj, CConstant): return obj.c_name # without further checks T = typeOf(obj) if isinstance(T, Primitive) or T == GCREF: return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if (isinstance(T.TO, OpaqueType) and T.TO.hints.get('c_pointer_typedef') is not None): if obj._obj is not None: value = rffi.cast(rffi.SSIZE_T, obj) return '((%s) %s)' % (cdecl(self.gettype(T), ''), self.get(value)) if obj: # test if the ptr is non-NULL try: container = obj._obj except lltype.DelayedPointer: # hack hack hack name = obj._obj0 assert name.startswith('delayed!') n = len('delayed!') if len(name) == n: raise if isinstance(lltype.typeOf(obj).TO, lltype.FuncType): if obj in self.idelayedfunctionnames: return self.idelayedfunctionnames[obj][0] funcname = name[n:] funcname = self.namespace.uniquename('g_'+funcname) self.idelayedfunctionnames[obj] = funcname, obj else: funcname = None # can't use the name of a # delayed non-function ptr self.delayedfunctionptrs.append(obj) return funcname # /hack hack hack else: # hack hack hack if obj in self.idelayedfunctionnames: # this used to be a delayed function, # make sure we use the same name forcename = self.idelayedfunctionnames[obj][0] node = self.getcontainernode(container, forcename=forcename) assert node.getptrname() == forcename return forcename # /hack hack hack if isinstance(container, int): # special case for tagged odd-valued pointers return '((%s) %d)' % (cdecl(self.gettype(T), ''), obj._obj) node = self.getcontainernode(container) if node._funccodegen_owner is None: node._funccodegen_owner = funcgen return node.getptrname() else: return '((%s) NULL)' % (cdecl(self.gettype(T), ''), ) else: raise Exception("don't know about %r" % (obj,))
def get(self, obj, funcgen=None): if isinstance(obj, CConstant): return obj.c_name # without further checks T = typeOf(obj) if isinstance(T, Primitive) or T == GCREF: return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if (isinstance(T.TO, OpaqueType) and T.TO.hints.get('c_pointer_typedef') is not None): if obj._obj is not None: value = rffi.cast(rffi.SSIZE_T, obj) return '((%s) %s)' % (cdecl(self.gettype(T), ''), self.get(value)) if obj: # test if the ptr is non-NULL try: container = obj._obj except lltype.DelayedPointer: # hack hack hack name = obj._obj0 assert name.startswith('delayed!') n = len('delayed!') if len(name) == n: raise if isinstance(lltype.typeOf(obj).TO, lltype.FuncType): if obj in self.idelayedfunctionnames: return self.idelayedfunctionnames[obj][0] funcname = name[n:] funcname = self.namespace.uniquename('g_' + funcname) self.idelayedfunctionnames[obj] = funcname, obj else: funcname = None # can't use the name of a # delayed non-function ptr self.delayedfunctionptrs.append(obj) return funcname # /hack hack hack else: # hack hack hack if obj in self.idelayedfunctionnames: # this used to be a delayed function, # make sure we use the same name forcename = self.idelayedfunctionnames[obj][0] node = self.getcontainernode(container, forcename=forcename) assert node.getptrname() == forcename return forcename # /hack hack hack if isinstance(container, int): # special case for tagged odd-valued pointers return '((%s) %d)' % (cdecl(self.gettype(T), ''), obj._obj) node = self.getcontainernode(container) if node._funccodegen_owner is None: node._funccodegen_owner = funcgen return node.getptrname() else: return '((%s) NULL)' % (cdecl(self.gettype(T), ''), ) else: raise Exception("don't know about %r" % (obj, ))
def name_signed(value, db): if isinstance(value, Symbolic): if isinstance(value, FieldOffset): structnode = db.gettypedefnode(value.TYPE) return 'offsetof(%s, %s)'%( cdecl(db.gettype(value.TYPE), ''), structnode.c_struct_field_name(value.fldname)) elif isinstance(value, ItemOffset): if value.TYPE != Void and value.repeat != 0: size = 'sizeof(%s)' % (cdecl(db.gettype(value.TYPE), ''),) if value.repeat != 1: size = '(%s * %s)' % (size, value.repeat) return size else: return '0' elif isinstance(value, ArrayItemsOffset): if (isinstance(value.TYPE, FixedSizeArray) or barebonearray(value.TYPE)): return '0' elif value.TYPE.OF != Void: return 'offsetof(%s, items)'%( cdecl(db.gettype(value.TYPE), '')) else: return 'sizeof(%s)'%(cdecl(db.gettype(value.TYPE), ''),) elif isinstance(value, ArrayLengthOffset): return 'offsetof(%s, length)'%( cdecl(db.gettype(value.TYPE), '')) elif isinstance(value, CompositeOffset): names = [name_signed(item, db) for item in value.offsets] return '(%s)' % (' + '.join(names),) elif type(value) == AddressOffset: return '0' elif type(value) == GCHeaderOffset: return '0' elif type(value) == RoundedUpForAllocation: return 'ROUND_UP_FOR_ALLOCATION(%s, %s)' % ( name_signed(value.basesize, db), name_signed(value.minsize, db)) elif isinstance(value, CDefinedIntSymbolic): return str(value.expr) elif isinstance(value, ComputedIntSymbolic): value = value.compute_fn() elif isinstance(value, llgroup.CombinedSymbolic): name = name_small_integer(value.lowpart, db) assert (value.rest & value.MASK) == 0 return '(%s+%dL)' % (name, value.rest) elif isinstance(value, AddressAsInt): return '((long)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r"%value) if value is None: assert not db.completed return None if value == -sys.maxint-1: # blame C return '(-%dL-1L)' % sys.maxint else: return '%dL' % value
def OP_FLAVORED_MALLOC_VARSIZE(self, op): # XXX this function should DIE!, at least twice over # XXX I know this working in just one case, probably makes # sense to assert it here, rest is just copied flavor = op.args[0].value assert flavor == 'raw' TYPE = self.lltypemap(op.result).TO assert isinstance(TYPE, Array) assert TYPE._hints.get('nolength', False) # </obscure hack> typename = self.db.gettype(TYPE) lenfld = 'length' nodedef = self.db.gettypedefnode(TYPE) if isinstance(TYPE, Struct): arfld = TYPE._arrayfld lenfld = "%s.length" % nodedef.c_struct_field_name(arfld) VARPART = TYPE._flds[TYPE._arrayfld] else: VARPART = TYPE assert isinstance(VARPART, Array) itemtypename = self.db.gettype(VARPART.OF) elength = self.expr(op.args[2]) eresult = self.expr(op.result) erestype = cdecl(typename, '*') if VARPART.OF is Void: # strange esize = 'sizeof(%s)' % (cdecl(typename, ''),) result = '{\n' else: itemtype = cdecl(itemtypename, '') result = 'IF_VARSIZE_OVERFLOW(%s, %s, %s)\nelse {\n' % ( elength, itemtype, eresult) esize = 'sizeof(%s)-sizeof(%s)+%s*sizeof(%s)' % ( cdecl(typename, ''), itemtype, elength, itemtype) # ctypes Arrays have no length field if not VARPART._hints.get('nolength', False): result += '\nif(%s) %s->%s = %s;' % (eresult, eresult, lenfld, elength) if flavor == "raw": result += "OP_RAW_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) elif flavor == "stack": result += "OP_STACK_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) elif flavor == "cpy": xxx # this will never work, as I don't know which arg it would be # tests, tests, tests.... cpytype = self.expr(op.args[2]) result += "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype) else: raise NotImplementedError result += '\n}' return result
def name_signed(value, db): if isinstance(value, Symbolic): if isinstance(value, FieldOffset): structnode = db.gettypedefnode(value.TYPE) return 'offsetof(%s, %s)' % (cdecl(db.gettype( value.TYPE), ''), structnode.c_struct_field_name( value.fldname)) elif isinstance(value, ItemOffset): if value.TYPE != Void and value.repeat != 0: size = 'sizeof(%s)' % (cdecl(db.gettype(value.TYPE), ''), ) if value.repeat != 1: size = '(%s * %s)' % (size, value.repeat) return size else: return '0' elif isinstance(value, ArrayItemsOffset): if (isinstance(value.TYPE, FixedSizeArray) or barebonearray(value.TYPE)): return '0' elif value.TYPE.OF != Void: return 'offsetof(%s, items)' % (cdecl(db.gettype(value.TYPE), '')) else: return 'sizeof(%s)' % (cdecl(db.gettype(value.TYPE), ''), ) elif isinstance(value, ArrayLengthOffset): return 'offsetof(%s, length)' % (cdecl(db.gettype(value.TYPE), '')) elif isinstance(value, CompositeOffset): names = [name_signed(item, db) for item in value.offsets] return '(%s)' % (' + '.join(names), ) elif type(value) == AddressOffset: return '0' elif type(value) == GCHeaderOffset: return '0' elif type(value) == RoundedUpForAllocation: return 'ROUND_UP_FOR_ALLOCATION(%s, %s)' % (name_signed( value.basesize, db), name_signed(value.minsize, db)) elif isinstance(value, CDefinedIntSymbolic): return str(value.expr) elif isinstance(value, ComputedIntSymbolic): value = value.compute_fn() elif isinstance(value, llgroup.CombinedSymbolic): name = name_small_integer(value.lowpart, db) assert (value.rest & value.MASK) == 0 return '(%s+%dL)' % (name, value.rest) elif isinstance(value, AddressAsInt): return '((long)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r" % value) if value is None: assert not db.completed return None if value == -sys.maxint - 1: # blame C return '(-%dL-1L)' % sys.maxint else: return '%dL' % value
def get(self, obj): # XXX extra indent is preserve svn blame - kind of important IMHO (rxe) if 1: if isinstance(obj, CConstant): return obj.c_name # without further checks T = typeOf(obj) if isinstance(T, Primitive) or T == GCREF: return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL try: container = obj._obj except lltype.DelayedPointer: # hack hack hack name = obj._obj0 assert name.startswith('delayed!') n = len('delayed!') if len(name) == n: raise if isinstance(lltype.typeOf(obj).TO, lltype.FuncType): if id(obj) in self.delayedfunctionnames: return self.delayedfunctionnames[id(obj)][0] funcname = name[n:] funcname = self.namespace.uniquename('g_' + funcname) self.delayedfunctionnames[id(obj)] = funcname, obj else: funcname = None # can't use the name of a # delayed non-function ptr self.delayedfunctionptrs.append(obj) return funcname # /hack hack hack else: # hack hack hack if id(obj) in self.delayedfunctionnames: # this used to be a delayed function, # make sure we use the same name forcename = self.delayedfunctionnames[id(obj)][0] node = self.getcontainernode(container, forcename=forcename) assert node.ptrname == forcename return forcename # /hack hack hack if isinstance(container, int): # special case for tagged odd-valued pointers return '((%s) %d)' % (cdecl(self.gettype(T), ''), obj._obj) node = self.getcontainernode(container) return node.ptrname else: return '((%s) NULL)' % (cdecl(self.gettype(T), ''), ) else: raise Exception("don't know about %r" % (obj, ))
def get(self, obj): if isinstance(obj, ErrorValue): T = obj.TYPE if isinstance(T, Primitive): return PrimitiveErrorValue[T] elif isinstance(T, Ptr): return 'NULL' else: raise Exception("don't know about %r" % (T,)) else: T = typeOf(obj) if isinstance(T, Primitive): return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL try: container = obj._obj except lltype.DelayedPointer: # hack hack hack name = obj._obj0 assert name.startswith('delayed!') n = len('delayed!') if len(name) == n: raise if id(obj) in self.delayedfunctionnames: return self.delayedfunctionnames[id(obj)][0] funcname = name[n:] funcname = self.namespace.uniquename('g_' + funcname) self.delayedfunctionnames[id(obj)] = funcname, obj self.delayedfunctionptrs.append(obj) return funcname # /hack hack hack else: # hack hack hack if id(obj) in self.delayedfunctionnames: # this used to be a delayed function, # make sure we use the same name forcename = self.delayedfunctionnames[id(obj)][0] node = self.getcontainernode(container, forcename=forcename) assert node.ptrname == forcename return forcename # /hack hack hack if isinstance(container, int): # special case for tagged odd-valued pointers return '((%s) %d)' % (cdecl(self.gettype(T), ''), obj._obj) node = self.getcontainernode(container) return node.ptrname else: return '((%s) NULL)' % (cdecl(self.gettype(T), ''), ) else: raise Exception("don't know about %r" % (obj,))
def get(self, obj): # XXX extra indent is preserve svn blame - kind of important IMHO (rxe) if 1: if isinstance(obj, CConstant): return obj.c_name # without further checks T = typeOf(obj) if isinstance(T, Primitive) or T == GCREF: return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL try: container = obj._obj except lltype.DelayedPointer: # hack hack hack name = obj._obj0 assert name.startswith('delayed!') n = len('delayed!') if len(name) == n: raise if isinstance(lltype.typeOf(obj).TO, lltype.FuncType): if id(obj) in self.delayedfunctionnames: return self.delayedfunctionnames[id(obj)][0] funcname = name[n:] funcname = self.namespace.uniquename('g_'+funcname) self.delayedfunctionnames[id(obj)] = funcname, obj else: funcname = None # can't use the name of a # delayed non-function ptr self.delayedfunctionptrs.append(obj) return funcname # /hack hack hack else: # hack hack hack if id(obj) in self.delayedfunctionnames: # this used to be a delayed function, # make sure we use the same name forcename = self.delayedfunctionnames[id(obj)][0] node = self.getcontainernode(container, forcename=forcename) assert node.ptrname == forcename return forcename # /hack hack hack if isinstance(container, int): # special case for tagged odd-valued pointers return '((%s) %d)' % (cdecl(self.gettype(T), ''), obj._obj) node = self.getcontainernode(container) return node.ptrname else: return '((%s) NULL)' % (cdecl(self.gettype(T), ''), ) else: raise Exception("don't know about %r" % (obj,))
def definition(self): gcpolicy = self.db.gcpolicy yield 'struct %s {' % self.name for fname, typename in self.gcfields: yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' line = '%s;' % cdecl(self.itemtypename, 'items[%d]' % self.varlength) if self.ARRAY.OF is Void: # strange line = '/* %s */' % line yield '\t' + line yield '};'
def definition(self): gcpolicy = self.db.gcpolicy yield 'struct %s {' % self.name for fname, typename in self.gcfields: yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) if self.ARRAY.OF is Void: # strange line = '/* %s */' % line yield '\t' + line yield '};'
def definition(self): gcpolicy = self.db.gcpolicy yield "struct %s {" % self.name for fname, typename in self.gcfields: yield "\t" + cdecl(typename, fname) + ";" if not self.ARRAY._hints.get("nolength", False): yield "\tlong length;" line = "%s;" % cdecl(self.itemtypename, "items[%d]" % self.varlength) if self.ARRAY.OF is Void: # strange line = "/* array of void */" if self.ARRAY._hints.get("nolength", False): line = "char _dummy; " + line yield "\t" + line yield "};"
def forward_declaration(self): hash_typename = self.get_hash_typename() hash_offset = self.db.gctransformer.get_hash_offset(self.T) yield '%s {' % cdecl(hash_typename, '') yield '\tunion {' yield '\t\t%s;' % cdecl(self.implementationtypename, 'head') yield '\t\tchar pad[%s];' % name_signed(hash_offset, self.db) yield '\t} u;' yield '\tlong hash;' yield '};' yield '%s;' % ( forward_cdecl(hash_typename, '_hash_' + self.name, self.db.standalone, self.is_thread_local()),) yield '#define %s _hash_%s.u.head' % (self.name, self.name)
def forward_declaration(self): T = self.getTYPE() assert self.typename == self.implementationtypename # no array part hash_typename = self.get_hash_typename() hash_offset = self.db.gctransformer.get_hash_offset(T) yield "%s {" % cdecl(hash_typename, "") yield "\tunion {" yield "\t\t%s;" % cdecl(self.implementationtypename, "head") yield "\t\tchar pad[%s];" % name_signed(hash_offset, self.db) yield "\t} u;" yield "\tlong hash;" yield "};" yield "%s;" % (forward_cdecl(hash_typename, "_hash_" + self.name, self.db.standalone, self.is_thread_local()),) yield "#define %s _hash_%s.u.head" % (self.name, self.name)
def OP_DEBUG_LLINTERPCALL(self, op): result = "abort(); /* debug_llinterpcall should be unreachable */" TYPE = self.lltypemap(op.result) if TYPE is not Void: typename = self.db.gettype(TYPE) result += "\n%s = (%s)0;" % (self.expr(op.result), cdecl(typename, "")) return result
def implementation(self): lines = list(self.initializationexpr()) lines[0] = '%s = %s' % ( cdecl(self.implementationtypename, self.name, self.is_thread_local()), lines[0]) lines[-1] += ';' return lines
def forward_declaration(self): self._fix_members() yield "" ctype = ["%s {" % cdecl(self.implementationtypename, "")] for i, member in enumerate(self.obj.members): structtypename = self.db.gettype(typeOf(member)) ctype.append("\t%s;" % cdecl(structtypename, "member%d" % i)) ctype.append("} @") ctype = "\n".join(ctype) yield "%s;" % (forward_cdecl(ctype, self.name, self.db.standalone, self.is_thread_local())) yield '#include "src/llgroup.h"' yield "PYPY_GROUP_CHECK_SIZE(%s)" % (self.name,) for i, member in enumerate(self.obj.members): structnode = self.db.getcontainernode(member) yield "#define %s %s.member%d" % (structnode.name, self.name, i) yield ""
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 pypy.translator.c.database import LowLevelDatabase from pypy.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); }' else: pattern = '%s { return %s(%s); }' source = pattern % ( 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], export_symbols=[wrapper_name], )) 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 OP_CAST_WEAKADR_TO_PTR(self, op): TYPE = self.lltypemap(op.result) assert TYPE != PyObjPtr typename = self.db.gettype(TYPE) return '%s = (%s)REVEAL_POINTER(%s);' % (self.expr(op.result), cdecl(typename, ''), self.expr(op.args[0]))
def OP_RAW_LOAD(self, op): addr = self.expr(op.args[0]) TYPE = op.args[1].value offset = self.expr(op.args[2]) result = self.expr(op.result) typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '') return "%(result)s = ((%(typename)s) %(addr)s)[%(offset)s];" % locals()
def OP_RAW_STORE(self, op): addr = self.expr(op.args[0]) TYPE = op.args[1].value offset = self.expr(op.args[2]) value = self.expr(op.args[3]) typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '') return "((%(typename)s) %(addr)s)[%(offset)s] = %(value)s;" % locals()
def OP_GET_GROUP_MEMBER(self, op): typename = self.db.gettype(op.result.concretetype) return '%s = (%s)_OP_GET_GROUP_MEMBER(%s, %s);' % ( self.expr(op.result), cdecl(typename, ''), self.expr(op.args[0]), self.expr(op.args[1]))
def name_signed(value, db): if isinstance(value, Symbolic): if isinstance(value, FieldOffset): structnode = db.gettypedefnode(value.TYPE) return 'offsetof(%s, %s)'%( cdecl(db.gettype(value.TYPE), ''), structnode.c_struct_field_name(value.fldname)) elif isinstance(value, ItemOffset): if value.TYPE != Void: return '(sizeof(%s) * %s)'%( cdecl(db.gettype(value.TYPE), ''), value.repeat) else: return '0' elif isinstance(value, ArrayItemsOffset): if isinstance(value.TYPE, FixedSizeArray): return '0' elif value.TYPE.OF != Void: return 'offsetof(%s, items)'%( cdecl(db.gettype(value.TYPE), '')) else: return 'sizeof(%s)'%(cdecl(db.gettype(value.TYPE), ''),) elif isinstance(value, ArrayLengthOffset): return 'offsetof(%s, length)'%( cdecl(db.gettype(value.TYPE), '')) elif isinstance(value, CompositeOffset): names = [name_signed(item, db) for item in value.offsets] return '(%s)' % (' + '.join(names),) elif type(value) == AddressOffset: return '0' elif type(value) == GCHeaderOffset: return '0' elif isinstance(value, CDefinedIntSymbolic): return str(value.expr) elif isinstance(value, ComputedIntSymbolic): value = value.compute_fn() elif isinstance(value, CConstant): return value.c_name else: raise Exception("unimplemented symbolic %r"%value) if value is None: assert not db.completed return None if value == -sys.maxint-1: # blame C return '(-%dL-1L)' % sys.maxint else: return '%dL' % value
def OP_FLAVORED_MALLOC(self, op): # XXX this function should DIE! TYPE = self.lltypemap(op.result).TO typename = self.db.gettype(TYPE) eresult = self.expr(op.result) esize = 'sizeof(%s)' % cdecl(typename, '') erestype = cdecl(typename, '*') flavor = op.args[0].value if flavor == "raw": return "OP_RAW_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) elif flavor == "stack": return "OP_STACK_MALLOC(%s, %s, %s);" % (esize, eresult, erestype) elif flavor == "cpy": cpytype = self.expr(op.args[2]) return "OP_CPY_MALLOC(%s, %s, %s);" % (cpytype, eresult, erestype) else: raise NotImplementedError
def OP_ADR_CALL(self, op): ARGTYPES = [v.concretetype for v in op.args[1:]] RESTYPE = op.result.concretetype FUNC = Ptr(FuncType(ARGTYPES, RESTYPE)) typename = self.db.gettype(FUNC) fnaddr = op.args[0] fnexpr = '((%s)%s)' % (cdecl(typename, ''), self.expr(fnaddr)) return self.generic_call(FUNC, fnexpr, op.args[1:], op.result)
def OP_DEBUG_LLINTERPCALL(self, op): result = 'abort(); /* debug_llinterpcall should be unreachable */' TYPE = self.lltypemap(op.result) if TYPE is not Void: typename = self.db.gettype(TYPE) result += '\n%s = (%s)0;' % (self.expr(op.result), cdecl(typename, '')) return result
def forward_declaration(self): self._fix_members() yield '' ctype = ['%s {' % cdecl(self.implementationtypename, '')] for i, member in enumerate(self.obj.members): structtypename = self.db.gettype(typeOf(member)) ctype.append('\t%s;' % cdecl(structtypename, 'member%d' % i)) ctype.append('} @') ctype = '\n'.join(ctype) yield '%s;' % (forward_cdecl(ctype, self.name, self.db.standalone, self.is_thread_local())) yield '#include "src/llgroup.h"' yield 'PYPY_GROUP_CHECK_SIZE(%s)' % (self.name, ) for i, member in enumerate(self.obj.members): structnode = self.db.getcontainernode(member) yield '#define %s %s.member%d' % (structnode.name, self.name, i) yield ''
def implementation(self): hash_typename = self.get_hash_typename() hash = self.db.gcpolicy.get_prebuilt_hash(self.obj) assert hash is not None lines = list(self.initializationexpr()) lines.insert(0, "%s = { {" % (cdecl(hash_typename, "_hash_" + self.name, self.is_thread_local()),)) lines.append("}, %s /* hash */ };" % name_signed(hash, self.db)) return lines
def OP_CAST_POINTER(self, op): TYPE = self.lltypemap(op.result) typename = self.db.gettype(TYPE) result = [] result.append('%s = (%s)%s;' % (self.expr(op.result), cdecl(typename, ''), self.expr(op.args[0]))) return '\t'.join(result)
def implementation(self): hard_tls = self.name == self.EXC_DATA_VARNAME lines = list(self.initializationexpr()) lines[0] = '%s = %s' % (cdecl(self.implementationtypename, self.name, hard_tls or self.is_thread_local()), lines[0]) lines[-1] += ';' return lines
def implementation(self): if llgroup.member_of_group(self.obj): return [] lines = list(self.initializationexpr()) lines[0] = '%s = %s' % ( cdecl(self.implementationtypename, self.name, self.is_thread_local()), lines[0]) lines[-1] += ';' return lines
def ptr_access_expr(self, baseexpr, fldname): if self.STRUCT._hints.get("inline_head"): first, FIRST = self.STRUCT._first_struct() if fldname == first: # "invalid" cast according to C99 but that's what CPython # requires and does all the time :-/ return "(*(%s) %s)" % (cdecl(self.db.gettype(FIRST), "*"), baseexpr) fldname = self.c_struct_field_name(fldname) return "RPyField(%s, %s)" % (baseexpr, fldname)
def gettype(self, T, varlength=1, who_asks=None, argnames=[]): if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Typedef): return '%s @' % T.c_name elif isinstance(T, Ptr): if (isinstance(T.TO, OpaqueType) and T.TO.hints.get('c_pointer_typedef') is not None): return '%s @' % T.TO.hints['c_pointer_typedef'] try: node = self.gettypedefnode(T.TO) except NoCorrespondingNode: pass else: if hasattr(node, 'getptrtype'): return node.getptrtype() # special-casing because of C typename = self.gettype(T.TO) # who_asks not propagated return typename.replace('@', '*@') elif isinstance(T, (Struct, Array, _WeakRefType)): node = self.gettypedefnode(T, varlength=varlength) if who_asks is not None: who_asks.dependencies[node] = True return node.gettype() elif T == PyObject: return 'PyObject @' elif isinstance(T, FuncType): resulttype = self.gettype(T.RESULT) argtypes = [] for i in range(len(T.ARGS)): if T.ARGS[i] is not Void: argtype = self.gettype(T.ARGS[i]) try: argname = argnames[i] except IndexError: argname = '' argtypes.append(cdecl(argtype, argname)) argtypes = ', '.join(argtypes) or 'void' return resulttype.replace('@', '(@)(%s)' % argtypes) elif isinstance(T, OpaqueType): if T == RuntimeTypeInfo: return self.gcpolicy.rtti_type() elif T.hints.get("render_structure", False): node = self.gettypedefnode(T, varlength=varlength) if who_asks is not None: who_asks.dependencies[node] = True return 'struct %s @' % node.name elif T.hints.get('external', None) == 'C': return '%s @' % T.hints['c_name'] else: #raise Exception("don't know about opaque type %r" % (T,)) return 'struct %s @' % (valid_identifier('pypy_opaque_' + T.tag), ) elif isinstance(T, llgroup.GroupType): return "/*don't use me*/ void @" else: raise Exception("don't know about type %r" % (T, ))
def gettype(self, T, varlength=1, who_asks=None, argnames=[]): if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Typedef): return '%s @' % T.c_name elif isinstance(T, Ptr): if (isinstance(T.TO, OpaqueType) and T.TO.hints.get('c_pointer_typedef') is not None): return '%s @' % T.TO.hints['c_pointer_typedef'] try: node = self.gettypedefnode(T.TO) except NoCorrespondingNode: pass else: if hasattr(node, 'getptrtype'): return node.getptrtype() # special-casing because of C typename = self.gettype(T.TO) # who_asks not propagated return typename.replace('@', '*@') elif isinstance(T, (Struct, Array, _WeakRefType)): node = self.gettypedefnode(T, varlength=varlength) if who_asks is not None: who_asks.dependencies[node] = True return node.gettype() elif T == PyObject: return 'PyObject @' elif isinstance(T, FuncType): resulttype = self.gettype(T.RESULT) argtypes = [] for i in range(len(T.ARGS)): if T.ARGS[i] is not Void: argtype = self.gettype(T.ARGS[i]) try: argname = argnames[i] except IndexError: argname = '' argtypes.append(cdecl(argtype, argname)) argtypes = ', '.join(argtypes) or 'void' return resulttype.replace('@', '(@)(%s)' % argtypes) elif isinstance(T, OpaqueType): if T == RuntimeTypeInfo: return self.gcpolicy.rtti_type() elif T.hints.get("render_structure", False): node = self.gettypedefnode(T, varlength=varlength) if who_asks is not None: who_asks.dependencies[node] = True return 'struct %s @' % node.name elif T.hints.get('external', None) == 'C': return '%s @' % T.hints['c_name'] else: #raise Exception("don't know about opaque type %r" % (T,)) return 'struct %s @' % ( valid_identifier('pypy_opaque_' + T.tag),) elif isinstance(T, llgroup.GroupType): return "/*don't use me*/ void @" else: raise Exception("don't know about type %r" % (T,))
def definition(self): gcpolicy = self.db.gcpolicy yield 'struct %s {' % self.name for fname, typename in self.gcfields: yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) if self.ARRAY.OF is Void: # strange line = '/* array of void */' if self.ARRAY._hints.get('nolength', False): line = 'char _dummy; ' + line yield '\t' + line yield '};' if self.varlength != 1: yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};'
def access_expr(self, baseexpr, fldname): if self.STRUCT._hints.get('inline_head'): first, FIRST = self.STRUCT._first_struct() if fldname == first: # "invalid" cast according to C99 but that's what CPython # requires and does all the time :-/ return '(*(%s) &(%s))' % (cdecl(self.db.gettype(FIRST), '*'), baseexpr) fldname = self.c_struct_field_name(fldname) return '%s.%s' % (baseexpr, fldname)
def ptr_access_expr(self, baseexpr, fldname): if self.STRUCT._hints.get('inline_head'): first, FIRST = self.STRUCT._first_struct() if fldname == first: # "invalid" cast according to C99 but that's what CPython # requires and does all the time :-/ return '(*(%s) %s)' % (cdecl(self.db.gettype(FIRST), '*'), baseexpr) fldname = self.c_struct_field_name(fldname) return 'RPyField(%s, %s)' % (baseexpr, fldname)
def forward_declaration(self): self._fix_members() yield '' ctype = ['%s {' % cdecl(self.implementationtypename, '')] for i, member in enumerate(self.obj.members): structtypename = self.db.gettype(typeOf(member)) ctype.append('\t%s;' % cdecl(structtypename, 'member%d' % i)) ctype.append('} @') ctype = '\n'.join(ctype) yield '%s;' % ( forward_cdecl(ctype, self.name, self.db.standalone, self.is_thread_local())) yield '#include "src/llgroup.h"' yield 'PYPY_GROUP_CHECK_SIZE(%s);' % self.name for i, member in enumerate(self.obj.members): structnode = self.db.getcontainernode(member) yield '#define %s %s.member%d' % (structnode.name, self.name, i) yield ''
def definition(self): gcpolicy = self.db.gcpolicy yield 'struct %s {' % self.name for fname, typename in self.gcfields: yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' line = '%s;' % cdecl(self.itemtypename, 'items[%d]' % self.varlength) if self.ARRAY.OF is Void: # strange line = '/* array of void */' if self.ARRAY._hints.get('nolength', False): line = 'char _dummy; ' + line yield '\t' + line yield '};' if self.varlength != 1: yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};'
def implementation(self): hash_typename = self.get_hash_typename() hash = self.db.gcpolicy.get_prebuilt_hash(self.obj) assert hash is not None lines = list(self.initializationexpr()) lines.insert( 0, '%s = { {' % (cdecl(hash_typename, '_hash_' + self.name, self.is_thread_local()), )) lines.append('}, %s /* hash */ };' % name_signed(hash, self.db)) return lines
def OP_CAST_PRIMITIVE(self, op): TYPE = self.lltypemap(op.result) val = self.expr(op.args[0]) ORIG = self.lltypemap(op.args[0]) if ORIG is Char: val = "(unsigned char)%s" % val elif ORIG is UniChar: val = "(unsigned long)%s" % val result = self.expr(op.result) typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals()
def OP_GC_GETTYPEPTR_GROUP(self, funcgen, op): # expands to a number of steps, as per rpython/lltypesystem/opimpl.py, # all implemented by a single call to a C macro. [v_obj, c_grpptr, c_skipoffset, c_vtableinfo] = op.args typename = funcgen.db.gettype(op.result.concretetype) fieldname = c_vtableinfo.value[2] return ( '%s = (%s)_OP_GET_NEXT_GROUP_MEMBER(%s, (unsigned short)%s->_%s, %s);' % (funcgen.expr(op.result), cdecl(typename, ''), funcgen.expr(c_grpptr), funcgen.expr(v_obj), fieldname, funcgen.expr(c_skipoffset)))
def name_small_integer(value, db): """Works for integers of size at most INT or UINT.""" if isinstance(value, Symbolic): if isinstance(value, llgroup.GroupMemberOffset): groupnode = db.getcontainernode(value.grpptr._as_obj()) return 'GROUP_MEMBER_OFFSET(%s, member%s)' % ( cdecl(groupnode.implementationtypename, ''), value.index, ) else: raise Exception("unimplemented symbolic %r" % value) return str(value)
def definition(self): if self.fields is None: # external definition only return yield '%s %s {' % (self.typetag, self.name) is_empty = True for name, typename in self.fields: line = '%s;' % cdecl(typename, name) if typename == PrimitiveType[Void]: line = '/* %s */' % line else: is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};' if self.varlength != 1: assert self.typetag == 'struct' yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};'
def implementation(self): if llgroup.member_of_group(self.obj): return [] lines = list(self.initializationexpr()) type, name = self.get_declaration() if name != self.name: lines[0] = '{ ' + lines[0] # extra braces around the 'a' part lines[-1] += ' }' # of the union lines[0] = '%s = %s' % (cdecl(type, name, self.is_thread_local()), lines[0]) lines[-1] += ';' return lines
def visitor_lines(self, prefix, on_item): ARRAY = self.ARRAY # we need a unique name for this C variable, or at least one that does # not collide with the expression in 'prefix' i = 0 varname = 'p0' while prefix.find(varname) >= 0: i += 1 varname = 'p%d' % i body = list(on_item('(*%s)' % varname, ARRAY.OF)) if body: yield '{' yield '\t%s = %s.items;' % (cdecl(self.itemtypename, '*' + varname), prefix) yield '\t%s = %s + %s.length;' % (cdecl( self.itemtypename, '*%s_end' % varname), varname, prefix) yield '\twhile (%s != %s_end) {' % (varname, varname) for line in body: yield '\t\t' + line yield '\t\t%s++;' % varname yield '\t}' yield '}'
def definition(self): if self.fields is None: # external definition only return yield '%s %s {' % (self.typetag, self.name) is_empty = True for name, typename in self.fields: line = '%s;' % cdecl(typename, name) if typename == PrimitiveType[Void]: line = '/* %s */' % line else: is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};'
def OP_GC_GETTYPEPTR_GROUP(self, funcgen, op): # expands to a number of steps, as per rpython/lltypesystem/opimpl.py, # all implemented by a single call to a C macro. [v_obj, c_grpptr, c_skipoffset, c_vtableinfo] = op.args typename = funcgen.db.gettype(op.result.concretetype) tid_field = c_vtableinfo.value[2] # Fish out the C name of the tid field. HDR = self.db.gctransformer.HDR hdr_node = self.db.gettypedefnode(HDR) fieldname = hdr_node.c_struct_field_name(tid_field) return ('%s = (%s)_OP_GET_NEXT_GROUP_MEMBER(%s, (pypy_halfword_t)%s->' '_gcheader.%s, %s);' % (funcgen.expr(op.result), cdecl(typename, ''), funcgen.expr(c_grpptr), funcgen.expr(v_obj), fieldname, funcgen.expr(c_skipoffset)))
def initializationexpr(self, decoration=''): T = self.getTYPE() is_empty = True yield '{' defnode = self.db.gettypedefnode(T) data = [] if needs_gcheader(T): gc_init = self.db.gcpolicy.struct_gcheader_initdata(self) data.append(('gcheader', gc_init)) for name in defnode.fieldnames: data.append((name, getattr(self.obj, name))) # Reasonably, you should only initialise one of the fields of a union # in C. This is possible with the syntax '.fieldname value' or # '.fieldname = value'. But here we don't know which of the # fields need initialization, so XXX we pick the first one # arbitrarily. if hasattr(T, "_hints") and T._hints.get('union'): data = data[0:1] if 'get_padding_drop' in T._hints: d = {} for name, _ in data: T1 = defnode.c_struct_field_type(name) typename = self.db.gettype(T1) d[name] = cdecl(typename, '') padding_drop = T._hints['get_padding_drop'](d) else: padding_drop = [] for name, value in data: if name in padding_drop: continue c_expr = defnode.access_expr(self.name, name) lines = generic_initializationexpr(self.db, value, c_expr, decoration + name) for line in lines: yield '\t' + line if not lines[0].startswith('/*'): is_empty = False if is_empty: yield '\t%s' % '0,' yield '}'
def funcgen_implementation(self, funcgen): funcgen.implementation_begin() # recompute implementationtypename as the argnames may have changed argnames = funcgen.argnames() implementationtypename = self.db.gettype(self.T, argnames=argnames) yield '%s {' % cdecl(implementationtypename, funcgen.name(self.name)) # # declare the local variables # localnames = list(funcgen.cfunction_declarations()) lengths = [len(a) for a in localnames] lengths.append(9999) start = 0 while start < len(localnames): # pack the local declarations over as few lines as possible total = lengths[start] + 8 end = start + 1 while total + lengths[end] < 77: total += lengths[end] + 1 end += 1 yield '\t' + ' '.join(localnames[start:end]) start = end # # generate the body itself # bodyiter = funcgen.cfunction_body() for line in bodyiter: # performs some formatting on the generated body: # indent normal lines with tabs; indent labels less than the rest if line.endswith(':'): if line.startswith('err'): try: nextline = bodyiter.next() except StopIteration: nextline = '' # merge this 'err:' label with the following line line = '\t%s\t%s' % (line, nextline) else: line = ' ' + line elif line: line = '\t' + line yield line yield '}' del bodyiter funcgen.implementation_end()
def cfunction_declarations(self): # declare the local variables, excluding the function arguments seen = {} for a in self.graph.getargs(): seen[a.name] = True result_by_name = [] for v in self.allvariables(): name = v.name if name not in seen: seen[name] = True result = cdecl(self.lltypename(v), LOCALVAR % name) + ';' if self.lltypemap(v) is Void: continue #result = '/*%s*/' % result result_by_name.append((v._name, result)) result_by_name.sort() return [result for name, result in result_by_name]