# Compute and generate tables for classes and modules.
package compiling_global
-#import compiling_base
-private import compiling_methods
-private import syntax
+private import compiling_icode
# Something that store color of table elements
class ColorContext
- attr _colors: HashMap[TableElt, Int]
+ var _colors: HashMap[TableElt, Int] = new HashMap[TableElt, Int]
# The color of a table element.
- meth color(e: TableElt): Int
+ fun color(e: TableElt): Int
do
return _colors[e]
end
# Is a table element already colored?
- meth has_color(e: TableElt): Bool
+ fun has_color(e: TableElt): Bool
do
- return _colors != null and _colors.has_key(e)
+ return _colors.has_key(e)
end
# Assign a color to a table element.
- meth color=(e: TableElt, c: Int)
+ fun color=(e: TableElt, c: Int)
do
- if _colors == null then _colors = new HashMap[TableElt, Int]
_colors[e] = c
var idx = c
for i in [0..e.length[ do
class GlobalAnalysis
special ColorContext
# Associate global classes to compiled classes
- readable attr _compiled_classes: HashMap[MMGlobalClass, CompiledClass]
+ readable var _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new HashMap[MMGlobalClass, CompiledClass]
# The main module of the program globally analysed
- readable attr _module: MMModule
+ readable var _module: MMModule
# FIXME: do something better.
- readable writable attr _max_class_table_length: Int
+ readable writable var _max_class_table_length: Int = 0
- init(module: MMSrcModule)
+ init(module: MMModule)
do
- _compiled_classes = new HashMap[MMGlobalClass, CompiledClass]
_module = module
end
end
-redef class CompilerVisitor
- # The global analysis result, if any
- readable writable attr _global_analysis: GlobalAnalysis
+class GlobalCompilerVisitor
+special CompilerVisitor
+ # The global analysis result
+ readable var _global_analysis: GlobalAnalysis
+ init(m: MMModule, tc: ToolContext, ga: GlobalAnalysis)
+ do
+ super(m, tc)
+ _global_analysis = ga
+ end
end
# A compiled class is a class in a program
class CompiledClass
special ColorContext
# The corresponding local class in the main module of the prgram
- readable attr _local_class: MMLocalClass
+ readable var _local_class: MMLocalClass
# The identifier of the class
- readable writable attr _id: Int
+ readable writable var _id: Int = 0
# The full class table of the class
- readable writable attr _class_table: Array[TableElt]
+ readable var _class_table: Array[nullable TableElt] = new Array[nullable TableElt]
# The full instance table of the class
- readable writable attr _instance_table: Array[TableElt]
+ readable var _instance_table: Array[nullable TableElt] = new Array[nullable TableElt]
# The proper class table part (no superclasses but all refinements)
- readable writable attr _class_layout: TableEltComposite
+ readable writable var _class_layout: TableEltComposite = new TableEltComposite(self)
# The proper instance table part (no superclasses but all refinements)
- readable writable attr _instance_layout: TableEltComposite
+ readable writable var _instance_layout: TableEltComposite = new TableEltComposite(self)
init(c: MMLocalClass) do _local_class = c
end
-redef class MMGlobalProperty
- # The position of the property in the local class table part
- # FIXME: It's ugly. store this somewhere else please
- readable writable attr _pos_of: Int
-end
-
-redef class MMSrcLocalClass
- # The table element of the attribute position (for accessor simulation)
- readable attr _base_attr_pos: TableEltBaseAttrPos
-
+redef class MMConcreteClass
# The table element of the subtype check
- readable attr _class_color_pos: TableEltClassColorPos
+ fun class_color_pos: TableEltClassColor do return _class_color_pos.as(not null)
+ var _class_color_pos: nullable TableEltClassColor
# The proper local class table part (nor superclasses nor refinments)
- readable attr _class_layout: Array[LocalTableElt]
+ readable var _class_layout: Array[TableElt] = new Array[TableElt]
# The proper local instance table part (nor superclasses nor refinments)
- readable attr _instance_layout: Array[LocalTableElt]
+ readable var _instance_layout: Array[TableElt] = new Array[TableElt]
# Build the local layout of the class and feed the module table
- meth build_layout_in(tc: ToolContext, module_table: Array[LocalTableElt])
+ fun build_layout_in(tc: ToolContext, module_table: Array[ModuleTableElt])
do
- var intro_methods = new Array[MMGlobalProperty] # FIXME: Remove this
- var intro_attributes = new Array[MMGlobalProperty] # FIXME: Remove this
- var clt = new Array[LocalTableElt]
- _class_layout = clt
- var ilt = new Array[LocalTableElt]
- _instance_layout = ilt
+ var clt = _class_layout
+ var ilt = _instance_layout
if global.intro == self then
- module_table.add(new TableEltClassIdPos(self))
- _class_color_pos = new TableEltClassColorPos(self)
- module_table.add(_class_color_pos)
- #clt.add(_class_color_pos)
- clt.add(new TableEltClassInitTablePos(self))
+ module_table.add(new TableEltClassId(self))
+ var cpp = new TableEltClassColor(self)
+ _class_color_pos = cpp
+ module_table.add(cpp)
+ clt.add(new TableEltClassInitTable(self))
end
- for p in src_local_properties do
+ for p in local_local_properties do
var pg = p.global
if pg.intro == p then
- if p isa MMSrcAttribute then
- pg.pos_of = intro_attributes.length
- intro_attributes.add(pg)
- ilt.add(new TableEltAttrPos(p))
- else if p isa MMSrcMethod then
- pg.pos_of = intro_methods.length
- intro_methods.add(pg)
- clt.add(new TableEltMethPos(p))
+ if p isa MMAttribute then
+ ilt.add(new TableEltAttr(p))
+ else if p isa MMMethod then
+ clt.add(new TableEltMeth(p))
end
end
- if p isa MMSrcMethod and p.need_super then
- clt.add(new TableEltSuperPos(p))
+ if p isa MMMethod and p.need_super then
+ clt.add(new TableEltSuper(p))
end
end
- if tc.attr_sim and not intro_attributes.is_empty then
- _base_attr_pos = new TableEltBaseAttrPos(self)
- clt.add(_base_attr_pos)
- else
- module_table.append(ilt)
+
+ if not ilt.is_empty then
+ var teg = new ModuleTableEltGroup
+ teg.elements.append(ilt)
+ module_table.add(teg)
+ end
+
+ if not clt.is_empty then
+ var teg = new ModuleTableEltGroup
+ teg.elements.append(clt)
+ module_table.add(teg)
end
- module_table.append(clt)
end
end
-redef class MMSrcModule
+redef class MMModule
# The local table of the module (refers things introduced in the module)
- attr _local_table: Array[LocalTableElt]
+ var _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt]
# Builds the local tables and local classes layouts
- meth local_analysis(tc: ToolContext)
+ fun local_analysis(tc: ToolContext)
do
- var lt = new Array[LocalTableElt]
- _local_table = lt
- for c in src_local_classes do
- c.build_layout_in(tc, lt)
+ for c in local_classes do
+ if c isa MMConcreteClass then
+ c.build_layout_in(tc, _local_table)
+ end
end
end
# Do the complete global analysis
- meth global_analysis(cctx: ToolContext): GlobalAnalysis
+ fun global_analysis(cctx: ToolContext): GlobalAnalysis
do
#print "Do the complete global analysis"
var ga = new GlobalAnalysis(self)
ctab.add(new TableEltClassSelfId)
itab.add(new TableEltVftPointer)
-
+
var pclassid = -1
var classid = 3
# Store the colortableelt in the class table pool
var bc = c.global.intro
- assert bc isa MMSrcLocalClass
+ assert bc isa MMConcreteClass
ctab.add(bc.class_color_pos)
end
# Compute core and crown classes for colorization
var crown_classes = new HashSet[MMLocalClass]
- var core_classes = new HashSet[MMLocalClass]
+ var core_classes = new HashSet[MMLocalClass]
for c in smallest_classes do
while c.cshe.direct_greaters.length == 1 do
c = c.cshe.direct_greaters.first
var cc = ga.compiled_classes[c.global]
if core_classes.has(c) then
# For core classes, just build the table
- cc.class_table = build_tables(ga, c, ctab)
+ build_tables_in(cc.class_table, ga, 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]
- cc.class_table = scc.class_table.to_a
+ assert cc.class_table.is_empty
+ cc.class_table.add_all(scc.class_table)
var bc = c.global.intro
- assert bc isa MMSrcLocalClass
+ assert bc isa MMConcreteClass
var colpos = bc.class_color_pos
var colposcolor = cc.class_table.length
ga.color(colpos) = colposcolor
# Fill class table and instance tables pools
for c in classes do
var cc = ga.compiled_classes[c.global]
- var cte = new TableEltComposite(cc)
- var ite = new TableEltComposite(cc)
+ var cte = cc.class_layout
+ var ite = cc.instance_layout
for sc in c.crhe.greaters_and_self do
- if sc isa MMSrcLocalClass then
+ if sc isa MMConcreteClass then
cte.add(sc, sc.class_layout)
ite.add(sc, sc.instance_layout)
end
- cc.class_layout = cte
- cc.instance_layout = ite
end
if core_classes.has(c) then
if cte.length > 0 then
ctab.add(cte)
end
- if not cctx.attr_sim and ite.length > 0 then
+ if ite.length > 0 then
itab.add(ite)
end
end
colorize(ga, itab, crown_classes, 0)
# Build class and instance tables now things are colored
- ga.max_class_table_length = 0
+ ga.max_class_table_length = 0
for c in classes do
var cc = ga.compiled_classes[c.global]
if core_classes.has(c) then
# For core classes, just build the table
- cc.class_table = build_tables(ga, c, ctab)
- cc.instance_table = build_tables(ga, c, itab)
+ build_tables_in(cc.class_table, ga, c, ctab)
+ build_tables_in(cc.instance_table, ga, 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]
- cc.class_table = scc.class_table.to_a
+ cc.class_table.clear
+ cc.class_table.add_all(scc.class_table)
var bc = c.global.intro
- assert bc isa MMSrcLocalClass
+ assert bc isa MMConcreteClass
var colpos = bc.class_color_pos
cc.class_table[ga.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)
- cc.instance_table = scc.instance_table.to_a
+ 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
-
- if cctx.attr_sim then
- cc.instance_table = build_tables(ga, c, itab)
- for sc in c.cshe.greaters_and_self do
- var scc = ga.compiled_classes[sc.global]
- append_to_table(cc, cc.instance_table, scc.instance_layout)
- end
- end
end
return ga
end
- private meth append_to_table(cc: ColorContext, table: Array[TableElt], cmp: TableEltComposite)
+ 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)
end
end
- private meth build_tables(ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt]): Array[TableElt]
+ 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
end
end
end
- var res = new Array[TableElt]
var i = 0
while i < len do
if tab.has_key(i) then
var e = tab[i]
for j in [0..e.length[ do
- res[i] = e.item(j)
+ table[i] = e.item(j)
i = i + 1
end
else
- res[i] = null
+ table[i] = null
i = i + 1
end
end
- return res
end
# Perform coloring
- meth colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
+ fun colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
do
var colors = new HashMap[Int, Array[TableElt]]
var rel_classes = new Array[MMLocalClass]
while trycolor != color do
color = trycolor
for c in rel_classes do
- var idx = 0
+ var idx = 0
while idx < len do
if colors.has_key(trycolor + idx) and not free_color(colors[trycolor + idx], c) then
trycolor = trycolor + idx + 1
end
end
- private meth free_color(es: Array[TableElt], c: MMLocalClass): Bool
+ private fun free_color(es: Array[TableElt], c: MMLocalClass): Bool
do
for e2 in es do
if e2.is_related_to(c) then
end
# Compile module and class tables
- meth compile_tables_to_c(v: CompilerVisitor)
+ fun compile_tables_to_c(v: GlobalCompilerVisitor)
do
for m in mhe.greaters_and_self do
- assert m isa MMSrcModule
m.compile_local_table_to_c(v)
end
for c in local_classes do
c.compile_tables_to_c(v)
end
- var s = "classtable_t TAG2VFT[4] = \{NULL"
+ 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
s.append(", (const classtable_t)VFT_{t}")
end
end
s.append("};")
- v.add_instr(s)
+ v.add_instr(s.to_s)
end
# Declare class table (for _sep.h)
- meth declare_class_tables_to_c(v: CompilerVisitor)
+ fun declare_class_tables_to_c(v: GlobalCompilerVisitor)
do
for c in local_classes do
if c.global.module == self then
end
# Compile main part (for _table.c)
- meth compile_main_part(v: CompilerVisitor)
+ fun compile_main_part(v: GlobalCompilerVisitor)
do
v.add_instr("int main(int argc, char **argv) \{")
v.indent
if not has_global_class_named(sysname) then
print("No main")
else
- var sys = class_by_name(sysname).get_type
- var main = sys.select_method(once "init".to_symbol)
- if main == null then
- main = sys.select_method(once "main".to_symbol)
- end
- if main == null then
+ var sys = class_by_name(sysname)
+ var name = once "main".to_symbol
+ if not sys.has_global_property_by_name(name) then
print("No main")
else
+ var mainm = sys.select_method(name)
v.add_instr("G_sys = NEW_Sys();")
- v.add_instr("{main.cname}(G_sys);")
+ v.add_instr("{mainm.cname}(G_sys);")
end
end
v.add_instr("return 0;")
v.unindent
v.add_instr("}")
end
-
- # Compile sep files
- meth compile_mod_to_c(v: CompilerVisitor)
+
+ # Compile sep files
+ fun compile_mod_to_c(v: GlobalCompilerVisitor)
do
+ v.add_decl("extern const char *LOCATE_{name};")
if not v.tc.global then
v.add_decl("extern const int SFT_{name}[];")
end
var i = 0
for e in _local_table do
+ var value: String
if v.tc.global then
- v.add_decl("#define {e.symbol} {e.value(v.global_analysis)}")
+ value = "{e.value(v.global_analysis)}"
else
- v.add_decl("#define {e.symbol} SFT_{name}[{i}]")
+ value = "SFT_{name}[{i}]"
i = i + 1
end
+ e.compile_macros(v, value)
end
- for c in src_local_classes do
- for p in c.src_local_properties do
- var pg = p.global
- if pg.intro == p and p isa MMAttribute then
- if v.tc.attr_sim then
- var bc = pg.local_class
- assert bc isa MMSrcLocalClass
- var s = bc.base_attr_pos.symbol
- v.add_decl("#define {pg.attr_access}(recv) ATTRS(recv, {s}, {pg.pos_of})")
- else
- v.add_decl("#define {pg.attr_access}(recv) ATTR(recv, {pg.color_id})")
+ for c in local_classes do
+ if not c isa MMConcreteClass then continue
+ for pg in c.global_properties do
+ var p = c[pg]
+ if p.local_class == c and p isa MMMethod then
+ p.compile_property_to_c(v)
+ end
+ if pg.is_init_for(c) then
+ # Declare constructors
+ var params = new Array[String]
+ for j in [0..p.signature.arity[ do
+ params.add("val_t p{j}")
end
+ v.add_decl("val_t NEW_{c}_{p.global.intro.cname}({params.join(", ")});")
end
- assert p isa MMSrcLocalProperty
- p.compile_property_to_c(v)
end
end
end
# Compile module file for the current module
- meth compile_local_table_to_c(v: CompilerVisitor)
+ fun compile_local_table_to_c(v: GlobalCompilerVisitor)
do
+ v.add_instr("const char *LOCATE_{name} = \"{location.file}\";")
+
if v.tc.global or _local_table.is_empty then
return
end
end
end
-class TableElt
- meth is_related_to(c: MMLocalClass): Bool is abstract
- meth length: Int do return 1
- meth item(i: Int): TableElt do return self
- meth compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract
+###############################################################################
+
+# An element of a class, an instance or a module table
+abstract class AbsTableElt
+ # Compile the macro needed to use the element and other related elements
+ fun compile_macros(v: GlobalCompilerVisitor, value: String) is abstract
end
-class LocalTableElt
-special TableElt
- meth symbol: String is abstract
- meth value(ga: GlobalAnalysis): String is abstract
+# An element of a class or an instance table
+# Such an elements represent method function pointers, attribute values, etc.
+abstract class TableElt
+special AbsTableElt
+ # Is the element conflict to class `c' (used for coloring)
+ fun is_related_to(c: MMLocalClass): Bool is abstract
+
+ # Number of sub-elements. 1 if none
+ fun length: Int do return 1
+
+ # Access the ith subelement.
+ fun item(i: Int): TableElt do return self
+
+ # Return the value of the element for a given class
+ fun compile_to_c(v: GlobalCompilerVisitor, c: MMLocalClass): String is abstract
+end
+
+# An element of a module table
+# Such an elements represent colors or identifiers
+abstract class ModuleTableElt
+special AbsTableElt
+ # Return the value of the element once the global analisys is performed
+ fun value(ga: GlobalAnalysis): String is abstract
end
-class TableEltPropPos
-special LocalTableElt
- attr _property: MMSrcLocalProperty
- redef meth symbol do return _property.global.color_id
- redef meth value(ga) do return "{ga.color(self)} /* Property {_property} */"
+# An element of a module table that represents a group of TableElt defined in the same local class
+class ModuleTableEltGroup
+special ModuleTableElt
+ readable var _elements: Array[TableElt] = new Array[TableElt]
- init(p: MMSrcLocalProperty)
+ redef fun value(ga) do return "{ga.color(_elements.first)} /* Group of ? */"
+ redef fun compile_macros(v, value)
+ do
+ var i = 0
+ for e in _elements do
+ e.compile_macros(v, "{value} + {i}")
+ i += 1
+ end
+ end
+end
+
+# An element that represents a class property
+abstract class TableEltProp
+special TableElt
+ var _property: MMLocalProperty
+
+ init(p: MMLocalProperty)
do
_property = p
end
end
-class TableEltMethPos
-special TableEltPropPos
- redef meth compile_to_c(v, c)
+# An element that represents a function pointer to a global method
+class TableEltMeth
+special TableEltProp
+ redef fun compile_macros(v, value)
+ do
+ var pg = _property.global
+ v.add_decl("#define {pg.meth_call}(recv) (({pg.intro.cname}_t)CALL((recv), ({value})))")
+ end
+
+ redef fun compile_to_c(v, c)
do
var p = c[_property.global]
return p.cname
end
- init(p) do super
end
-class TableEltSuperPos
-special TableEltPropPos
- redef meth symbol do return _property.color_id_for_super
- redef meth compile_to_c(v, c)
+# An element that represents a function pointer to the super method of a local method
+class TableEltSuper
+special TableEltProp
+ redef fun compile_macros(v, value)
+ do
+ var p = _property
+ v.add_decl("#define {p.super_meth_call}(recv) (({p.cname}_t)CALL((recv), ({value})))")
+ end
+
+ redef fun compile_to_c(v, c)
do
var pc = _property.local_class
var g = _property.global
if s == pc then
found = true
else if found and c.che < s then
- var p = s[g]
- if p != null and p isa MMConcreteProperty then
+ if s.has_global_property(g) then
#print "found {s.module}::{s}::{p}"
- return p.cname
+ return s[g].cname
end
end
end
- assert false
- return null
+ abort
end
-
- init(p) do super
end
-class TableEltAttrPos
-special TableEltPropPos
- redef meth compile_to_c(v, c)
+# An element that represents the value stored for a global attribute
+class TableEltAttr
+special TableEltProp
+ redef fun compile_macros(v, value)
+ do
+ var pg = _property.global
+ v.add_decl("#define {pg.attr_access}(recv) ATTR(recv, ({value}))")
+ end
+
+ redef fun compile_to_c(v, c)
do
var ga = v.global_analysis
var p = c[_property.global]
return "/* {ga.color(self)}: Attribute {c}::{p} */"
end
-
- init(p) do super
end
-class TableEltClassPos
-special LocalTableElt
- attr _local_class: MMLocalClass
- redef meth is_related_to(c)
- do
- var bc = c.module[_local_class.global]
- return c.cshe <= bc
- end
+# An element representing a class information
+class AbsTableEltClass
+special AbsTableElt
+ # The local class where the information comes from
+ var _local_class: MMLocalClass
init(c: MMLocalClass)
do
_local_class = c
end
-end
-class TableEltClassIdPos
-special TableEltClassPos
- redef meth symbol do return _local_class.global.id_id
- redef meth value(ga)
+ # The C macro name refering the value
+ fun symbol: String is abstract
+
+ redef fun compile_macros(v, value)
do
- return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
+ v.add_decl("#define {symbol} ({value})")
end
+end
- init(c) do super
+# An element of a class table representing a class information
+class TableEltClass
+special TableElt
+special AbsTableEltClass
+ redef fun is_related_to(c)
+ do
+ var bc = c.module[_local_class.global]
+ return c.cshe <= bc
+ end
end
-class TableEltClassInitTablePos
-special TableEltClassPos
- redef meth symbol do return _local_class.global.init_table_pos_id
- redef meth value(ga)
+# An element representing the id of a class in a module table
+class TableEltClassId
+special ModuleTableElt
+special AbsTableEltClass
+ redef fun symbol do return _local_class.global.id_id
+
+ redef fun value(ga)
do
- return "{ga.color(self)} /* Color of {_local_class} */"
+ return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
end
- redef meth compile_to_c(v, c)
+end
+
+# An element representing the constructor marker position in a class table
+class TableEltClassInitTable
+special TableEltClass
+ redef fun symbol do return _local_class.global.init_table_pos_id
+
+ redef fun compile_to_c(v, c)
do
var ga = v.global_analysis
var cc = ga.compiled_classes[_local_class.global]
end
return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */"
end
-
- init(c) do super
end
-class TableEltClassColorPos
-special TableEltClassPos
- redef meth symbol do return _local_class.global.color_id
- redef meth value(ga)
+# An element used for a cast
+# Note: this element is both a TableElt and a ModuleTableElt.
+# At the TableElt offset, there is the id of the super-class
+# At the ModuleTableElt offset, there is the TableElt offset (ie. the color of the super-class).
+class TableEltClassColor
+special TableEltClass
+special ModuleTableElt
+ redef fun symbol do return _local_class.global.color_id
+
+ redef fun value(ga)
do
return "{ga.color(self)} /* Color of {_local_class} */"
end
- redef meth compile_to_c(v, c)
+
+ 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 */"
end
-
- init(c) do super
-end
-
-class TableEltBaseAttrPos
-special LocalTableElt
- attr _local_class: MMSrcLocalClass
- redef meth symbol do return "COLOR_{_local_class.module}_{_local_class.name}_BASEATTR"
- redef meth value(ga)
- do
- return "{ga.color(self)} /* BaseAttrPos of {_local_class} */"
- end
-
- redef meth compile_to_c(v, c)
- do
- var ga = v.global_analysis
- var cc = ga.compiled_classes[c.global]
- return "{cc.color(_local_class.instance_layout.first)} /* {ga.color(self)}: Base attribut offset of {_local_class.module}::{_local_class} in {c} */"
- end
-
- init(c: MMSrcLocalClass)
- do
- _local_class = c
- end
end
+# A Group of elements introduced in the same global-class that are colored together
class TableEltComposite
special TableElt
- attr _table: Array[LocalTableElt]
- attr _cc: CompiledClass
- attr _offsets: HashMap[MMLocalClass, Int]
- redef meth length do return _table.length
- redef meth is_related_to(c) do return c.cshe <= _cc.local_class
+ var _table: Array[TableElt]
+ var _cc: CompiledClass
+ var _offsets: HashMap[MMLocalClass, Int]
+ redef fun length do return _table.length
+ redef fun is_related_to(c) do return c.cshe <= _cc.local_class
- meth add(c: MMLocalClass, tab: Array[LocalTableElt])
+ fun add(c: MMLocalClass, tab: Array[TableElt])
do
_offsets[c] = _table.length
_table.append(tab)
end
- redef meth item(i) do return _table[i]
+ redef fun item(i) do return _table[i]
- redef meth compile_to_c(v, c) do abort
+ redef fun compile_to_c(v, c) do abort
init(cc: CompiledClass)
do
_cc = cc
- _table = new Array[LocalTableElt]
+ _table = new Array[TableElt]
_offsets = new HashMap[MMLocalClass, Int]
end
end
+# The element that represent the class id
class TableEltClassSelfId
special TableElt
- redef meth is_related_to(c) do return true
- redef meth compile_to_c(v, c)
+ 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 */"
end
-
- init do end
end
+# The element that
class TableEltVftPointer
special TableElt
- redef meth is_related_to(c) do return true
- redef meth compile_to_c(v, c)
+ 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 */"
end
-
- init do end
end
+###############################################################################
+
# Used to sort local class in a deterministic total order
# The total order superset the class refinement and the class specialisation relations
class ClassSorter
special AbstractSorter[MMLocalClass]
- redef meth compare(a, b) do return a.compare(b)
+ redef fun compare(a, b) do return a.compare(b)
init do end
end
redef class MMLocalClass
# Comparaison in a total order that superset the class refinement and the class specialisation relations
- meth compare(b: MMLocalClass): Int
+ fun compare(b: MMLocalClass): Int
do
var a = self
if a == b then
end
# Declaration and macros related to the class table
- meth declare_tables_to_c(v: CompilerVisitor)
+ fun declare_tables_to_c(v: GlobalCompilerVisitor)
do
v.add_decl("")
var pi = primitive_info
end
# Compilation of table and new (or box)
- meth compile_tables_to_c(v: CompilerVisitor)
+ fun compile_tables_to_c(v: GlobalCompilerVisitor)
do
var cc = v.global_analysis.compiled_classes[self.global]
- var ctab = cc.class_table
+ 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 e == null then
v.add_instr("\{0} /* Class Hole :( */,")
else
- v.add_instr("\{(int) {e.compile_to_c(v, self)}},")
+ v.add_instr("\{(bigint) {e.compile_to_c(v, self)}},")
end
end
if clen > ctab.length then
var pi = primitive_info
if pi == null then
- v.clear
- var s = "val_t NEW_{name}(void)"
- v.add_instr(s + " \{")
- v.indent
- var ctx_old = v.ctx
- v.ctx = new CContext
+ do
+ var iself = new IRegister(get_type)
+ var iselfa = [iself]
+ var iroutine = new IRoutine(new Array[IRegister], iself)
+ 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]
+ var t = p.signature.return_type
+ if p isa MMAttribute and t != null then
+ var ir = p.iroutine
+ if ir == null then continue
+ # FIXME: Not compatible with sep compilation
+ var e = ir.inline_in_seq(icb.seq, iselfa).as(not null)
+ icb.stmt(new IAttrWrite(p, iself, e))
+ end
+ end
- v.method_params = ["OBJ2VAL(obj)"]
+ var cname = "NEW_{name}"
+ var args = iroutine.compile_signature_to_c(v, cname, "new {name}", null, null)
+ var ctx_old = v.ctx
+ v.ctx = new CContext
+ v.add_decl("obj_t obj;")
+ v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
+ v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
+ 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.unindent
+ v.add_instr("}")
+ end
- 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};")
- for g in global_properties do
- var p = self[g]
- var t = p.signature.return_type
- if p isa MMAttribute and t != null then
- # FIXME: Not compatible with sep compilation
- var pi = p.concrete_property
- assert pi isa MMSrcAttribute
- var np = pi.node
- assert np isa AAttrPropdef
- var ne = np.n_expr
- if ne != null then
- var e = ne.compile_expr(v)
- v.add_instr("{p.global.attr_access}(obj) = {e};")
- else
- var pi = t.local_class.primitive_info
- if pi != null and pi.tagged then
- var default = t.default_cvalue
- v.add_instr("{p.global.attr_access}(obj) = {default};")
- end
+ do
+ # Compile CHECKNAME
+ var iself = new IRegister(get_type)
+ var iselfa = [iself]
+ var iroutine = new IRoutine(iselfa, null)
+ var icb = new ICodeBuilder(module, iroutine)
+ for g in global_properties do
+ var p = self[g]
+ var t = p.signature.return_type
+ if p isa MMAttribute and t != null and not t.is_nullable then
+ icb.add_attr_check(p, iself)
end
end
+ var cname = "CHECKNEW_{name}"
+ var args = iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null)
+ var ctx_old = v.ctx
+ v.ctx = new CContext
+ iroutine.compile_to_c(v, cname, args)
+ ctx_old.append(v.ctx)
+ v.ctx = ctx_old
+ v.unindent
+ v.add_instr("}")
end
- v.add_instr("return OBJ2VAL(obj);")
- ctx_old.append(v.ctx)
- v.ctx = ctx_old
- v.unindent
- v.add_instr("}")
var init_table_size = cshe.greaters.length + 1
var init_table_decl = "int init_table[{init_table_size}] = \{0{", 0" * (init_table_size-1)}};"
for g in global_properties do
var p = self[g]
- if not p.global.is_init or p.global.intro.local_class.global != global then continue
- v.clear
- var params = new Array[String]
- var args = ["self"]
- for i in [0..p.signature.arity[ do
- params.add("val_t p{i}")
- args.add("p{i}")
- end
- args.add("init_table")
- var s = "val_t NEW_{p.global.intro.cname}({params.join(", ")})"
- v.add_instr(s + " \{")
- v.indent
+ # FIXME skip invisible constructors
+ if not p.global.is_init_for(self) then continue
+ assert p isa MMMethod
+
+ var iself = new IRegister(get_type)
+ var iparams = new Array[IRegister]
+ for i in [0..p.signature.arity[ do iparams.add(new IRegister(p.signature[i]))
+ var iroutine = new IRoutine(iparams, iself)
+ iroutine.location = p.iroutine.location
+ var icb = new ICodeBuilder(module, iroutine)
+
+ var inew = new INative("NEW_{name}()", null)
+ 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]))
+
+ 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)
+ var ctx_old = v.ctx
+ v.ctx = new CContext
v.add_instr(init_table_decl)
- v.add_instr("val_t self = NEW_{name}();")
- v.add_instr("{p.concrete_property.cname}({args.join(", ")});")
- v.add_instr("return self;")
+ var e = iroutine.compile_to_c(v, cname, new_args).as(not null)
+ v.add_instr("return {e};")
+ ctx_old.append(v.ctx)
+ v.ctx = ctx_old
v.unindent
v.add_instr("}")
end
end
end
+redef class MMMethod
+ fun compile_property_to_c(v: CompilerVisitor)
+ do
+ var ir = iroutine
+ assert ir != null
+
+ var more_params: nullable String = null
+ if global.is_init then more_params = "int* init_table"
+ var args = ir.compile_signature_to_c(v, cname, full_name, null, more_params)
+ var ctx_old = v.ctx
+ v.ctx = new CContext
+
+ v.out_contexts.clear
+
+ var itpos: nullable String = null
+ if global.is_init then
+ itpos = "itpos{v.new_number}"
+ v.add_decl("int {itpos} = VAL2OBJ({args.first})->vft[{local_class.global.init_table_pos_id}].i;")
+ v.add_instr("if (init_table[{itpos}]) return;")
+ end
+
+ var s = ir.compile_to_c(v, cname, args)
+
+ if itpos != null then
+ v.add_instr("init_table[{itpos}] = 1;")
+ end
+ if s == null then
+ v.add_instr("return;")
+ else
+ v.add_instr("return ", s, ";")
+ end
+
+ ctx_old.append(v.ctx)
+ v.ctx = ctx_old
+ v.unindent
+ v.add_instr("}")
+
+ for ctx in v.out_contexts do v.ctx.merge(ctx)
+ end
+end
+