Do not use CALL macro directly.
[nit.git] / src / compiling / compiling_global.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Compute and generate tables for classes and modules.
18 package compiling_global
19
20 #import compiling_base
21 private import compiling_methods
22 private import syntax
23
24 # Something that store color of table elements
25 class ColorContext
26 attr _colors: HashMap[TableElt, Int] = null
27
28 # The color of a table element.
29 meth color(e: TableElt): Int
30 do
31 return _colors[e]
32 end
33
34 # Is a table element already colored?
35 meth has_color(e: TableElt): Bool
36 do
37 return _colors != null and _colors.has_key(e)
38 end
39
40 # Assign a color to a table element.
41 meth color=(e: TableElt, c: Int)
42 do
43 if _colors == null then _colors = new HashMap[TableElt, Int]
44 _colors[e] = c
45 var idx = c
46 for i in [0..e.length[ do
47 _colors[e.item(i)] = idx
48 idx = idx + 1
49 end
50 end
51 end
52
53 # All information and results of the global analysis.
54 class GlobalAnalysis
55 special ColorContext
56 # Associate global classes to compiled classes
57 readable attr _compiled_classes: HashMap[MMGlobalClass, CompiledClass]
58
59 # The main module of the program globally analysed
60 readable attr _module: MMModule
61
62 # FIXME: do something better.
63 readable writable attr _max_class_table_length: Int
64
65 init(module: MMSrcModule)
66 do
67 _compiled_classes = new HashMap[MMGlobalClass, CompiledClass]
68 _module = module
69 end
70 end
71
72 redef class CompilerVisitor
73 # The global analysis result, if any
74 readable writable attr _global_analysis: GlobalAnalysis
75 end
76
77 # A compiled class is a class in a program
78 class CompiledClass
79 special ColorContext
80 # The corresponding local class in the main module of the prgram
81 readable attr _local_class: MMLocalClass
82
83 # The identifier of the class
84 readable writable attr _id: Int
85
86 # The full class table of the class
87 readable writable attr _class_table: Array[TableElt]
88
89 # The full instance table of the class
90 readable writable attr _instance_table: Array[TableElt]
91
92 # The proper class table part (no superclasses but all refinements)
93 readable writable attr _class_layout: TableEltComposite
94
95 # The proper instance table part (no superclasses but all refinements)
96 readable writable attr _instance_layout: TableEltComposite
97
98 init(c: MMLocalClass) do _local_class = c
99 end
100
101 redef class MMGlobalProperty
102 # The position of the property in the local class table part
103 # FIXME: It's ugly. store this somewhere else please
104 readable writable attr _pos_of: Int
105 end
106
107 redef class MMSrcLocalClass
108 # The table element of the attribute position (for accessor simulation)
109 readable attr _base_attr_pos: TableEltBaseAttrPos
110
111 # The table element of the subtype check
112 readable attr _class_color_pos: TableEltClassColorPos
113
114 # The proper local class table part (nor superclasses nor refinments)
115 readable attr _class_layout: Array[LocalTableElt]
116
117 # The proper local instance table part (nor superclasses nor refinments)
118 readable attr _instance_layout: Array[LocalTableElt]
119
120 # Build the local layout of the class and feed the module table
121 meth build_layout_in(tc: ToolContext, module_table: Array[LocalTableElt])
122 do
123 var intro_methods = new Array[MMGlobalProperty] # FIXME: Remove this
124 var intro_attributes = new Array[MMGlobalProperty] # FIXME: Remove this
125 var clt = new Array[LocalTableElt]
126 _class_layout = clt
127 var ilt = new Array[LocalTableElt]
128 _instance_layout = ilt
129
130 if global.intro == self then
131 module_table.add(new TableEltClassIdPos(self))
132 _class_color_pos = new TableEltClassColorPos(self)
133 module_table.add(_class_color_pos)
134 #clt.add(_class_color_pos)
135 clt.add(new TableEltClassInitTablePos(self))
136 end
137 for p in src_local_properties do
138 var pg = p.global
139 if pg.intro == p then
140 if p isa MMSrcAttribute then
141 pg.pos_of = intro_attributes.length
142 intro_attributes.add(pg)
143 ilt.add(new TableEltAttrPos(p))
144 else if p isa MMSrcMethod then
145 pg.pos_of = intro_methods.length
146 intro_methods.add(pg)
147 clt.add(new TableEltMethPos(p))
148 end
149 end
150 if p isa MMSrcMethod and p.need_super then
151 clt.add(new TableEltSuperPos(p))
152 end
153 end
154 if tc.attr_sim and not intro_attributes.is_empty then
155 _base_attr_pos = new TableEltBaseAttrPos(self)
156 clt.add(_base_attr_pos)
157 else
158 module_table.append(ilt)
159 end
160 module_table.append(clt)
161 end
162 end
163
164 redef class MMSrcModule
165 # The local table of the module (refers things introduced in the module)
166 attr _local_table: Array[LocalTableElt]
167
168 # Builds the local tables and local classes layouts
169 meth local_analysis(tc: ToolContext)
170 do
171 var lt = new Array[LocalTableElt]
172 _local_table = lt
173 for c in src_local_classes do
174 c.build_layout_in(tc, lt)
175 end
176 end
177
178 # Do the complete global analysis
179 meth global_analysis(cctx: ToolContext): GlobalAnalysis
180 do
181 #print "Do the complete global analysis"
182 var ga = new GlobalAnalysis(self)
183 var smallest_classes = new Array[MMLocalClass]
184 var global_properties = new HashSet[MMGlobalProperty]
185 var ctab = new Array[TableElt]
186 var itab = new Array[TableElt]
187
188 ctab.add(new TableEltClassSelfId)
189 itab.add(new TableEltVftPointer)
190
191 var pclassid = -1
192 var classid = 3
193
194 # We have to work on ALL the classes of the module
195 var classes = new Array[MMLocalClass]
196 for c in local_classes do
197 c.compute_super_classes
198 classes.add(c)
199 end
200 (new ClassSorter).sort(classes)
201
202 for c in classes do
203 # Finish processing the class (if invisible)
204 c.compute_ancestors
205 c.inherit_global_properties
206
207 # Associate a CompiledClass to the class
208 var cc = new CompiledClass(c)
209 ga.compiled_classes[c.global] = cc
210
211 # Assign a unique class identifier
212 # (negative are for primitive classes)
213 var gc = c.global
214 var bm = gc.module
215 if c.primitive_info != null then
216 cc.id = pclassid
217 pclassid = pclassid - 4
218 else
219 cc.id = classid
220 classid = classid + 4
221 end
222
223 # Register is the class is a leaf
224 if c.cshe.direct_smallers.is_empty then
225 smallest_classes.add(c)
226 end
227
228 # Store the colortableelt in the class table pool
229 var bc = c.global.intro
230 assert bc isa MMSrcLocalClass
231 ctab.add(bc.class_color_pos)
232 end
233
234 # Compute core and crown classes for colorization
235 var crown_classes = new HashSet[MMLocalClass]
236 var core_classes = new HashSet[MMLocalClass]
237 for c in smallest_classes do
238 while c.cshe.direct_greaters.length == 1 do
239 c = c.cshe.direct_greaters.first
240 end
241 crown_classes.add(c)
242 core_classes.add_all(c.cshe.greaters_and_self)
243 end
244 #print("nbclasses: {classes.length} leaves: {smallest_classes.length} crown: {crown_classes.length} core: {core_classes.length}")
245
246 # Colorize core color for typechecks
247 colorize(ga, ctab, crown_classes, 0)
248
249 # Compute tables for typechecks
250 var maxcolor = 0
251 for c in classes do
252 var cc = ga.compiled_classes[c.global]
253 if core_classes.has(c) then
254 # For core classes, just build the table
255 cc.class_table = build_tables(ga, c, ctab)
256 if maxcolor < cc.class_table.length then maxcolor = cc.class_table.length
257 else
258 # For other classes, it's easier: just append to the parent tables
259 var sc = c.cshe.direct_greaters.first
260 var scc = ga.compiled_classes[sc.global]
261 cc.class_table = scc.class_table.to_a
262 var bc = c.global.intro
263 assert bc isa MMSrcLocalClass
264 var colpos = bc.class_color_pos
265 var colposcolor = cc.class_table.length
266 ga.color(colpos) = colposcolor
267 cc.class_table.add(colpos)
268 if maxcolor < colposcolor then maxcolor = colposcolor
269 end
270 end
271 ga.max_class_table_length = maxcolor + 1
272
273 # Fill class table and instance tables pools
274 for c in classes do
275 var cc = ga.compiled_classes[c.global]
276 var cte = new TableEltComposite(cc)
277 var ite = new TableEltComposite(cc)
278 for sc in c.crhe.greaters_and_self do
279 if sc isa MMSrcLocalClass then
280 cte.add(sc, sc.class_layout)
281 ite.add(sc, sc.instance_layout)
282 end
283 cc.class_layout = cte
284 cc.instance_layout = ite
285 end
286
287 if core_classes.has(c) then
288 if cte.length > 0 then
289 ctab.add(cte)
290 end
291 if not cctx.attr_sim and ite.length > 0 then
292 itab.add(ite)
293 end
294 end
295 end
296
297 # Colorize all elements in pools tables
298 colorize(ga, ctab, crown_classes, maxcolor+1)
299 colorize(ga, itab, crown_classes, 0)
300
301 # Build class and instance tables now things are colored
302 ga.max_class_table_length = 0
303 for c in classes do
304 var cc = ga.compiled_classes[c.global]
305 if core_classes.has(c) then
306 # For core classes, just build the table
307 cc.class_table = build_tables(ga, c, ctab)
308 cc.instance_table = build_tables(ga, c, itab)
309 else
310 # For other classes, it's easier: just append to the parent tables
311 var sc = c.cshe.direct_greaters.first
312 var scc = ga.compiled_classes[sc.global]
313 cc.class_table = scc.class_table.to_a
314 var bc = c.global.intro
315 assert bc isa MMSrcLocalClass
316 var colpos = bc.class_color_pos
317 cc.class_table[ga.color(colpos)] = colpos
318 while cc.class_table.length <= maxcolor do
319 cc.class_table.add(null)
320 end
321 append_to_table(ga, cc.class_table, cc.class_layout)
322 cc.instance_table = scc.instance_table.to_a
323 append_to_table(ga, cc.instance_table, cc.instance_layout)
324 end
325
326 if cctx.attr_sim then
327 cc.instance_table = build_tables(ga, c, itab)
328 for sc in c.cshe.greaters_and_self do
329 var scc = ga.compiled_classes[sc.global]
330 append_to_table(cc, cc.instance_table, scc.instance_layout)
331 end
332 end
333 end
334
335 return ga
336 end
337
338 private meth append_to_table(cc: ColorContext, table: Array[TableElt], cmp: TableEltComposite)
339 do
340 for j in [0..cmp.length[ do
341 var e = cmp.item(j)
342 cc.color(e) = table.length
343 table.add(e)
344 end
345 end
346
347 private meth build_tables(ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt]): Array[TableElt]
348 do
349 var tab = new HashMap[Int, TableElt]
350 var len = 0
351 for e in elts do
352 if e.is_related_to(c) then
353 var col = ga.color(e)
354 var l = col + e.length
355 tab[col] = e
356 if len < l then
357 len = l
358 end
359 end
360 end
361 var res = new Array[TableElt]
362 var i = 0
363 while i < len do
364 if tab.has_key(i) then
365 var e = tab[i]
366 for j in [0..e.length[ do
367 res[i] = e.item(j)
368 i = i + 1
369 end
370 else
371 res[i] = null
372 i = i + 1
373 end
374 end
375 return res
376 end
377
378 # Perform coloring
379 meth colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
380 do
381 var colors = new HashMap[Int, Array[TableElt]]
382 var rel_classes = new Array[MMLocalClass]
383 for e in elts do
384 var color = -1
385 var len = e.length
386 if ga.has_color(e) then
387 color = ga.color(e)
388 else
389 rel_classes.clear
390 for c in classes do
391 if e.is_related_to(c) then
392 rel_classes.add(c)
393 end
394 end
395 var trycolor = startcolor
396 while trycolor != color do
397 color = trycolor
398 for c in rel_classes do
399 var idx = 0
400 while idx < len do
401 if colors.has_key(trycolor + idx) and not free_color(colors[trycolor + idx], c) then
402 trycolor = trycolor + idx + 1
403 idx = 0
404 else
405 idx = idx + 1
406 end
407 end
408 end
409 end
410 ga.color(e) = color
411 end
412 for idx in [0..len[ do
413 if colors.has_key(color + idx) then
414 colors[color + idx].add(e)
415 else
416 colors[color + idx] = [e]
417 end
418 end
419 end
420 end
421
422 private meth free_color(es: Array[TableElt], c: MMLocalClass): Bool
423 do
424 for e2 in es do
425 if e2.is_related_to(c) then
426 return false
427 end
428 end
429 return true
430 end
431
432 # Compile module and class tables
433 meth compile_tables_to_c(v: CompilerVisitor)
434 do
435 for m in mhe.greaters_and_self do
436 assert m isa MMSrcModule
437 m.compile_local_table_to_c(v)
438 end
439
440 for c in local_classes do
441 c.compile_tables_to_c(v)
442 end
443 var s = "classtable_t TAG2VFT[4] = \{NULL"
444 for t in ["Int","Char","Bool"] do
445 if has_global_class_named(t.to_symbol) then
446 s.append(", (const classtable_t)VFT_{t}")
447 else
448 s.append(", NULL")
449 end
450 end
451 s.append("};")
452 v.add_instr(s)
453 end
454
455 # Declare class table (for _sep.h)
456 meth declare_class_tables_to_c(v: CompilerVisitor)
457 do
458 for c in local_classes do
459 if c.global.module == self then
460 c.declare_tables_to_c(v)
461 end
462 end
463 end
464
465 # Compile main part (for _table.c)
466 meth compile_main_part(v: CompilerVisitor)
467 do
468 v.add_instr("int main(int argc, char **argv) \{")
469 v.indent
470 v.add_instr("prepare_signals();")
471 v.add_instr("glob_argc = argc; glob_argv = argv;")
472 var sysname = once "Sys".to_symbol
473 if not has_global_class_named(sysname) then
474 print("No main")
475 else
476 var sys = class_by_name(sysname)
477 # var initm = sys.select_method(once "init".to_symbol)
478 var mainm = sys.select_method(once "main".to_symbol)
479 if mainm == null then
480 print("No main")
481 else
482 #v.add_instr("G_sys = NEW_{initm.cname}();")
483 v.add_instr("G_sys = NEW_Sys();")
484 v.add_instr("{mainm.cname}(G_sys);")
485 end
486 end
487 v.add_instr("return 0;")
488 v.unindent
489 v.add_instr("}")
490 end
491
492 # Compile sep files
493 meth compile_mod_to_c(v: CompilerVisitor)
494 do
495 v.add_decl("extern const char *LOCATE_{name};")
496 if not v.tc.global then
497 v.add_decl("extern const int SFT_{name}[];")
498 end
499 var i = 0
500 for e in _local_table do
501 if v.tc.global then
502 v.add_decl("#define {e.symbol} {e.value(v.global_analysis)}")
503 else
504 v.add_decl("#define {e.symbol} SFT_{name}[{i}]")
505 i = i + 1
506 end
507 end
508 for c in src_local_classes do
509 for pg in c.global_properties do
510 var p = c[pg]
511 if p.local_class == c then
512 if pg.intro == p then
513 if p isa MMAttribute then
514 if v.tc.attr_sim then
515 var bc = pg.local_class
516 assert bc isa MMSrcLocalClass
517 var s = bc.base_attr_pos.symbol
518 v.add_decl("#define {pg.attr_access}(recv) ATTRS(recv, {s}, {pg.pos_of})")
519 else
520 v.add_decl("#define {pg.attr_access}(recv) ATTR(recv, {pg.color_id})")
521 end
522 else if p isa MMMethod then
523 v.add_decl("#define {pg.meth_call}(recv) (({p.cname}_t)CALL((recv), {pg.color_id}))")
524 end
525 end
526 if p isa MMSrcMethod and p.need_super then
527 v.add_decl("#define {p.super_meth_call}(recv) (({p.cname}_t)CALL((recv), {p.color_id_for_super}))")
528 end
529 p.compile_property_to_c(v)
530 end
531 if pg.is_init_for(c) then
532 # Declare constructors
533 var params = new Array[String]
534 for i in [0..p.signature.arity[ do
535 params.add("val_t p{i}")
536 end
537 v.add_decl("val_t NEW_{c}_{p.global.intro.cname}({params.join(", ")});")
538 end
539 end
540 end
541 end
542
543 # Compile module file for the current module
544 meth compile_local_table_to_c(v: CompilerVisitor)
545 do
546 v.add_instr("const char *LOCATE_{name} = \"{filename}\";")
547
548 if v.tc.global or _local_table.is_empty then
549 return
550 end
551
552 v.add_instr("const int SFT_{name}[{_local_table.length}] = \{")
553 v.indent
554 for e in _local_table do
555 v.add_instr(e.value(v.global_analysis) + ",")
556 end
557 v.unindent
558 v.add_instr("\};")
559 end
560 end
561
562 class TableElt
563 meth is_related_to(c: MMLocalClass): Bool is abstract
564 meth length: Int do return 1
565 meth item(i: Int): TableElt do return self
566 meth compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract
567 end
568
569 class LocalTableElt
570 special TableElt
571 meth symbol: String is abstract
572 meth value(ga: GlobalAnalysis): String is abstract
573 end
574
575 class TableEltPropPos
576 special LocalTableElt
577 attr _property: MMLocalProperty
578 redef meth symbol do return _property.global.color_id
579 redef meth value(ga) do return "{ga.color(self)} /* Property {_property} */"
580
581 init(p: MMLocalProperty)
582 do
583 _property = p
584 end
585 end
586
587 class TableEltMethPos
588 special TableEltPropPos
589 redef meth compile_to_c(v, c)
590 do
591 var p = c[_property.global]
592 return p.cname
593 end
594 init(p) do super
595 end
596
597 class TableEltSuperPos
598 special TableEltPropPos
599 redef meth symbol do return _property.color_id_for_super
600 redef meth compile_to_c(v, c)
601 do
602 var pc = _property.local_class
603 var g = _property.global
604 var lin = c.che.linear_extension
605 var found = false
606 for s in lin do
607 #print "{c.module}::{c} for {pc.module}::{pc}::{_property} try {s.module}:{s}"
608 if s == pc then
609 found = true
610 else if found and c.che < s then
611 var p = s[g]
612 if p != null then
613 #print "found {s.module}::{s}::{p}"
614 return p.cname
615 end
616 end
617 end
618 assert false
619 return null
620 end
621
622 init(p) do super
623 end
624
625 class TableEltAttrPos
626 special TableEltPropPos
627 redef meth compile_to_c(v, c)
628 do
629 var ga = v.global_analysis
630 var p = c[_property.global]
631 return "/* {ga.color(self)}: Attribute {c}::{p} */"
632 end
633
634 init(p) do super
635 end
636
637 class TableEltClassPos
638 special LocalTableElt
639 attr _local_class: MMLocalClass
640 redef meth is_related_to(c)
641 do
642 var bc = c.module[_local_class.global]
643 return c.cshe <= bc
644 end
645
646 init(c: MMLocalClass)
647 do
648 _local_class = c
649 end
650 end
651
652 class TableEltClassIdPos
653 special TableEltClassPos
654 redef meth symbol do return _local_class.global.id_id
655 redef meth value(ga)
656 do
657 return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
658 end
659
660 init(c) do super
661 end
662
663 class TableEltClassInitTablePos
664 special TableEltClassPos
665 redef meth symbol do return _local_class.global.init_table_pos_id
666 redef meth value(ga)
667 do
668 return "{ga.color(self)} /* Color of {_local_class} */"
669 end
670 redef meth compile_to_c(v, c)
671 do
672 var ga = v.global_analysis
673 var cc = ga.compiled_classes[_local_class.global]
674 var linext = c.cshe.reverse_linear_extension
675 var i = 0
676 while linext[i].global != _local_class.global do
677 i += 1
678 end
679 return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */"
680 end
681
682 init(c) do super
683 end
684
685 class TableEltClassColorPos
686 special TableEltClassPos
687 redef meth symbol do return _local_class.global.color_id
688 redef meth value(ga)
689 do
690 return "{ga.color(self)} /* Color of {_local_class} */"
691 end
692 redef meth compile_to_c(v, c)
693 do
694 var ga = v.global_analysis
695 var cc = ga.compiled_classes[_local_class.global]
696 return "{cc.id} /* {ga.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */"
697 end
698
699 init(c) do super
700 end
701
702 class TableEltBaseAttrPos
703 special LocalTableElt
704 attr _local_class: MMSrcLocalClass
705 redef meth symbol do return "COLOR_{_local_class.module}_{_local_class.name}_BASEATTR"
706 redef meth value(ga)
707 do
708 return "{ga.color(self)} /* BaseAttrPos of {_local_class} */"
709 end
710
711 redef meth compile_to_c(v, c)
712 do
713 var ga = v.global_analysis
714 var cc = ga.compiled_classes[c.global]
715 return "{cc.color(_local_class.instance_layout.first)} /* {ga.color(self)}: Base attribut offset of {_local_class.module}::{_local_class} in {c} */"
716 end
717
718 init(c: MMSrcLocalClass)
719 do
720 _local_class = c
721 end
722 end
723
724 class TableEltComposite
725 special TableElt
726 attr _table: Array[LocalTableElt]
727 attr _cc: CompiledClass
728 attr _offsets: HashMap[MMLocalClass, Int]
729 redef meth length do return _table.length
730 redef meth is_related_to(c) do return c.cshe <= _cc.local_class
731
732 meth add(c: MMLocalClass, tab: Array[LocalTableElt])
733 do
734 _offsets[c] = _table.length
735 _table.append(tab)
736 end
737
738 redef meth item(i) do return _table[i]
739
740 redef meth compile_to_c(v, c) do abort
741
742 init(cc: CompiledClass)
743 do
744 _cc = cc
745 _table = new Array[LocalTableElt]
746 _offsets = new HashMap[MMLocalClass, Int]
747 end
748 end
749
750 class TableEltClassSelfId
751 special TableElt
752 redef meth is_related_to(c) do return true
753 redef meth compile_to_c(v, c)
754 do
755 var ga = v.global_analysis
756 return "{v.global_analysis.compiled_classes[c.global].id} /* {ga.color(self)}: Identity */"
757 end
758
759 init do end
760 end
761
762 class TableEltVftPointer
763 special TableElt
764 redef meth is_related_to(c) do return true
765 redef meth compile_to_c(v, c)
766 do
767 var ga = v.global_analysis
768 return "/* {ga.color(self)}: Pointer to the classtable */"
769 end
770
771 init do end
772 end
773
774 # Used to sort local class in a deterministic total order
775 # The total order superset the class refinement and the class specialisation relations
776 class ClassSorter
777 special AbstractSorter[MMLocalClass]
778 redef meth compare(a, b) do return a.compare(b)
779 init do end
780 end
781
782 redef class MMLocalClass
783 # Comparaison in a total order that superset the class refinement and the class specialisation relations
784 meth compare(b: MMLocalClass): Int
785 do
786 var a = self
787 if a == b then
788 return 0
789 else if a.module.mhe < b.module then
790 return 1
791 else if b.module.mhe < a.module then
792 return -1
793 end
794 var ar = a.cshe.rank
795 var br = b.cshe.rank
796 if ar > br then
797 return 1
798 else if br > ar then
799 return -1
800 else
801 return b.name.to_s <=> a.name.to_s
802 end
803 end
804
805 # Declaration and macros related to the class table
806 meth declare_tables_to_c(v: CompilerVisitor)
807 do
808 v.add_decl("")
809 var pi = primitive_info
810 v.add_decl("extern const classtable_elt_t VFT_{name}[];")
811 if pi == null then
812 # v.add_decl("val_t NEW_{name}(void);")
813 else if not pi.tagged then
814 var t = pi.cname
815 var tbox = "struct TBOX_{name}"
816 v.add_decl("{tbox} \{ const classtable_elt_t * vft; {t} val;};")
817 v.add_decl("val_t BOX_{name}({t} val);")
818 v.add_decl("#define UNBOX_{name}(x) ((({tbox} *)(VAL2OBJ(x)))->val)")
819 end
820 end
821
822 # Compilation of table and new (or box)
823 meth compile_tables_to_c(v: CompilerVisitor)
824 do
825 var cc = v.global_analysis.compiled_classes[self.global]
826 var ctab = cc.class_table
827 var clen = ctab.length
828 if v.global_analysis.max_class_table_length > ctab.length then
829 clen = v.global_analysis.max_class_table_length
830 end
831
832 v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
833 v.indent
834 for e in ctab do
835 if e == null then
836 v.add_instr("\{0} /* Class Hole :( */,")
837 else
838 v.add_instr("\{(bigint) {e.compile_to_c(v, self)}},")
839 end
840 end
841 if clen > ctab.length then
842 v.add_instr("\{0},"*(clen-ctab.length))
843 end
844 v.unindent
845 v.add_instr("};")
846 var itab = cc.instance_table
847 for e in itab do
848 if e == null then
849 v.add_instr("/* Instance Hole :( */")
850 else
851 v.add_instr(e.compile_to_c(v, self))
852 end
853 end
854
855 var pi = primitive_info
856 if pi == null then
857 v.cfc = new CFunctionContext(v)
858 v.nmc = new NitMethodContext(null)
859 var s = "val_t NEW_{name}(void)"
860 v.add_instr(s + " \{")
861 v.indent
862 var ctx_old = v.ctx
863 v.ctx = new CContext
864
865 var self_var = new ParamVariable(null, null)
866 var self_var_cname = v.cfc.register_variable(self_var)
867 v.nmc.method_params = [self_var]
868
869 v.add_instr("obj_t obj;")
870 v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
871 v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
872 v.add_assignment(self_var_cname, "OBJ2VAL(obj)")
873
874 for g in global_properties do
875 var p = self[g]
876 var t = p.signature.return_type
877 if p isa MMAttribute and t != null then
878 # FIXME: Not compatible with sep compilation
879 assert p isa MMSrcAttribute
880 var np = p.node
881 assert np isa AAttrPropdef
882 var ne = np.n_expr
883 if ne != null then
884 var e = ne.compile_expr(v)
885 v.add_instr("{p.global.attr_access}(obj) = {e};")
886 else
887 var pi = t.local_class.primitive_info
888 if pi != null and pi.tagged then
889 var default = t.default_cvalue
890 v.add_instr("{p.global.attr_access}(obj) = {default};")
891 end
892 end
893 end
894 end
895 v.add_instr("return OBJ2VAL(obj);")
896 v.cfc.generate_var_decls
897 ctx_old.append(v.ctx)
898 v.ctx = ctx_old
899 v.unindent
900 v.add_instr("}")
901
902 var init_table_size = cshe.greaters.length + 1
903 var init_table_decl = "int init_table[{init_table_size}] = \{0{", 0" * (init_table_size-1)}};"
904
905 for g in global_properties do
906 var p = self[g]
907 # FIXME skip invisible constructors
908 if not p.global.is_init_for(self) then continue
909 var params = new Array[String]
910 var args = ["self"]
911 for i in [0..p.signature.arity[ do
912 params.add("val_t p{i}")
913 args.add("p{i}")
914 end
915 args.add("init_table")
916 var s = "val_t NEW_{self}_{p.global.intro.cname}({params.join(", ")}) \{"
917 v.add_instr(s)
918 v.indent
919 v.add_instr(init_table_decl)
920 v.add_instr("val_t self = NEW_{name}();")
921 v.add_instr("{p.cname}({args.join(", ")});")
922 v.add_instr("return self;")
923 v.unindent
924 v.add_instr("}")
925 end
926 else if not pi.tagged then
927 var t = pi.cname
928 var tbox = "struct TBOX_{name}"
929 v.add_instr("val_t BOX_{name}({t} val) \{")
930 v.indent
931 v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
932 v.add_instr("box->vft = VFT_{name};")
933 v.add_instr("box->val = val;")
934 v.add_instr("return OBJ2VAL(box);")
935 v.unindent
936 v.add_instr("}")
937 end
938 end
939 end
940