# Compute and generate tables for classes and modules.
package compiling_global
+import program
private import compiling_icode
# Something that store color of table elements
end
# All information and results of the global analysis.
-class GlobalAnalysis
+class TableInformation
special ColorContext
- # Associate global classes to compiled classes
- readable var _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new HashMap[MMGlobalClass, CompiledClass]
-
- # The main module of the program globally analysed
- readable var _module: MMModule
-
# FIXME: do something better.
readable writable var _max_class_table_length: Int = 0
-
- init(module: MMModule)
- do
- _module = module
- end
end
class GlobalCompilerVisitor
special CompilerVisitor
# The global analysis result
- readable var _global_analysis: GlobalAnalysis
- init(m: MMModule, tc: ToolContext, ga: GlobalAnalysis)
+ readable var _program: Program
+ init(m: MMModule, tc: ToolContext, prog: Program)
do
super(m, tc)
- _global_analysis = ga
+ _program = prog
end
end
end
end
-redef class MMModule
- # The local table of the module (refers things introduced in the module)
- var _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt]
+redef class Program
+ # Information about the class tables
+ readable var _table_information: TableInformation = new TableInformation
- # Builds the local tables and local classes layouts
- fun local_analysis(tc: ToolContext)
- do
- for c in local_classes do
- if c isa MMConcreteClass then
- c.build_layout_in(tc, _local_table)
- end
- end
- end
+ # Associate global classes to compiled classes
+ readable var _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new HashMap[MMGlobalClass, CompiledClass]
# Do the complete global analysis
- fun global_analysis(cctx: ToolContext): GlobalAnalysis
+ fun global_analysis(cctx: ToolContext)
do
- #print "Do the complete global analysis"
- var ga = new GlobalAnalysis(self)
var smallest_classes = new Array[MMLocalClass]
var global_properties = new HashSet[MMGlobalProperty]
var ctab = new Array[TableElt]
# We have to work on ALL the classes of the module
var classes = new Array[MMLocalClass]
- for c in local_classes do
+ for c in module.local_classes do
c.compute_super_classes
classes.add(c)
end
# Associate a CompiledClass to the class
var cc = new CompiledClass(c)
- ga.compiled_classes[c.global] = cc
+ compiled_classes[c.global] = cc
# Assign a unique class identifier
# (negative are for primitive classes)
#print("nbclasses: {classes.length} leaves: {smallest_classes.length} crown: {crown_classes.length} core: {core_classes.length}")
# Colorize core color for typechecks
- colorize(ga, ctab, crown_classes, 0)
+ colorize(ctab, crown_classes, 0)
# Compute tables for typechecks
var maxcolor = 0
for c in classes do
- var cc = ga.compiled_classes[c.global]
+ var cc = compiled_classes[c.global]
if core_classes.has(c) then
# For core classes, just build the table
- build_tables_in(cc.class_table, ga, c, ctab)
+ build_tables_in(cc.class_table, c, ctab)
if maxcolor < cc.class_table.length then maxcolor = cc.class_table.length
else
# For other classes, it's easier: just append to the parent tables
var sc = c.cshe.direct_greaters.first
- var scc = ga.compiled_classes[sc.global]
+ var scc = compiled_classes[sc.global]
assert cc.class_table.is_empty
cc.class_table.add_all(scc.class_table)
var bc = c.global.intro
assert bc isa MMConcreteClass
var colpos = bc.class_color_pos
var colposcolor = cc.class_table.length
- ga.color(colpos) = colposcolor
+ table_information.color(colpos) = colposcolor
cc.class_table.add(colpos)
if maxcolor < colposcolor then maxcolor = colposcolor
end
end
- ga.max_class_table_length = maxcolor + 1
+ table_information.max_class_table_length = maxcolor + 1
# Fill class table and instance tables pools
for c in classes do
- var cc = ga.compiled_classes[c.global]
+ var cc = compiled_classes[c.global]
var cte = cc.class_layout
var ite = cc.instance_layout
for sc in c.crhe.greaters_and_self do
end
# Colorize all elements in pools tables
- colorize(ga, ctab, crown_classes, maxcolor+1)
- colorize(ga, itab, crown_classes, 0)
+ colorize(ctab, crown_classes, maxcolor+1)
+ colorize(itab, crown_classes, 0)
# Build class and instance tables now things are colored
- ga.max_class_table_length = 0
+ table_information.max_class_table_length = 0
for c in classes do
- var cc = ga.compiled_classes[c.global]
+ var cc = compiled_classes[c.global]
if core_classes.has(c) then
# For core classes, just build the table
- build_tables_in(cc.class_table, ga, c, ctab)
- build_tables_in(cc.instance_table, ga, c, itab)
+ build_tables_in(cc.class_table, c, ctab)
+ build_tables_in(cc.instance_table, c, itab)
else
# For other classes, it's easier: just append to the parent tables
var sc = c.cshe.direct_greaters.first
- var scc = ga.compiled_classes[sc.global]
+ var scc = compiled_classes[sc.global]
cc.class_table.clear
cc.class_table.add_all(scc.class_table)
var bc = c.global.intro
assert bc isa MMConcreteClass
var colpos = bc.class_color_pos
- cc.class_table[ga.color(colpos)] = colpos
+ cc.class_table[table_information.color(colpos)] = colpos
while cc.class_table.length <= maxcolor do
cc.class_table.add(null)
end
- append_to_table(ga, cc.class_table, cc.class_layout)
+ append_to_table(cc.class_table, cc.class_layout)
assert cc.instance_table.is_empty
cc.instance_table.add_all(scc.instance_table)
- append_to_table(ga, cc.instance_table, cc.instance_layout)
- end
- end
-
- return ga
- end
-
- private fun append_to_table(cc: ColorContext, table: Array[nullable TableElt], cmp: TableEltComposite)
- do
- for j in [0..cmp.length[ do
- var e = cmp.item(j)
- cc.color(e) = table.length
- table.add(e)
- end
- end
-
- private fun build_tables_in(table: Array[nullable TableElt], ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt])
- do
- var tab = new HashMap[Int, TableElt]
- var len = 0
- for e in elts do
- if e.is_related_to(c) then
- var col = ga.color(e)
- var l = col + e.length
- tab[col] = e
- if len < l then
- len = l
- end
- end
- end
- var i = 0
- while i < len do
- if tab.has_key(i) then
- var e = tab[i]
- for j in [0..e.length[ do
- table[i] = e.item(j)
- i = i + 1
- end
- else
- table[i] = null
- i = i + 1
+ append_to_table(cc.instance_table, cc.instance_layout)
end
end
end
# Perform coloring
- fun colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
+ fun colorize(elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
do
var colors = new HashMap[Int, Array[TableElt]]
var rel_classes = new Array[MMLocalClass]
for e in elts do
var color = -1
var len = e.length
- if ga.has_color(e) then
- color = ga.color(e)
+ if table_information.has_color(e) then
+ color = table_information.color(e)
else
rel_classes.clear
for c in classes do
end
end
end
- ga.color(e) = color
+ table_information.color(e) = color
end
for idx in [0..len[ do
if colors.has_key(color + idx) then
return true
end
+ private fun append_to_table(table: Array[nullable TableElt], cmp: TableEltComposite)
+ do
+ for j in [0..cmp.length[ do
+ var e = cmp.item(j)
+ table_information.color(e) = table.length
+ table.add(e)
+ end
+ end
+
+ private fun build_tables_in(table: Array[nullable TableElt], c: MMLocalClass, elts: Array[TableElt])
+ do
+ var tab = new HashMap[Int, TableElt]
+ var len = 0
+ for e in elts do
+ if e.is_related_to(c) then
+ var col = table_information.color(e)
+ var l = col + e.length
+ tab[col] = e
+ if len < l then
+ len = l
+ end
+ end
+ end
+ var i = 0
+ while i < len do
+ if tab.has_key(i) then
+ var e = tab[i]
+ for j in [0..e.length[ do
+ table[i] = e.item(j)
+ i = i + 1
+ end
+ else
+ table[i] = null
+ i = i + 1
+ end
+ end
+ end
+
# Compile module and class tables
fun compile_tables_to_c(v: GlobalCompilerVisitor)
do
- for m in mhe.greaters_and_self do
+ for m in module.mhe.greaters_and_self do
m.compile_local_table_to_c(v)
end
- for c in local_classes do
+ for c in module.local_classes do
c.compile_tables_to_c(v)
end
var s = new Buffer.from("classtable_t TAG2VFT[4] = \{NULL")
for t in ["Int","Char","Bool"] do
- if has_global_class_named(t.to_symbol) then
+ if module.has_global_class_named(t.to_symbol) then
s.append(", (const classtable_t)VFT_{t}")
else
s.append(", NULL")
v.add_instr(s.to_s)
end
- # Declare class table (for _sep.h)
- fun declare_class_tables_to_c(v: GlobalCompilerVisitor)
- do
- for c in local_classes do
- if c.global.module == self then
- c.declare_tables_to_c(v)
- end
- end
- end
-
# Compile main part (for _table.c)
fun compile_main_part(v: GlobalCompilerVisitor)
do
v.add_instr("prepare_signals();")
v.add_instr("glob_argc = argc; glob_argv = argv;")
var sysname = once "Sys".to_symbol
- if not has_global_class_named(sysname) then
+ if not module.has_global_class_named(sysname) then
print("No main")
else
- var sys = class_by_name(sysname)
+ var sys = module.class_by_name(sysname)
var name = once "main".to_symbol
if not sys.has_global_property_by_name(name) then
print("No main")
v.unindent
v.add_instr("}")
end
+end
+
+redef class MMModule
+ # The local table of the module (refers things introduced in the module)
+ var _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt]
+
+ # Builds the local tables and local classes layouts
+ fun local_analysis(tc: ToolContext)
+ do
+ for c in local_classes do
+ if c isa MMConcreteClass then
+ c.build_layout_in(tc, _local_table)
+ end
+ end
+ end
+
+ # Declare class table (for _sep.h)
+ fun declare_class_tables_to_c(v: GlobalCompilerVisitor)
+ do
+ for c in local_classes do
+ if c.global.module == self then
+ c.declare_tables_to_c(v)
+ end
+ end
+ end
# Compile sep files
fun compile_mod_to_c(v: GlobalCompilerVisitor)
for e in _local_table do
var value: String
if v.tc.global then
- value = "{e.value(v.global_analysis)}"
+ value = "{e.value(v.program)}"
else
value = "SFT_{name}[{i}]"
i = i + 1
v.add_instr("const int SFT_{name}[{_local_table.length}] = \{")
v.indent
for e in _local_table do
- v.add_instr(e.value(v.global_analysis) + ",")
+ v.add_instr(e.value(v.program) + ",")
end
v.unindent
v.add_instr("\};")
abstract class ModuleTableElt
special AbsTableElt
# Return the value of the element once the global analisys is performed
- fun value(ga: GlobalAnalysis): String is abstract
+ fun value(prog: Program): String is abstract
end
# An element of a module table that represents a group of TableElt defined in the same local class
special ModuleTableElt
readable var _elements: Array[TableElt] = new Array[TableElt]
- redef fun value(ga) do return "{ga.color(_elements.first)} /* Group of ? */"
+ redef fun value(prog) do return "{prog.table_information.color(_elements.first)} /* Group of ? */"
redef fun compile_macros(v, value)
do
var i = 0
redef fun compile_to_c(v, c)
do
- var ga = v.global_analysis
+ var prog = v.program
var p = c[_property.global]
- return "/* {ga.color(self)}: Attribute {c}::{p} */"
+ return "/* {prog.table_information.color(self)}: Attribute {c}::{p} */"
end
end
special AbsTableEltClass
redef fun symbol do return _local_class.global.id_id
- redef fun value(ga)
+ redef fun value(prog)
do
- return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
+ return "{prog.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
end
end
redef fun compile_to_c(v, c)
do
- var ga = v.global_analysis
- var cc = ga.compiled_classes[_local_class.global]
+ var prog = v.program
+ var cc = prog.compiled_classes[_local_class.global]
var linext = c.cshe.reverse_linear_extension
var i = 0
while linext[i].global != _local_class.global do
i += 1
end
- return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */"
+ return "{i} /* {prog.table_information.color(self)}: {c} < {cc.local_class}: superclass init_table position */"
end
end
special ModuleTableElt
redef fun symbol do return _local_class.global.color_id
- redef fun value(ga)
+ redef fun value(prog)
do
- return "{ga.color(self)} /* Color of {_local_class} */"
+ return "{prog.table_information.color(self)} /* Color of {_local_class} */"
end
redef fun compile_to_c(v, c)
do
- var ga = v.global_analysis
- var cc = ga.compiled_classes[_local_class.global]
- return "{cc.id} /* {ga.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */"
+ var prog = v.program
+ var cc = prog.compiled_classes[_local_class.global]
+ return "{cc.id} /* {prog.table_information.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */"
end
end
redef fun is_related_to(c) do return true
redef fun compile_to_c(v, c)
do
- var ga = v.global_analysis
- return "{v.global_analysis.compiled_classes[c.global].id} /* {ga.color(self)}: Identity */"
+ var prog = v.program
+ return "{prog.compiled_classes[c.global].id} /* {prog.table_information.color(self)}: Identity */"
end
end
redef fun compile_to_c(v, c)
do
var nb = 0
- var ga = v.global_analysis
+ var p = v.program
if c.name == "NativeArray".to_symbol then
nb = -1
else
- var cc = ga.compiled_classes[c.global]
+ var cc = p.compiled_classes[c.global]
var itab = cc.instance_table
for e in itab do
nb += 1
end
end
- return "{nb} /* {ga.color(self)}: Object size (-1 if a NativeArray)*/"
+ return "{nb} /* {p.table_information.color(self)}: Object size (-1 if a NativeArray)*/"
end
end
redef fun is_related_to(c) do return true
redef fun compile_to_c(v, c)
do
- var ga = v.global_analysis
- return "/* {ga.color(self)}: Object_id */"
+ var p = v.program
+ return "/* {p.table_information.color(self)}: Object_id */"
end
end
redef fun is_related_to(c) do return true
redef fun compile_to_c(v, c)
do
- var ga = v.global_analysis
- return "/* {ga.color(self)}: Pointer to the classtable */"
+ var prog = v.program
+ return "/* {prog.table_information.color(self)}: Pointer to the classtable */"
end
end
# Compilation of table and new (or box)
fun compile_tables_to_c(v: GlobalCompilerVisitor)
do
- var cc = v.global_analysis.compiled_classes[self.global]
+ var cc = v.program.compiled_classes[self.global]
var ctab = cc.class_table
var clen = ctab.length
- if v.global_analysis.max_class_table_length > ctab.length then
- clen = v.global_analysis.max_class_table_length
+ if v.program.table_information.max_class_table_length > ctab.length then
+ clen = v.program.table_information.max_class_table_length
end
v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
v.add_instr("}")
else if pi == null then
do
+ # Generate INIT_ATTRIBUTES routine
var iself = new IRegister(get_type)
var iselfa = [iself]
- var iroutine = new IRoutine(new Array[IRegister], iself)
+ var iroutine = new IRoutine(iselfa, null)
var icb = new ICodeBuilder(module, iroutine)
- var obj = new INative("OBJ2VAL(obj)", null)
- obj.result = iself
- icb.stmt(obj)
for g in global_properties do
var p = self[g]
end
end
- var cname = "NEW_{name}"
- var args = iroutine.compile_signature_to_c(v, cname, "new {name}", null, null)
+ var cname = "INIT_ATTRIBUTES__{name}"
+ var args = iroutine.compile_signature_to_c(v, cname, "init attributes of {name}", null, null)
var ctx_old = v.ctx
v.ctx = new CContext
- v.add_decl("obj_t obj;")
+ iroutine.compile_to_c(v, cname, args)
+ ctx_old.append(v.ctx)
+ v.ctx = ctx_old
+ v.unindent
+ v.add_instr("}")
+ end
+ do
+ # Generate NEW routine
+ v.add_decl("val_t NEW_{name}(void);")
+ v.add_instr("val_t NEW_{name}(void)")
+ v.add_instr("\{")
+ v.indent
+ v.add_instr("obj_t obj;")
v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
v.add_instr("obj[1].object_id = object_id_counter;")
v.add_instr("object_id_counter = object_id_counter + 1;")
- var r = iroutine.compile_to_c(v, cname, args).as(not null)
- v.add_instr("return {r};")
- ctx_old.append(v.ctx)
- v.ctx = ctx_old
+ v.add_instr("return OBJ2VAL(obj);")
v.unindent
v.add_instr("}")
end
-
do
# Compile CHECKNAME
var iself = new IRegister(get_type)
iroutine.location = p.iroutine.location
var icb = new ICodeBuilder(module, iroutine)
- var inew = new INative("NEW_{name}()", null)
+ var inew = new IAllocateInstance(get_type)
inew.result = iself
icb.stmt(inew)
var iargs = [iself]
iargs.add_all(iparams)
- icb.stmt(new INative("{p.cname}(@@@{", @@@"*iparams.length}, init_table)", iargs))
- icb.stmt(new INative("CHECKNEW_{name}(@@@)", [iself]))
+
+ icb.stmt(new IInitAttributes(get_type, iself))
+ icb.stmt(new IStaticCall(p, iargs))
+ icb.stmt(new ICheckInstance(get_type, iself))
var cname = "NEW_{self}_{p.global.intro.cname}"
var new_args = iroutine.compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null)