# Compute and generate tables for classes and modules.
package compiling_global
-#import compiling_base
-private import compiling_methods
-private import syntax
+import program
+private import compiling_icode
# Something that store color of table elements
class ColorContext
# FIXME: do something better.
readable writable var _max_class_table_length: Int = 0
- init(module: MMSrcModule)
+ init(module: MMModule)
do
_module = module
end
special CompilerVisitor
# The global analysis result
readable var _global_analysis: GlobalAnalysis
- init(m: MMSrcModule, tc: ToolContext, ga: GlobalAnalysis)
+ init(m: MMModule, tc: ToolContext, ga: GlobalAnalysis)
do
super(m, tc)
_global_analysis = ga
init(c: MMLocalClass) do _local_class = c
end
-redef class MMSrcLocalClass
+redef class MMConcreteClass
# The table element of the subtype check
fun class_color_pos: TableEltClassColor do return _class_color_pos.as(not null)
var _class_color_pos: nullable TableEltClassColor
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
+ if p isa MMAttribute then
ilt.add(new TableEltAttr(p))
- else if p isa MMSrcMethod then
+ else if p isa MMMethod then
clt.add(new TableEltMeth(p))
end
end
- if p isa MMSrcMethod and p.need_super then
+ if p isa MMMethod and p.need_super then
clt.add(new TableEltSuper(p))
end
end
end
end
-redef class MMSrcModule
- # 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 src_local_classes do
- c.build_layout_in(tc, _local_table)
- end
- end
-
+redef class Program
# Do the complete global analysis
fun global_analysis(cctx: ToolContext): GlobalAnalysis
do
- #print "Do the complete global analysis"
- var ga = new GlobalAnalysis(self)
+ var ga = new GlobalAnalysis(module)
var smallest_classes = new Array[MMLocalClass]
var global_properties = new HashSet[MMGlobalProperty]
var ctab = new Array[TableElt]
var itab = new Array[TableElt]
ctab.add(new TableEltClassSelfId)
+ ctab.add(new TableEltClassObjectSize)
itab.add(new TableEltVftPointer)
+ itab.add(new TableEltObjectId)
var pclassid = -1
var classid = 3
# 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
# 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
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
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_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
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
- end
- end
- end
-
# Perform coloring
fun colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
do
return true
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
+ end
+ end
+ end
+
# Compile module and class tables
fun compile_tables_to_c(v: GlobalCompilerVisitor)
do
- for m in mhe.greaters_and_self do
- assert m isa MMSrcModule
+ 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")
else
var mainm = sys.select_method(name)
v.add_instr("G_sys = NEW_Sys();")
+ v.add_instr("register_static_object(&G_sys);")
v.add_instr("{mainm.cname}(G_sys);")
end
end
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)
end
e.compile_macros(v, value)
end
- for c in src_local_classes do
+ 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 then
+ 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 i in [0..p.signature.arity[ do
- params.add("val_t p{i}")
+ 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
# Compile module file for the current module
fun compile_local_table_to_c(v: GlobalCompilerVisitor)
do
- v.add_instr("const char *LOCATE_{name} = \"{filename}\";")
+ v.add_instr("const char *LOCATE_{name} = \"{location.file}\";")
if v.tc.global or _local_table.is_empty then
return
end
end
+
+# The element that represent the Object Size
+class TableEltClassObjectSize
+special TableElt
+ redef fun is_related_to(c) do return true
+ redef fun compile_to_c(v, c)
+ do
+ var nb = 0
+ var ga = v.global_analysis
+ if c.name == "NativeArray".to_symbol then
+ nb = -1
+ else
+ var cc = ga.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)*/"
+ end
+end
+
+# The element that represent the object id
+class TableEltObjectId
+special TableElt
+ 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 */"
+ end
+end
+
# The element that
class TableEltVftPointer
special TableElt
v.add_decl("")
var pi = primitive_info
v.add_decl("extern const classtable_elt_t VFT_{name}[];")
- if pi == null then
+ if name == "NativeArray".to_symbol then
+ v.add_decl("val_t NEW_NativeArray(size_t length, size_t size);")
+ else if pi == null then
# v.add_decl("val_t NEW_{name}(void);")
else if not pi.tagged then
var t = pi.cname
var tbox = "struct TBOX_{name}"
- v.add_decl("{tbox} \{ const classtable_elt_t * vft; {t} val;};")
+ v.add_decl("{tbox} \{ const classtable_elt_t * vft; bigint object_id; {t} val;};")
v.add_decl("val_t BOX_{name}({t} val);")
v.add_decl("#define UNBOX_{name}(x) ((({tbox} *)(VAL2OBJ(x)))->val)")
end
end
var pi = primitive_info
- if pi == null then
- v.cfc = new CFunctionContext(v)
- v.nmc = new NitMethodContext(null)
- var s = "val_t NEW_{name}(void)"
- v.add_instr(s + " \{")
+ if name == "NativeArray".to_symbol then
+ v.add_instr("val_t NEW_NativeArray(size_t length, size_t size) \{")
v.indent
- var ctx_old = v.ctx
- v.ctx = new CContext
-
- var self_var = new ParamVariable(once ("self".to_symbol), null)
- var self_var_cname = v.cfc.register_variable(self_var)
- v.nmc.method_params = [self_var]
-
- 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_assignment(self_var_cname, "OBJ2VAL(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
- # FIXME: Not compatible with sep compilation
- assert p isa MMSrcAttribute
- var np = p.node
- var ne = np.n_expr
- if ne != null then
- var e = ne.compile_expr(v)
- v.add_instr("{p.global.attr_access}(obj) = {e};")
- end
- end
- end
- v.add_instr("return OBJ2VAL(obj);")
- v.cfc.generate_var_decls
- ctx_old.append(v.ctx)
- v.ctx = ctx_old
+ v.add_instr("Nit_NativeArray array;")
+ v.add_instr("array = (Nit_NativeArray)alloc(sizeof(struct Nit_NativeArray) + ((length - 1) * size));")
+ v.add_instr("array->vft = (classtable_elt_t*)VFT_{name};")
+ v.add_instr("array->object_id = object_id_counter;")
+ v.add_instr("object_id_counter = object_id_counter + 1;")
+ v.add_instr("array->size = length;")
+ v.add_instr("return OBJ2VAL(array);")
v.unindent
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(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 then
+ var ir = p.iroutine
+ if ir == null then continue
+ # FIXME: Not compatible with sep compilation
+ var e = icb.inline_routine(ir, iselfa, null).as(not null)
+ icb.stmt(new IAttrWrite(p, iself, e))
+ end
+ end
- # Compile CHECKNAME
- var s = "void CHECKNEW_{name}(val_t self, char *from)"
- v.add_instr(s + " \{")
- v.indent
- var ctx_old = v.ctx
- v.ctx = new CContext
- 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
- v.add_instr("if ({p.global.attr_access}(self) == NIT_NULL) \{ fprintf(stderr, \"Uninitialized attribute %s at %s.\\n\", \"{p.full_name}\", from); nit_exit(1); \}")
+ 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
+ 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;")
+ v.add_instr("return OBJ2VAL(obj);")
+ v.unindent
+ v.add_instr("}")
+ 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
- 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)}};"
var p = self[g]
# FIXME skip invisible constructors
if not p.global.is_init_for(self) then continue
- 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_{self}_{p.global.intro.cname}({params.join(", ")}) \{"
- v.add_instr(s)
- v.indent
+ 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 IAllocateInstance(get_type)
+ inew.result = iself
+ icb.stmt(inew)
+ var iargs = [iself]
+ iargs.add_all(iparams)
+
+ 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)
+ 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.cname}({args.join(", ")});")
- v.add_instr("CHECKNEW_{name}(self, \"{p.full_name} for {self}\");")
- 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
v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
v.add_instr("box->vft = VFT_{name};")
v.add_instr("box->val = val;")
+ v.add_instr("box->object_id = object_id_counter;")
+ v.add_instr("object_id_counter = object_id_counter + 1;")
v.add_instr("return OBJ2VAL(box);")
v.unindent
v.add_instr("}")
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
+