def visitor_lines(self, prefix, on_item): assert self.varlength is None 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 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 implementation(self): if llgroup.member_of_group(self.obj): return [] lines = list(self.initializationexpr()) type, name = self.get_declaration() if name != self.name and len(lines) < 2: # a union with length 0 lines[0] = cdecl(type, name, self.is_thread_local()) else: 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 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 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_THREADLOCALREF_GET(self, op): typename = self.db.gettype(op.result.concretetype) if isinstance(op.args[0], Constant): assert isinstance(op.args[0].value, CDefinedIntSymbolic) fieldname = op.args[0].value.expr assert fieldname.startswith('RPY_TLOFS_') fieldname = fieldname[10:] return '%s = (%s)RPY_THREADLOCALREF_GET(%s);' % ( self.expr(op.result), cdecl(typename, ''), fieldname) else: return 'OP_THREADLOCALREF_GET_NONCONST(%s, %s, %s);' % ( cdecl(typename, ''), self.expr(op.args[0]), self.expr(op.result))
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); }' 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_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 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 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 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 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 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_RAW_LOAD(self, op): addr = self.expr(op.args[0]) offset = self.expr(op.args[1]) result = self.expr(op.result) TYPE = op.result.concretetype typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '') return ( "%(result)s = ((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0];" % locals())
def OP_RAW_STORE(self, op): addr = self.expr(op.args[0]) offset = self.expr(op.args[1]) value = self.expr(op.args[2]) TYPE = op.args[2].concretetype typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '') return ( '((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0] = %(value)s;' % locals())
def definition(self): 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[%s]" % deflength(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 is not None: yield "union %su {" % self.name yield " struct %s a;" % self.name yield " %s;" % cdecl(self.normalizedtypename, "b") yield "};"
def definition(self): 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[%s]' % deflength(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 is not None: 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.gctransformer.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 gettype(self, T, varlength=None, 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.add(node) return node.gettype() 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.add(node) 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 visitor_lines(self, prefix, on_item): FIXEDARRAY = self.FIXEDARRAY # 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, FIXEDARRAY.OF)) if body: yield "{" yield "\t%s = %s;" % (cdecl(self.itemtypename, "*" + varname), prefix) yield "\t%s = %s + %d;" % (cdecl(self.itemtypename, "*%s_end" % varname), varname, FIXEDARRAY.length) yield "\twhile (%s != %s_end) {" % (varname, varname) for line in body: yield "\t\t" + line yield "\t\t%s++;" % varname yield "\t}" yield "}"
def OP_GC_LOAD_INDEXED(self, op): addr = self.expr(op.args[0]) index = self.expr(op.args[1]) scale = self.expr(op.args[2]) base_ofs = self.expr(op.args[3]) result = self.expr(op.result) TYPE = op.result.concretetype typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '') return ( "%(result)s = ((%(typename)s) (((char *)%(addr)s) + " "%(base_ofs)s + %(scale)s * %(index)s))[0];" % locals())
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 OP_CAST_PRIMITIVE(self, op): TYPE = self.lltypemap(op.result) val = self.expr(op.args[0]) result = self.expr(op.result) if TYPE == Bool: return "%(result)s = !!%(val)s;" % locals() ORIG = self.lltypemap(op.args[0]) if ORIG is Char: val = "(unsigned char)%s" % val elif ORIG is UniChar: val = "(unsigned long)%s" % val typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals()
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 initializationexpr(self, decoration=''): T = self.getTYPE() is_empty = True 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 = [] type, name = self.get_declaration() if name != self.name and self.getvarlength() < 1 and len(data) < 2: # an empty union yield '' return yield '{' 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 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: if is_empty and typename.endswith("[RPY_VARLENGTH]"): yield "\tRPY_DUMMY_VARLENGTH" is_empty = False yield "\t" + line if is_empty: yield "\t" + "char _dummy; /* this struct is empty */" yield "};" if self.varlength is not None: assert self.typetag == "struct" yield "union %su {" % self.name yield " struct %s a;" % self.name yield " %s;" % cdecl(self.normalizedtypename, "b") yield "};"
def OP_CAST_PRIMITIVE(self, op): self._check_split_gc_address_space(op) TYPE = self.lltypemap(op.result) val = self.expr(op.args[0]) result = self.expr(op.result) if TYPE == Bool: return "%(result)s = !!%(val)s;" % locals() ORIG = self.lltypemap(op.args[0]) if ORIG is Char: val = "(unsigned char)%s" % val elif ORIG is UniChar: val = "(unsigned long)%s" % val typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals()
def visitor_lines(self, prefix, on_item): FIXEDARRAY = self.FIXEDARRAY # 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, FIXEDARRAY.OF)) if body: yield '{' yield '\t%s = %s;' % (cdecl(self.itemtypename, '*' + varname), prefix) yield '\t%s = %s + %d;' % (cdecl( self.itemtypename, '*%s_end' % varname), varname, FIXEDARRAY.length) 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: if is_empty and typename.endswith('[RPY_VARLENGTH]'): yield '\tRPY_DUMMY_VARLENGTH' is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};' if self.varlength is not None: assert self.typetag == 'struct' yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};'
def initializationexpr(self, decoration=''): T = self.getTYPE() is_empty = True defnode = self.db.gettypedefnode(T) data = [] if needs_gcheader(T): data.append(('gcheader', self.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 = [] type, name = self.get_declaration() if name != self.name and self.getvarlength() < 1 and len(data) < 2: # an empty union yield '' return yield '{' 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 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 tid_field = c_vtableinfo.value[2] typename = funcgen.db.gettype(op.result.concretetype) 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), self.tid_fieldname(tid_field), funcgen.expr(c_skipoffset), )
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 tid_field = c_vtableinfo.value[2] typename = funcgen.db.gettype(op.result.concretetype) 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), self.tid_fieldname(tid_field), funcgen.expr(c_skipoffset)))
def implementation(self): funcgen = 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, 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 gen_threadlocal_structdef(f, database): from rpython.translator.c.support import cdecl print >> f bk = database.translator.annotator.bookkeeper fields = list(bk.thread_local_fields) fields.sort(key=lambda field: field.fieldname) for field in fields: print >> f, ('#define RPY_TLOFS_%s offsetof(' % field.fieldname + 'struct pypy_threadlocal_s, %s)' % field.fieldname) print >> f, 'struct pypy_threadlocal_s {' print >> f, '\tint ready;' print >> f, '\tchar *stack_end;' for field in fields: typename = database.gettype(field.FIELDTYPE) print >> f, '\t%s;' % cdecl(typename, field.fieldname) print >> f, '};' print >> f
def cfunction_declarations(self): # declare the local variables, excluding the function arguments seen = set() for a in self.graph.getargs(): seen.add(a.name) result_by_name = [] for v in self.allvariables(): name = v.name if name not in seen: seen.add(name) 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]
def gen_threadlocal_structdef(f, database): from rpython.translator.c.support import cdecl print >> f bk = database.translator.annotator.bookkeeper fields = list(bk.thread_local_fields) fields.sort(key=lambda field: field.fieldname) for field in fields: print >> f, ('#define RPY_TLOFS_%s offsetof(' % field.fieldname + 'struct pypy_threadlocal_s, %s)' % field.fieldname) print >> f, 'struct pypy_threadlocal_s {' print >> f, '\tint ready;' print >> f, '\tchar *stack_end;' print >> f, '\tstruct pypy_threadlocal_s *prev, *next;' # note: if the four fixed fields above are changed, you need # to adapt threadlocal.c's linkedlist_head declaration too for field in fields: typename = database.gettype(field.FIELDTYPE) print >> f, '\t%s;' % cdecl(typename, field.fieldname) print >> f, '};' print >> f
def _name_tagged(obj, db): assert obj & 1 == 1 return '((%s) %d)' % (cdecl("void*", ''), obj)
def cfunction_declarations(self): if self.FUNCTYPE.RESULT is not Void: yield '%s;' % cdecl(self.resulttypename, 'result')
def emit(normal_code, tp, value): if tp == 'void @': return emit_void(normal_code) return 'RPY_REVDB_EMIT(%s, %s, %s);' % (normal_code, cdecl(tp, '_e'), value)
def OP_CAST_INT_TO_PTR(self, op): TYPE = self.lltypemap(op.result) typename = self.db.gettype(TYPE) return "%s = (%s)%s;" % (self.expr(op.result), cdecl(typename, ""), self.expr(op.args[0]))
def name_signed(value, db): if isinstance(value, Symbolic): if isinstance(value, FieldOffset): structnode = db.gettypedefnode(value.TYPE) if isinstance(value.TYPE, FixedSizeArray): assert value.fldname.startswith('item') repeat = value.fldname[4:] size = 'sizeof(%s)' % (cdecl(db.gettype(value.TYPE.OF), ''), ) return '(%s * %s)' % (size, repeat) 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 ('(((%(x)s>=%(minsize)s?%(x)s:%(minsize)s) + %(align_m1)s)' ' & ~%(align_m1)s)') % { 'x': name_signed(value.basesize, db), 'minsize': name_signed(value.minsize, db), 'align_m1': MEMORY_ALIGNMENT - 1 } 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 lll('(%s+%dL)') % (name, value.rest) elif isinstance(value, AddressAsInt): return '((Signed)%s)' % name_address(value.adr, db) else: raise Exception("unimplemented symbolic %r" % value) if value is None or isinstance(value, _uninitialized): assert not db.completed return None if value == -sys.maxint - 1: # blame C return lll('(-%dL-1L)') % sys.maxint else: return lll('%dL') % value
def OP_GET_NEXT_GROUP_MEMBER(self, op): typename = self.db.gettype(op.result.concretetype) return '%s = (%s)_OP_GET_NEXT_GROUP_MEMBER(%s, %s, %s);' % (self.expr( op.result), cdecl(typename, ''), self.expr( op.args[0]), self.expr(op.args[1]), self.expr(op.args[2]))
def OP_CAST_INT_TO_PTR(self, op): self._check_split_gc_address_space(op) TYPE = self.lltypemap(op.result) typename = self.db.gettype(TYPE) return "%s = (%s)%s;" % (self.expr(op.result), cdecl( typename, ""), self.expr(op.args[0]))
def OP_THREADLOCALREF_STORE(self, op): typename = self.db.gettype(op.args[1].concretetype) return 'OP_THREADLOCALREF_STORE(%s, %s, %s);' % (cdecl( typename, ''), self.expr(op.args[0]), self.expr(op.args[1]))
def OP_THREADLOCALREF_LOAD(self, op): typename = self.db.gettype(op.result.concretetype) return 'OP_THREADLOCALREF_LOAD(%s, %s, %s);' % (cdecl( typename, ''), self.expr(op.args[0]), self.expr(op.result))
def predeclaretype(c_typename, lowleveltype): typename = db.gettype(lowleveltype) return 'typedef %s;' % cdecl(typename, c_typename)