import table_computation
private import compiling_icode
-class GlobalCompilerVisitor
-special CompilerVisitor
- # The global analysis result
- readable var _program: Program
- init(m: MMModule, tc: ToolContext, prog: Program)
- do
- super(m, tc)
- _program = prog
- end
-end
-
redef class Program
# Compile module and class tables
- fun compile_tables_to_c(v: GlobalCompilerVisitor)
+ fun compile_tables_to_c(v: CompilerVisitor)
do
- for m in module.mhe.greaters_and_self do
+ for m in main_module.mhe.greaters_and_self do
m.compile_local_table_to_c(v)
end
- for c in module.local_classes do
+ with_each_live_local_classes !action(c) do
+ if c.global.is_abstract or c.global.is_interface then continue
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 module.has_global_class_named(t.to_symbol) then
- s.append(", (const classtable_t)VFT_{t}")
+ if main_module.has_global_class_named(t.to_symbol) then
+ var c = main_module.class_by_name(t.to_symbol)
+ s.append(", (const classtable_t)VFT_{c.cname}")
else
s.append(", NULL")
end
end
# Compile main part (for _table.c)
- fun compile_main_part(v: GlobalCompilerVisitor)
+ fun compile_main_part(v: CompilerVisitor)
do
v.add_instr("int main(int argc, char **argv) \{")
v.indent
v.add_instr("prepare_signals();")
v.add_instr("glob_argc = argc; glob_argv = argv;")
- var sysname = once "Sys".to_symbol
- if not module.has_global_class_named(sysname) then
+ if v.program.main_method == null then
print("No main")
else
- 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
+ var c = v.program.main_class
+ v.add_instr("G_sys = NEW_{c.cname}();")
+ v.add_instr("register_static_object(&G_sys);")
+ v.add_instr("{v.program.main_method.cname}(G_sys);")
end
v.add_instr("return 0;")
v.unindent
end
redef class MMModule
- # Declare class table (for _sep.h)
- fun declare_class_tables_to_c(v: GlobalCompilerVisitor)
+ # Declare class table (for _sep.h or _glob.h)
+ fun declare_class_tables_to_c(v: CompilerVisitor)
do
for c in local_classes do
- if c.global.module == self then
+ if c.global.mmmodule == self then
c.declare_tables_to_c(v)
end
end
end
# Compile sep files
- fun compile_mod_to_c(v: GlobalCompilerVisitor)
+ fun compile_mod_to_c(v: CompilerVisitor)
do
- v.add_decl("extern const char *LOCATE_{name};")
- if not v.tc.global then
- v.add_decl("extern const int SFT_{name}[];")
+ v.add_decl("extern const char *LOCATE_{cname};")
+ if not v.program.tc.use_SFT_optimization then
+ v.add_decl("extern const int SFT_{cname}[];")
end
var i = 0
for e in local_table do
var value: String
- if v.tc.global then
+ if v.program.tc.use_SFT_optimization then
value = "{e.value(v.program)}"
else
- value = "SFT_{name}[{i}]"
+ value = "SFT_{cname}[{i}]"
i = i + 1
end
e.compile_macros(v, value)
end
# Compile module file for the current module
- fun compile_local_table_to_c(v: GlobalCompilerVisitor)
+ fun compile_local_table_to_c(v: CompilerVisitor)
do
- v.add_instr("const char *LOCATE_{name} = \"{location.file}\";")
+ v.add_instr("const char *LOCATE_{cname} = \"{location.file.filename}\";")
- if v.tc.global or local_table.is_empty then
+ if v.program.tc.use_SFT_optimization or local_table.is_empty then
return
end
- v.add_instr("const int SFT_{name}[{local_table.length}] = \{")
+ v.add_instr("const int SFT_{cname}[{local_table.length}] = \{")
v.indent
for e in local_table do
v.add_instr(e.value(v.program) + ",")
redef class AbsTableElt
# Compile the macro needed to use the element and other related elements
- fun compile_macros(v: GlobalCompilerVisitor, value: String) is abstract
+ fun compile_macros(v: CompilerVisitor, value: String) is abstract
end
redef class TableElt
# Return the value of the element for a given class
- fun compile_to_c(v: GlobalCompilerVisitor, c: MMLocalClass): String is abstract
+ fun compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract
end
redef class ModuleTableElt
end
end
+redef class TableEltClassSelfName
+ redef fun compile_to_c(v, c)
+ do
+ var prog = v.program
+ return "\"{c.global.name}\" /* {prog.table_information.color(self)}: Class Name */"
+ end
+end
+
redef class TableEltClassObjectSize
redef fun compile_to_c(v, c)
do
###############################################################################
redef class MMLocalClass
- # IRoutine for the initialization of the default attributes (called by IInitAttributes)
- var _init_var_iroutine: nullable IRoutine = null
- # IRoutine to validate the instance after initialization (called by ICheckInstance)
- var _checknew_iroutine: nullable IRoutine = null
- # IRoutines to call to create a new valid instance (memory allocated, object initialized and validated)
- # These iroutines will call: IAllocateInstance, IInitAttributes, some init function and ICheckInstance
- # These routines will be called by INew
- var _new_instance_iroutine: HashMap[MMMethod, IRoutine] = new HashMap[MMMethod, IRoutine]
-
# Declaration and macros related to the class table
- fun declare_tables_to_c(v: GlobalCompilerVisitor)
+ fun declare_tables_to_c(v: CompilerVisitor)
do
v.add_decl("")
var pi = primitive_info
- v.add_decl("extern const classtable_elt_t VFT_{name}[];")
- 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
+ v.add_decl("extern const classtable_elt_t VFT_{cname}[];")
+ if pi != null and not pi.tagged then
var t = pi.cname
var tbox = "struct TBOX_{name}"
v.add_decl("{tbox} \{ const classtable_elt_t * vft; bigint object_id; {t} val;};")
end
end
- # Generation of allocation function of this class
- fun generate_allocation_iroutines(prog: Program)
- do
- var cc = prog.compiled_classes[self.global]
-
- var pi = primitive_info
- 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
-
- _init_var_iroutine = iroutine
- 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
-
- _checknew_iroutine = iroutine
- end
-
- var init_table_size = cshe.greaters.length + 1
-
- for g in global_properties do
- var p = self[g]
- # 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 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))
-
- _new_instance_iroutine[p] = iroutine
- end
- end
- end
-
# Compilation of table and new (or box)
- fun compile_tables_to_c(v: GlobalCompilerVisitor)
+ fun compile_tables_to_c(v: CompilerVisitor)
do
var cc = v.program.compiled_classes[self.global]
var ctab = cc.class_table
clen = v.program.table_information.max_class_table_length
end
- v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
+ v.add_instr("const classtable_elt_t VFT_{cname}[{clen}] = \{")
v.indent
for e in ctab do
if e == null then
v.indent
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->vft = (classtable_elt_t*)VFT_{cname};")
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;")
else if pi == null then
do
# Generate INIT_ATTRIBUTES routine
- var cname = "INIT_ATTRIBUTES__{name}"
- var args = _init_var_iroutine.compile_signature_to_c(v, cname, "init var of {name}", null, null)
- var ctx_old = v.ctx
- v.ctx = new CContext
- _init_var_iroutine.compile_to_c(v, cname, args)
- ctx_old.append(v.ctx)
- v.ctx = ctx_old
+ var cname = "INIT_ATTRIBUTES__{cname}"
+ var args = init_var_iroutine.compile_signature_to_c(v, cname, "init var of {name}", null, null)
+ var decl_writer_old = v.decl_writer
+ v.decl_writer = v.writer.sub
+ init_var_iroutine.compile_to_c(v, cname, args)
+ v.decl_writer = decl_writer_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_decl("val_t NEW_{cname}(void);")
+ v.add_instr("val_t NEW_{cname}(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->vft = (classtable_elt_t*)VFT_{cname};")
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);")
end
do
# Compile CHECKNAME
- var cname = "CHECKNEW_{name}"
- var args = _checknew_iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null)
- var ctx_old = v.ctx
- v.ctx = new CContext
- _checknew_iroutine.compile_to_c(v, cname, args)
- ctx_old.append(v.ctx)
- v.ctx = ctx_old
+ var cname = "CHECKNEW_{cname}"
+ var args = checknew_iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null)
+ var decl_writer_old = v.decl_writer
+ v.decl_writer = v.writer.sub
+ checknew_iroutine.compile_to_c(v, cname, args)
+ v.decl_writer = decl_writer_old
v.unindent
v.add_instr("}")
end
assert p isa MMMethod
var cname = "NEW_{self}_{p.global.intro.cname}"
- var new_args = _new_instance_iroutine[p].compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null)
- var ctx_old = v.ctx
- v.ctx = new CContext
+ var new_args = new_instance_iroutine[p].compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null)
+ var decl_writer_old = v.decl_writer
+ v.decl_writer = v.writer.sub
v.add_instr(init_table_decl)
- var e = _new_instance_iroutine[p].compile_to_c(v, cname, new_args).as(not null)
+ var e = new_instance_iroutine[p].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.decl_writer = decl_writer_old
v.unindent
v.add_instr("}")
end
v.add_instr("val_t BOX_{name}({t} val) \{")
v.indent
v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
- v.add_instr("box->vft = VFT_{name};")
+ v.add_instr("box->vft = VFT_{cname};")
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;")
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 writer_old = v.writer
+ v.writer = v.writer.sub
+ var decl_writer_old = v.decl_writer
+ v.decl_writer = v.writer.sub
var itpos: nullable String = null
if global.is_init then
if s == null then
v.add_instr("return;")
else
- v.add_instr("return ", s, ";")
+ 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)
+ v.writer = writer_old
+ v.decl_writer = decl_writer_old
end
end