PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/translator/c/node.py

https://bitbucket.org/pypy/pypy/
Python | 1068 lines | 1045 code | 8 blank | 15 comment | 9 complexity | 45a5caafc9248ad7e55918f9d47a8018 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.rtyper.lltypesystem.lltype import (Struct, Array, FixedSizeArray,
  2. FuncType, typeOf, GcStruct, GcArray, RttiStruct, ContainerType, parentlink,
  3. Void, OpaqueType, Float, RuntimeTypeInfo, getRuntimeTypeInfo, Char,
  4. _subarray)
  5. from rpython.rtyper.lltypesystem import llmemory, llgroup
  6. from rpython.translator.c.funcgen import make_funcgen
  7. from rpython.translator.c.support import USESLOTS # set to False if necessary while refactoring
  8. from rpython.translator.c.support import cdecl, forward_cdecl, somelettersfrom
  9. from rpython.translator.c.support import c_char_array_constant, barebonearray
  10. from rpython.translator.c.primitive import PrimitiveType, name_signed
  11. from rpython.rlib import exports
  12. from rpython.rlib.rfloat import isfinite, isinf
  13. def needs_gcheader(T):
  14. if not isinstance(T, ContainerType):
  15. return False
  16. if T._gckind != 'gc':
  17. return False
  18. if isinstance(T, GcStruct):
  19. if T._first_struct() != (None, None):
  20. return False # gcheader already in the first field
  21. return True
  22. class Node(object):
  23. __slots__ = ("db", )
  24. def __init__(self, db):
  25. self.db = db
  26. class NodeWithDependencies(Node):
  27. __slots__ = ("dependencies", )
  28. def __init__(self, db):
  29. Node.__init__(self, db)
  30. self.dependencies = set()
  31. class StructDefNode(NodeWithDependencies):
  32. typetag = 'struct'
  33. extra_union_for_varlength = True
  34. def __init__(self, db, STRUCT, varlength=None):
  35. NodeWithDependencies.__init__(self, db)
  36. self.STRUCT = STRUCT
  37. self.LLTYPE = STRUCT
  38. self.varlength = varlength
  39. if varlength is None:
  40. basename = STRUCT._name
  41. with_number = True
  42. else:
  43. basename = db.gettypedefnode(STRUCT).barename
  44. basename = '%s_len%d' % (basename, varlength)
  45. with_number = False
  46. if STRUCT._hints.get('union'):
  47. self.typetag = 'union'
  48. assert STRUCT._gckind == 'raw' # not supported: "GcUnion"
  49. if STRUCT._hints.get('typedef'):
  50. self.typetag = ''
  51. assert STRUCT._hints.get('external')
  52. if self.STRUCT._hints.get('external'): # XXX hack
  53. self.forward_decl = None
  54. if STRUCT._hints.get('c_name'):
  55. self.barename = self.name = STRUCT._hints['c_name']
  56. self.c_struct_field_name = self.verbatim_field_name
  57. else:
  58. (self.barename,
  59. self.name) = db.namespace.uniquename(basename,
  60. with_number=with_number,
  61. bare=True)
  62. self.prefix = somelettersfrom(STRUCT._name) + '_'
  63. #
  64. self.fieldnames = STRUCT._names
  65. if STRUCT._hints.get('typeptr', False):
  66. if db.gcpolicy.need_no_typeptr():
  67. assert self.fieldnames == ('typeptr',)
  68. self.fieldnames = ()
  69. #
  70. self.fulltypename = '%s %s @' % (self.typetag, self.name)
  71. def setup(self):
  72. # this computes self.fields
  73. if self.STRUCT._hints.get('external'): # XXX hack
  74. self.fields = None # external definition only
  75. return
  76. self.fields = []
  77. db = self.db
  78. STRUCT = self.STRUCT
  79. if self.varlength is not None:
  80. self.normalizedtypename = db.gettype(STRUCT, who_asks=self)
  81. if needs_gcheader(self.STRUCT):
  82. HDR = db.gcpolicy.struct_gcheader_definition(self)
  83. if HDR is not None:
  84. gc_field = ("_gcheader", db.gettype(HDR, who_asks=self))
  85. self.fields.append(gc_field)
  86. for name in self.fieldnames:
  87. T = self.c_struct_field_type(name)
  88. if name == STRUCT._arrayfld:
  89. typename = db.gettype(T, varlength=self.varlength,
  90. who_asks=self)
  91. else:
  92. typename = db.gettype(T, who_asks=self)
  93. self.fields.append((self.c_struct_field_name(name), typename))
  94. self.computegcinfo(self.db.gcpolicy)
  95. def computegcinfo(self, gcpolicy):
  96. # let the gcpolicy do its own setup
  97. self.gcinfo = None # unless overwritten below
  98. rtti = None
  99. STRUCT = self.STRUCT
  100. if isinstance(STRUCT, RttiStruct):
  101. try:
  102. rtti = getRuntimeTypeInfo(STRUCT)
  103. except ValueError:
  104. pass
  105. if self.varlength is None:
  106. gcpolicy.struct_setup(self, rtti)
  107. return self.gcinfo
  108. def gettype(self):
  109. return self.fulltypename
  110. def c_struct_field_name(self, name):
  111. # occasionally overridden in __init__():
  112. # self.c_struct_field_name = self.verbatim_field_name
  113. return self.prefix + name
  114. def verbatim_field_name(self, name):
  115. assert name.startswith('c_') # produced in this way by rffi
  116. return name[2:]
  117. def c_struct_field_type(self, name):
  118. return self.STRUCT._flds[name]
  119. def access_expr(self, baseexpr, fldname):
  120. fldname = self.c_struct_field_name(fldname)
  121. return '%s.%s' % (baseexpr, fldname)
  122. def ptr_access_expr(self, baseexpr, fldname, baseexpr_is_const=False):
  123. fldname = self.c_struct_field_name(fldname)
  124. if baseexpr_is_const:
  125. return '%s->%s' % (baseexpr, fldname)
  126. return 'RPyField(%s, %s)' % (baseexpr, fldname)
  127. def definition(self):
  128. if self.fields is None: # external definition only
  129. return
  130. yield '%s %s {' % (self.typetag, self.name)
  131. is_empty = True
  132. for name, typename in self.fields:
  133. line = '%s;' % cdecl(typename, name)
  134. if typename == PrimitiveType[Void]:
  135. line = '/* %s */' % line
  136. else:
  137. if is_empty and typename.endswith('[RPY_VARLENGTH]'):
  138. yield '\tRPY_DUMMY_VARLENGTH'
  139. is_empty = False
  140. yield '\t' + line
  141. if is_empty:
  142. yield '\t' + 'char _dummy; /* this struct is empty */'
  143. yield '};'
  144. if self.varlength is not None:
  145. assert self.typetag == 'struct'
  146. yield 'union %su {' % self.name
  147. yield ' struct %s a;' % self.name
  148. yield ' %s;' % cdecl(self.normalizedtypename, 'b')
  149. yield '};'
  150. def visitor_lines(self, prefix, on_field):
  151. for name in self.fieldnames:
  152. FIELD_T = self.c_struct_field_type(name)
  153. cname = self.c_struct_field_name(name)
  154. for line in on_field('%s.%s' % (prefix, cname),
  155. FIELD_T):
  156. yield line
  157. def deflength(varlength):
  158. if varlength is None:
  159. return 'RPY_VARLENGTH'
  160. elif varlength == 0:
  161. return 'RPY_LENGTH0'
  162. else:
  163. return varlength
  164. class ArrayDefNode(NodeWithDependencies):
  165. typetag = 'struct'
  166. extra_union_for_varlength = True
  167. def __init__(self, db, ARRAY, varlength=None):
  168. NodeWithDependencies.__init__(self, db)
  169. self.ARRAY = ARRAY
  170. self.LLTYPE = ARRAY
  171. self.gcfields = []
  172. self.varlength = varlength
  173. if varlength is None:
  174. basename = 'array'
  175. with_number = True
  176. else:
  177. basename = db.gettypedefnode(ARRAY).barename
  178. basename = '%s_len%d' % (basename, varlength)
  179. with_number = False
  180. (self.barename,
  181. self.name) = db.namespace.uniquename(basename, with_number=with_number,
  182. bare=True)
  183. self.fulltypename = '%s %s @' % (self.typetag, self.name)
  184. self.fullptrtypename = '%s %s *@' % (self.typetag, self.name)
  185. def setup(self):
  186. if hasattr(self, 'itemtypename'):
  187. return # setup() was already called, likely by __init__
  188. db = self.db
  189. ARRAY = self.ARRAY
  190. self.computegcinfo(db.gcpolicy)
  191. if self.varlength is not None:
  192. self.normalizedtypename = db.gettype(ARRAY, who_asks=self)
  193. if needs_gcheader(ARRAY):
  194. HDR = db.gcpolicy.array_gcheader_definition(self)
  195. if HDR is not None:
  196. gc_field = ("_gcheader", db.gettype(HDR, who_asks=self))
  197. self.gcfields.append(gc_field)
  198. self.itemtypename = db.gettype(ARRAY.OF, who_asks=self)
  199. def computegcinfo(self, gcpolicy):
  200. # let the gcpolicy do its own setup
  201. self.gcinfo = None # unless overwritten below
  202. if self.varlength is None:
  203. gcpolicy.array_setup(self)
  204. return self.gcinfo
  205. def gettype(self):
  206. return self.fulltypename
  207. def getptrtype(self):
  208. return self.fullptrtypename
  209. def access_expr(self, baseexpr, index):
  210. return '%s.items[%s]' % (baseexpr, index)
  211. access_expr_varindex = access_expr
  212. def ptr_access_expr(self, baseexpr, index, dummy=False):
  213. assert 0 <= index <= sys.maxint, "invalid constant index %r" % (index,)
  214. return self.itemindex_access_expr(baseexpr, index)
  215. def itemindex_access_expr(self, baseexpr, indexexpr):
  216. if self.ARRAY._hints.get('nolength', False):
  217. return 'RPyNLenItem(%s, %s)' % (baseexpr, indexexpr)
  218. else:
  219. return 'RPyItem(%s, %s)' % (baseexpr, indexexpr)
  220. def definition(self):
  221. yield 'struct %s {' % self.name
  222. for fname, typename in self.gcfields:
  223. yield '\t' + cdecl(typename, fname) + ';'
  224. if not self.ARRAY._hints.get('nolength', False):
  225. yield '\tlong length;'
  226. varlength = self.varlength
  227. if varlength is not None:
  228. varlength += self.ARRAY._hints.get('extra_item_after_alloc', 0)
  229. line = '%s;' % cdecl(self.itemtypename,
  230. 'items[%s]' % deflength(varlength))
  231. if self.ARRAY.OF is Void: # strange
  232. line = '/* array of void */'
  233. if self.ARRAY._hints.get('nolength', False):
  234. line = 'char _dummy; ' + line
  235. yield '\t' + line
  236. yield '};'
  237. if self.varlength is not None:
  238. yield 'union %su {' % self.name
  239. yield ' struct %s a;' % self.name
  240. yield ' %s;' % cdecl(self.normalizedtypename, 'b')
  241. yield '};'
  242. def visitor_lines(self, prefix, on_item):
  243. assert self.varlength is None
  244. ARRAY = self.ARRAY
  245. # we need a unique name for this C variable, or at least one that does
  246. # not collide with the expression in 'prefix'
  247. i = 0
  248. varname = 'p0'
  249. while prefix.find(varname) >= 0:
  250. i += 1
  251. varname = 'p%d' % i
  252. body = list(on_item('(*%s)' % varname, ARRAY.OF))
  253. if body:
  254. yield '{'
  255. yield '\t%s = %s.items;' % (cdecl(self.itemtypename, '*' + varname),
  256. prefix)
  257. yield '\t%s = %s + %s.length;' % (cdecl(self.itemtypename,
  258. '*%s_end' % varname),
  259. varname,
  260. prefix)
  261. yield '\twhile (%s != %s_end) {' % (varname, varname)
  262. for line in body:
  263. yield '\t\t' + line
  264. yield '\t\t%s++;' % varname
  265. yield '\t}'
  266. yield '}'
  267. class BareBoneArrayDefNode(NodeWithDependencies):
  268. """For 'simple' array types which don't need a length nor GC headers.
  269. Implemented directly as a C array instead of a struct with an items field.
  270. rffi kind of expects such arrays to be 'bare' C arrays.
  271. """
  272. gcinfo = None
  273. name = None
  274. forward_decl = None
  275. extra_union_for_varlength = False
  276. def __init__(self, db, ARRAY, varlength=None):
  277. NodeWithDependencies.__init__(self, db)
  278. self.ARRAY = ARRAY
  279. self.LLTYPE = ARRAY
  280. self.varlength = varlength
  281. contained_type = ARRAY.OF
  282. # There is no such thing as an array of voids:
  283. # we use a an array of chars instead; only the pointer can be void*.
  284. self.itemtypename = db.gettype(contained_type, who_asks=self)
  285. self.fulltypename = self.itemtypename.replace('@', '(@)[%s]' %
  286. deflength(varlength))
  287. if ARRAY._hints.get("render_as_void"):
  288. self.fullptrtypename = 'void *@'
  289. else:
  290. self.fullptrtypename = self.itemtypename.replace('@', '*@')
  291. if ARRAY._hints.get("render_as_const"):
  292. self.fullptrtypename = 'const ' + self.fullptrtypename
  293. def setup(self):
  294. """Array loops are forbidden by ForwardReference.become() because
  295. there is no way to declare them in C."""
  296. def gettype(self):
  297. return self.fulltypename
  298. def getptrtype(self):
  299. return self.fullptrtypename
  300. def access_expr(self, baseexpr, index):
  301. return '%s[%d]' % (baseexpr, index)
  302. access_expr_varindex = access_expr
  303. def ptr_access_expr(self, baseexpr, index, dummy=False):
  304. assert 0 <= index <= sys.maxint, "invalid constant index %r" % (index,)
  305. return self.itemindex_access_expr(baseexpr, index)
  306. def itemindex_access_expr(self, baseexpr, indexexpr):
  307. if self.ARRAY._hints.get("render_as_void"):
  308. return 'RPyBareItem((char*)%s, %s)' % (baseexpr, indexexpr)
  309. else:
  310. return 'RPyBareItem(%s, %s)' % (baseexpr, indexexpr)
  311. def definition(self):
  312. return [] # no declaration is needed
  313. def visitor_lines(self, prefix, on_item):
  314. raise Exception("cannot visit C arrays - don't know the length")
  315. class FixedSizeArrayDefNode(NodeWithDependencies):
  316. gcinfo = None
  317. name = None
  318. typetag = 'struct'
  319. extra_union_for_varlength = False
  320. def __init__(self, db, FIXEDARRAY):
  321. NodeWithDependencies.__init__(self, db)
  322. self.FIXEDARRAY = FIXEDARRAY
  323. self.LLTYPE = FIXEDARRAY
  324. self.itemtypename = db.gettype(FIXEDARRAY.OF, who_asks=self)
  325. self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' %
  326. FIXEDARRAY.length)
  327. self.fullptrtypename = self.itemtypename.replace('@', '*@')
  328. def setup(self):
  329. """Loops are forbidden by ForwardReference.become() because
  330. there is no way to declare them in C."""
  331. def gettype(self):
  332. return self.fulltypename
  333. def getptrtype(self):
  334. return self.fullptrtypename
  335. def access_expr(self, baseexpr, index, dummy=False):
  336. if not isinstance(index, int):
  337. assert index.startswith('item')
  338. index = int(index[4:])
  339. if not (0 <= index < self.FIXEDARRAY.length):
  340. raise IndexError("refusing to generate a statically out-of-bounds"
  341. " array indexing")
  342. return '%s[%d]' % (baseexpr, index)
  343. ptr_access_expr = access_expr
  344. def access_expr_varindex(self, baseexpr, index):
  345. return '%s[%s]' % (baseexpr, index)
  346. def itemindex_access_expr(self, baseexpr, indexexpr):
  347. return 'RPyFxItem(%s, %s, %d)' % (baseexpr, indexexpr,
  348. self.FIXEDARRAY.length)
  349. def definition(self):
  350. return [] # no declaration is needed
  351. def visitor_lines(self, prefix, on_item):
  352. FIXEDARRAY = self.FIXEDARRAY
  353. # we need a unique name for this C variable, or at least one that does
  354. # not collide with the expression in 'prefix'
  355. i = 0
  356. varname = 'p0'
  357. while prefix.find(varname) >= 0:
  358. i += 1
  359. varname = 'p%d' % i
  360. body = list(on_item('(*%s)' % varname, FIXEDARRAY.OF))
  361. if body:
  362. yield '{'
  363. yield '\t%s = %s;' % (cdecl(self.itemtypename, '*' + varname),
  364. prefix)
  365. yield '\t%s = %s + %d;' % (cdecl(self.itemtypename,
  366. '*%s_end' % varname),
  367. varname,
  368. FIXEDARRAY.length)
  369. yield '\twhile (%s != %s_end) {' % (varname, varname)
  370. for line in body:
  371. yield '\t\t' + line
  372. yield '\t\t%s++;' % varname
  373. yield '\t}'
  374. yield '}'
  375. class ExtTypeOpaqueDefNode(NodeWithDependencies):
  376. """For OpaqueTypes created with the hint render_structure."""
  377. typetag = 'struct'
  378. def __init__(self, db, T):
  379. NodeWithDependencies.__init__(self, db)
  380. self.T = T
  381. self.name = 'RPyOpaque_%s' % (T.tag,)
  382. def setup(self):
  383. pass
  384. def definition(self):
  385. return []
  386. # ____________________________________________________________
  387. class ContainerNode(Node):
  388. if USESLOTS: # keep the number of slots down!
  389. __slots__ = """db obj
  390. typename implementationtypename
  391. name
  392. _funccodegen_owner
  393. globalcontainer""".split()
  394. eci_name = '_compilation_info'
  395. def __init__(self, db, T, obj):
  396. Node.__init__(self, db)
  397. self.obj = obj
  398. self.typename = db.gettype(T) #, who_asks=self)
  399. self.implementationtypename = db.gettype(
  400. T, varlength=self.getvarlength())
  401. parent, parentindex = parentlink(obj)
  402. if obj in exports.EXPORTS_obj2name:
  403. self.name = exports.EXPORTS_obj2name[obj]
  404. self.globalcontainer = 2 # meh
  405. elif parent is None:
  406. self.name = db.namespace.uniquename('g_' + self.basename())
  407. self.globalcontainer = True
  408. else:
  409. self.globalcontainer = False
  410. parentnode = db.getcontainernode(parent)
  411. defnode = db.gettypedefnode(parentnode.getTYPE())
  412. self.name = defnode.access_expr(parentnode.name, parentindex)
  413. if self.typename != self.implementationtypename:
  414. if db.gettypedefnode(T).extra_union_for_varlength:
  415. self.name += '.b'
  416. self._funccodegen_owner = None
  417. def getptrname(self):
  418. return '(&%s)' % self.name
  419. def getTYPE(self):
  420. return typeOf(self.obj)
  421. def is_thread_local(self):
  422. T = self.getTYPE()
  423. return hasattr(T, "_hints") and T._hints.get('thread_local')
  424. def is_exported(self):
  425. return self.globalcontainer == 2 # meh
  426. def compilation_info(self):
  427. return getattr(self.obj, self.eci_name, None)
  428. def get_declaration(self):
  429. if self.name[-2:] == '.b':
  430. # xxx fish fish
  431. assert self.implementationtypename.startswith('struct ')
  432. assert self.implementationtypename.endswith(' @')
  433. uniontypename = 'union %su @' % self.implementationtypename[7:-2]
  434. return uniontypename, self.name[:-2]
  435. else:
  436. return self.implementationtypename, self.name
  437. def forward_declaration(self):
  438. if llgroup.member_of_group(self.obj):
  439. return
  440. type, name = self.get_declaration()
  441. yield '%s;' % (
  442. forward_cdecl(type, name, self.db.standalone,
  443. is_thread_local=self.is_thread_local(),
  444. is_exported=self.is_exported()))
  445. def implementation(self):
  446. if llgroup.member_of_group(self.obj):
  447. return []
  448. lines = list(self.initializationexpr())
  449. type, name = self.get_declaration()
  450. if name != self.name and len(lines) < 2:
  451. # a union with length 0
  452. lines[0] = cdecl(type, name, self.is_thread_local())
  453. else:
  454. if name != self.name:
  455. lines[0] = '{ ' + lines[0] # extra braces around the 'a' part
  456. lines[-1] += ' }' # of the union
  457. lines[0] = '%s = %s' % (
  458. cdecl(type, name, self.is_thread_local()),
  459. lines[0])
  460. lines[-1] += ';'
  461. return lines
  462. def startupcode(self):
  463. return []
  464. def getvarlength(self):
  465. return None
  466. assert not USESLOTS or '__dict__' not in dir(ContainerNode)
  467. class StructNode(ContainerNode):
  468. nodekind = 'struct'
  469. if USESLOTS:
  470. __slots__ = ('gc_init',)
  471. def __init__(self, db, T, obj):
  472. ContainerNode.__init__(self, db, T, obj)
  473. if needs_gcheader(T):
  474. gct = self.db.gctransformer
  475. if gct is not None:
  476. self.gc_init = gct.gcheader_initdata(self.obj)
  477. else:
  478. self.gc_init = None
  479. def basename(self):
  480. T = self.getTYPE()
  481. return T._name
  482. def enum_dependencies(self):
  483. T = self.getTYPE()
  484. for name in T._names:
  485. yield getattr(self.obj, name)
  486. def getvarlength(self):
  487. T = self.getTYPE()
  488. if T._arrayfld is None:
  489. return None
  490. else:
  491. array = getattr(self.obj, T._arrayfld)
  492. return len(array.items)
  493. def initializationexpr(self, decoration=''):
  494. T = self.getTYPE()
  495. is_empty = True
  496. defnode = self.db.gettypedefnode(T)
  497. data = []
  498. if needs_gcheader(T):
  499. data.append(('gcheader', self.gc_init))
  500. for name in defnode.fieldnames:
  501. data.append((name, getattr(self.obj, name)))
  502. # Reasonably, you should only initialise one of the fields of a union
  503. # in C. This is possible with the syntax '.fieldname value' or
  504. # '.fieldname = value'. But here we don't know which of the
  505. # fields need initialization, so XXX we pick the first one
  506. # arbitrarily.
  507. if hasattr(T, "_hints") and T._hints.get('union'):
  508. data = data[0:1]
  509. if 'get_padding_drop' in T._hints:
  510. d = {}
  511. for name, _ in data:
  512. T1 = defnode.c_struct_field_type(name)
  513. typename = self.db.gettype(T1)
  514. d[name] = cdecl(typename, '')
  515. padding_drop = T._hints['get_padding_drop'](d)
  516. else:
  517. padding_drop = []
  518. type, name = self.get_declaration()
  519. if name != self.name and self.getvarlength() < 1 and len(data) < 2:
  520. # an empty union
  521. yield ''
  522. return
  523. yield '{'
  524. for name, value in data:
  525. if name in padding_drop:
  526. continue
  527. c_expr = defnode.access_expr(self.name, name)
  528. lines = generic_initializationexpr(self.db, value, c_expr,
  529. decoration + name)
  530. for line in lines:
  531. yield '\t' + line
  532. if not lines[0].startswith('/*'):
  533. is_empty = False
  534. if is_empty:
  535. yield '\t%s' % '0,'
  536. yield '}'
  537. assert not USESLOTS or '__dict__' not in dir(StructNode)
  538. class GcStructNodeWithHash(StructNode):
  539. # for the outermost level of nested structures, if it has a _hash_cache_.
  540. nodekind = 'struct'
  541. if USESLOTS:
  542. __slots__ = ()
  543. def get_hash_typename(self):
  544. return 'struct _hashT_%s @' % self.name
  545. def forward_declaration(self):
  546. T = self.getTYPE()
  547. assert self.typename == self.implementationtypename # no array part
  548. hash_typename = self.get_hash_typename()
  549. hash_offset = self.db.gctransformer.get_hash_offset(T)
  550. yield '%s {' % cdecl(hash_typename, '')
  551. yield '\tunion {'
  552. yield '\t\t%s;' % cdecl(self.implementationtypename, 'head')
  553. yield '\t\tchar pad[%s];' % name_signed(hash_offset, self.db)
  554. yield '\t} u;'
  555. yield '\tlong hash;'
  556. yield '};'
  557. yield '%s;' % (
  558. forward_cdecl(hash_typename, '_hash_' + self.name,
  559. self.db.standalone, self.is_thread_local()),)
  560. yield '#define %s _hash_%s.u.head' % (self.name, self.name)
  561. def implementation(self):
  562. hash_typename = self.get_hash_typename()
  563. hash = self.db.gctransformer.get_prebuilt_hash(self.obj)
  564. assert hash is not None
  565. lines = list(self.initializationexpr())
  566. lines.insert(0, '%s = { {' % (
  567. cdecl(hash_typename, '_hash_' + self.name,
  568. self.is_thread_local()),))
  569. lines.append('}, %s /* hash */ };' % name_signed(hash, self.db))
  570. return lines
  571. def gcstructnode_factory(db, T, obj):
  572. if (db.gctransformer and
  573. db.gctransformer.get_prebuilt_hash(obj) is not None):
  574. cls = GcStructNodeWithHash
  575. else:
  576. cls = StructNode
  577. return cls(db, T, obj)
  578. class ArrayNode(ContainerNode):
  579. nodekind = 'array'
  580. if USESLOTS:
  581. __slots__ = ('gc_init',)
  582. def __init__(self, db, T, obj):
  583. ContainerNode.__init__(self, db, T, obj)
  584. if needs_gcheader(T):
  585. gct = self.db.gctransformer
  586. if gct is not None:
  587. self.gc_init = gct.gcheader_initdata(self.obj)
  588. else:
  589. self.gc_init = None
  590. def getptrname(self):
  591. if barebonearray(self.getTYPE()):
  592. return self.name
  593. return ContainerNode.getptrname(self)
  594. def basename(self):
  595. return 'array'
  596. def enum_dependencies(self):
  597. return self.obj.items
  598. def getvarlength(self):
  599. return len(self.obj.items)
  600. def initializationexpr(self, decoration=''):
  601. T = self.getTYPE()
  602. yield '{'
  603. if needs_gcheader(T):
  604. lines = generic_initializationexpr(self.db, self.gc_init, 'gcheader',
  605. '%sgcheader' % (decoration,))
  606. for line in lines:
  607. yield line
  608. if T._hints.get('nolength', False):
  609. length = ''
  610. else:
  611. length = '%d, ' % len(self.obj.items)
  612. if T.OF is Void or len(self.obj.items) == 0:
  613. yield '\t%s' % length.rstrip(', ')
  614. yield '}'
  615. elif T.OF == Char:
  616. if len(self.obj.items) and self.obj.items[0] is None:
  617. s = ''.join([self.obj.getitem(i) for i in range(len(self.obj.items))])
  618. else:
  619. s = ''.join(self.obj.items)
  620. array_constant = c_char_array_constant(s)
  621. if array_constant.startswith('{') and barebonearray(T):
  622. assert array_constant.endswith('}')
  623. array_constant = array_constant[1:-1].strip()
  624. yield '\t%s%s' % (length, array_constant)
  625. yield '}'
  626. else:
  627. barebone = barebonearray(T)
  628. if not barebone:
  629. yield '\t%s{' % length
  630. for j in range(len(self.obj.items)):
  631. value = self.obj.items[j]
  632. basename = self.name
  633. if basename.endswith('.b'):
  634. basename = basename[:-2] + '.a'
  635. lines = generic_initializationexpr(self.db, value,
  636. '%s.items[%d]' % (basename, j),
  637. '%s%d' % (decoration, j))
  638. for line in lines:
  639. yield '\t' + line
  640. if not barebone:
  641. yield '} }'
  642. else:
  643. yield '}'
  644. assert not USESLOTS or '__dict__' not in dir(ArrayNode)
  645. class FixedSizeArrayNode(ContainerNode):
  646. nodekind = 'array'
  647. if USESLOTS:
  648. __slots__ = ()
  649. def getptrname(self):
  650. if not isinstance(self.obj, _subarray): # XXX hackish
  651. return self.name
  652. return ContainerNode.getptrname(self)
  653. def basename(self):
  654. T = self.getTYPE()
  655. return T._name
  656. def enum_dependencies(self):
  657. for i in range(self.obj.getlength()):
  658. yield self.obj.getitem(i)
  659. def getvarlength(self):
  660. return None # not variable-sized!
  661. def initializationexpr(self, decoration=''):
  662. T = self.getTYPE()
  663. assert self.typename == self.implementationtypename # not var-sized
  664. yield '{'
  665. # _names == ['item0', 'item1', ...]
  666. for j, name in enumerate(T._names):
  667. value = getattr(self.obj, name)
  668. lines = generic_initializationexpr(self.db, value,
  669. '%s[%d]' % (self.name, j),
  670. '%s%d' % (decoration, j))
  671. for line in lines:
  672. yield '\t' + line
  673. yield '}'
  674. def generic_initializationexpr(db, value, access_expr, decoration):
  675. if isinstance(typeOf(value), ContainerType):
  676. node = db.getcontainernode(value)
  677. lines = list(node.initializationexpr(decoration+'.'))
  678. lines[-1] += ','
  679. return lines
  680. else:
  681. comma = ','
  682. if typeOf(value) == Float and not isfinite(value):
  683. db.late_initializations.append(('%s' % access_expr, db.get(value)))
  684. if isinf(value):
  685. name = '-+'[value > 0] + 'inf'
  686. else:
  687. name = 'NaN'
  688. expr = '0.0 /* patched later with %s */' % (name,)
  689. else:
  690. expr = db.get(value)
  691. if typeOf(value) is Void:
  692. comma = ''
  693. expr += comma
  694. i = expr.find('\n')
  695. if i < 0:
  696. i = len(expr)
  697. expr = '%s\t/* %s */%s' % (expr[:i], decoration, expr[i:])
  698. return expr.split('\n')
  699. # ____________________________________________________________
  700. class FuncNodeBase(ContainerNode):
  701. nodekind = 'func'
  702. eci_name = 'compilation_info'
  703. # there not so many node of this kind, slots should not
  704. # be necessary
  705. def __init__(self, db, T, obj, ptrname):
  706. Node.__init__(self, db)
  707. self.globalcontainer = True
  708. self.T = T
  709. self.obj = obj
  710. self.name = ptrname
  711. self.typename = db.gettype(T) #, who_asks=self)
  712. def getptrname(self):
  713. return self.name
  714. def basename(self):
  715. return self.obj._name
  716. class FuncNode(FuncNodeBase):
  717. def __init__(self, db, T, obj, ptrname):
  718. FuncNodeBase.__init__(self, db, T, obj, ptrname)
  719. exception_policy = getattr(obj, 'exception_policy', None)
  720. self.funcgen = make_funcgen(obj.graph, db, exception_policy, ptrname)
  721. argnames = self.funcgen.argnames()
  722. self.implementationtypename = db.gettype(T, argnames=argnames)
  723. self._funccodegen_owner = self.funcgen
  724. def enum_dependencies(self):
  725. return self.funcgen.allconstantvalues()
  726. def forward_declaration(self):
  727. callable = getattr(self.obj, '_callable', None)
  728. is_exported = getattr(callable, 'exported_symbol', False)
  729. yield '%s;' % (
  730. forward_cdecl(self.implementationtypename,
  731. self.name, self.db.standalone, is_exported=is_exported))
  732. def graphs_to_patch(self):
  733. for i in self.funcgen.graphs_to_patch():
  734. yield i
  735. def implementation(self):
  736. funcgen = self.funcgen
  737. funcgen.implementation_begin()
  738. # recompute implementationtypename as the argnames may have changed
  739. argnames = funcgen.argnames()
  740. implementationtypename = self.db.gettype(self.T, argnames=argnames)
  741. yield '%s {' % cdecl(implementationtypename, self.name)
  742. #
  743. # declare the local variables
  744. #
  745. localnames = list(funcgen.cfunction_declarations())
  746. lengths = [len(a) for a in localnames]
  747. lengths.append(9999)
  748. start = 0
  749. while start < len(localnames):
  750. # pack the local declarations over as few lines as possible
  751. total = lengths[start] + 8
  752. end = start + 1
  753. while total + lengths[end] < 77:
  754. total += lengths[end] + 1
  755. end += 1
  756. yield '\t' + ' '.join(localnames[start:end])
  757. start = end
  758. #
  759. # generate the body itself
  760. #
  761. bodyiter = funcgen.cfunction_body()
  762. for line in bodyiter:
  763. # performs some formatting on the generated body:
  764. # indent normal lines with tabs; indent labels less than the rest
  765. if line.endswith(':'):
  766. if line.startswith('err'):
  767. try:
  768. nextline = bodyiter.next()
  769. except StopIteration:
  770. nextline = ''
  771. # merge this 'err:' label with the following line
  772. line = '\t%s\t%s' % (line, nextline)
  773. else:
  774. line = ' ' + line
  775. elif line:
  776. line = '\t' + line
  777. yield line
  778. yield '}'
  779. del bodyiter
  780. funcgen.implementation_end()
  781. class ExternalFuncNode(FuncNodeBase):
  782. def __init__(self, db, T, obj, ptrname):
  783. FuncNodeBase.__init__(self, db, T, obj, ptrname)
  784. self._funccodegen_owner = None
  785. def enum_dependencies(self):
  786. return []
  787. def forward_declaration(self):
  788. return []
  789. def implementation(self):
  790. return []
  791. def new_funcnode(db, T, obj, forcename=None):
  792. from rpython.rtyper.rtyper import llinterp_backend
  793. if db.sandbox:
  794. if (getattr(obj, 'external', None) is not None and
  795. not obj._safe_not_sandboxed):
  796. from rpython.translator.sandbox import rsandbox
  797. obj.__dict__['graph'] = rsandbox.get_sandbox_stub(
  798. obj, db.translator.rtyper)
  799. obj.__dict__.pop('_safe_not_sandboxed', None)
  800. obj.__dict__.pop('external', None)
  801. if forcename:
  802. name = forcename
  803. else:
  804. name = _select_name(db, obj)
  805. if hasattr(obj, 'graph'):
  806. return FuncNode(db, T, obj, name)
  807. elif getattr(obj, 'external', None) is not None:
  808. assert obj.external == 'C'
  809. if db.sandbox:
  810. assert obj._safe_not_sandboxed
  811. return ExternalFuncNode(db, T, obj, name)
  812. elif hasattr(obj._callable, "c_name"):
  813. return ExternalFuncNode(db, T, obj, name) # this case should only be used for entrypoints
  814. elif db.translator.rtyper.backend is llinterp_backend:
  815. # on llinterp, anything goes
  816. return ExternalFuncNode(db, T, obj, name)
  817. else:
  818. raise ValueError("don't know how to generate code for %r" % (obj,))
  819. def _select_name(db, obj):
  820. try:
  821. return obj._callable.c_name
  822. except AttributeError:
  823. pass
  824. if getattr(obj, 'external', None) == 'C':
  825. return obj._name
  826. return db.namespace.uniquename('g_' + obj._name)
  827. class ExtType_OpaqueNode(ContainerNode):
  828. nodekind = 'rpyopaque'
  829. def enum_dependencies(self):
  830. return []
  831. def initializationexpr(self, decoration=''):
  832. T = self.getTYPE()
  833. raise NotImplementedError(
  834. 'seeing an unexpected prebuilt object: %s' % (T.tag,))
  835. def startupcode(self):
  836. T = self.getTYPE()
  837. args = [self.getptrname()]
  838. # XXX how to make this code more generic?
  839. if T.tag == 'ThreadLock':
  840. lock = self.obj.externalobj
  841. if lock.locked():
  842. args.append('1')
  843. else:
  844. args.append('0')
  845. yield 'RPyOpaque_SETUP_%s(%s);' % (T.tag, ', '.join(args))
  846. def opaquenode_factory(db, T, obj):
  847. if T == RuntimeTypeInfo:
  848. return db.gcpolicy.rtti_node_factory()(db, T, obj)
  849. if T.hints.get("render_structure", False):
  850. return ExtType_OpaqueNode(db, T, obj)
  851. raise Exception("don't know about %r" % (T,))
  852. def weakrefnode_factory(db, T, obj):
  853. assert isinstance(obj, llmemory._wref)
  854. ptarget = obj._dereference()
  855. wrapper = db.gcpolicy.convert_weakref_to(ptarget)
  856. container = wrapper._obj
  857. #obj._converted_weakref = container # hack for genllvm :-/
  858. return db.getcontainernode(container, _dont_write_c_code=False)
  859. class GroupNode(ContainerNode):
  860. nodekind = 'group'
  861. count_members = None
  862. def __init__(self, *args):
  863. ContainerNode.__init__(self, *args)
  864. self.implementationtypename = 'struct group_%s_s @' % self.name
  865. def basename(self):
  866. return self.obj.name
  867. def enum_dependencies(self):
  868. # note: for the group used by the GC, it can grow during this phase,
  869. # which means that we might not return all members yet. This is fixed
  870. # by get_finish_tables() in rpython.memory.gctransform.framework.
  871. for member in self.obj.members:
  872. yield member._as_ptr()
  873. def _fix_members(self):
  874. if self.obj.outdated:
  875. raise Exception(self.obj.outdated)
  876. if self.count_members is None:
  877. self.count_members = len(self.obj.members)
  878. else:
  879. # make sure no new member showed up, because it's too late
  880. assert len(self.obj.members) == self.count_members
  881. def forward_declaration(self):
  882. self._fix_members()
  883. yield ''
  884. ctype = ['%s {' % cdecl(self.implementationtypename, '')]
  885. for i, member in enumerate(self.obj.members):
  886. structtypename = self.db.gettype(typeOf(member))
  887. ctype.append('\t%s;' % cdecl(structtypename, 'member%d' % i))
  888. ctype.append('} @')
  889. ctype = '\n'.join(ctype)
  890. yield '%s;' % (
  891. forward_cdecl(ctype, self.name, self.db.standalone,
  892. self.is_thread_local()))
  893. yield '#include "src/llgroup.h"'
  894. yield 'PYPY_GROUP_CHECK_SIZE(%s)' % (self.name,)
  895. for i, member in enumerate(self.obj.members):
  896. structnode = self.db.getcontainernode(member)
  897. yield '#define %s %s.member%d' % (structnode.name,
  898. self.name, i)
  899. yield ''
  900. def initializationexpr(self):
  901. self._fix_members()
  902. lines = ['{']
  903. lasti = len(self.obj.members) - 1
  904. for i, member in enumerate(self.obj.members):
  905. structnode = self.db.getcontainernode(member)
  906. lines1 = list(structnode.initializationexpr())
  907. lines1[0] += '\t/* member%d: %s */' % (i, structnode.name)
  908. if i != lasti:
  909. lines1[-1] += ','
  910. lines.extend(lines1)
  911. lines.append('}')
  912. return lines
  913. ContainerNodeFactory = {
  914. Struct: StructNode,
  915. GcStruct: gcstructnode_factory,
  916. Array: ArrayNode,
  917. GcArray: ArrayNode,
  918. FixedSizeArray: FixedSizeArrayNode,
  919. FuncType: new_funcnode,
  920. OpaqueType: opaquenode_factory,
  921. llmemory._WeakRefType: weakrefnode_factory,
  922. llgroup.GroupType: GroupNode,
  923. }