import abstract_compiler
import layout_builders
import rapid_type_analysis
+import collect_super_sends
+import compiler_ffi
# Add separate compiler specific options
redef class ToolContext
end
redef class ModelBuilder
- fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
+ fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis)
do
var time0 = get_time
self.toolcontext.info("*** GENERATING C ***", 1)
redef type VISITOR: SeparateCompilerVisitor
# The result of the RTA (used to know live types and methods)
- var runtime_type_analysis: RapidTypeAnalysis
+ var runtime_type_analysis: nullable RapidTypeAnalysis
private var undead_types: Set[MType] = new HashSet[MType]
private var partial_types: Set[MType] = new HashSet[MType]
protected var method_layout: nullable Layout[PropertyLayoutElement]
protected var attr_layout: nullable Layout[MAttribute]
- init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do
+ init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
super(mainmodule, mmbuilder)
var file = new_file("nit.common")
self.header = new CodeWriter(file)
end
# lookup super calls and add it to the list of mmethods to build layout with
- var super_calls = runtime_type_analysis.live_super_sends
+ var super_calls
+ if runtime_type_analysis != null then
+ super_calls = runtime_type_analysis.live_super_sends
+ else
+ super_calls = modelbuilder.collect_super_sends
+ end
for mmethoddef in super_calls do
var mclass = mmethoddef.mclassdef.mclass
mmethods[mclass].add(mmethoddef)
var attrs = self.attr_tables[mclass]
var v = new_visitor
- var is_dead = not runtime_type_analysis.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray"
+ var is_dead = runtime_type_analysis != null and not runtime_type_analysis.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray"
v.add_decl("/* runtime class {c_name} */")
v.add("return {res};")
end
v.add("\}")
-
- generate_check_init_instance(mtype)
end
# Add a dynamic test to ensure that the type referenced by `t` is a live type
v.add("\}")
end
- redef fun generate_check_init_instance(mtype)
- do
- if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return
-
- var v = self.new_visitor
- var c_name = mtype.mclass.c_name
- var res = new RuntimeVariable("self", mtype, mtype)
- self.provide_declaration("CHECK_NEW_{c_name}", "void CHECK_NEW_{c_name}({mtype.ctype});")
- v.add_decl("/* allocate {mtype} */")
- v.add_decl("void CHECK_NEW_{c_name}({mtype.ctype} {res}) \{")
- if runtime_type_analysis.live_classes.has(mtype.mclass) then
- self.generate_check_attr(v, res, mtype)
- else
- v.add_abort("{mtype.mclass} is DEAD")
- end
- v.add("\}")
- end
-
redef fun new_visitor do return new SeparateCompilerVisitor(self)
# Stats
end
print "\t{total}\t{holes}"
end
+
+ redef fun compile_nitni_structs
+ do
+ self.header.add_decl("struct nitni_instance \{struct instance *value;\};")
+ end
+
+ redef fun finalize_ffi_for_module(nmodule)
+ do
+ var old_module = self.mainmodule
+ self.mainmodule = nmodule.mmodule.as(not null)
+ super
+ self.mainmodule = old_module
+ end
end
# A visitor on the AST of property definition that generate the C code of a separate compilation process.
else if mtype.ctype == "val*" then
var valtype = value.mtype.as(MClassType)
var res = self.new_var(mtype)
- if not compiler.runtime_type_analysis.live_types.has(valtype) then
+ if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
- self.add("printf(\"Dead code executed!\\n\"); exit(1);")
+ self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);")
return res
end
self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
return res
+ else if value.mtype.cname_blind == "void*" and mtype.cname_blind == "void*" then
+ return value
else
# Bad things will appen!
var res = self.new_var(mtype)
self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
- self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); exit(1);")
+ self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
return res
end
end
redef fun send(mmethod, arguments)
do
self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
- return table_send(mmethod, arguments, mmethod.const_color)
- end
- private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
- do
if arguments.first.mcasttype.ctype != "val*" then
# In order to shortcut the primitive, we need to find the most specific method
# Howverr, because of performance (no flattening), we always work on the realmainmodule
return res
end
+ return table_send(mmethod, arguments, mmethod.const_color)
+ end
+
+ private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
+ do
var res: nullable RuntimeVariable
var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true)
var ret = msignature.return_mtype
redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
do
+ if arguments.first.mcasttype.ctype != "val*" then
+ # In order to shortcut the primitive, we need to find the most specific method
+ # However, because of performance (no flattening), we always work on the realmainmodule
+ var main = self.compiler.mainmodule
+ self.compiler.mainmodule = self.compiler.realmainmodule
+ var res = self.monomorphic_super_send(m, recvtype, arguments)
+ self.compiler.mainmodule = main
+ return res
+ end
return table_send(m.mproperty, arguments, m.const_color)
end
return self.new_expr("NEW_{mtype.mclass.c_name}(&type_{mtype.c_name})", mtype)
end
- redef fun check_init_instance(value, mtype)
- do
- if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return
- self.require_declaration("CHECK_NEW_{mtype.mclass.c_name}")
- self.add("CHECK_NEW_{mtype.mclass.c_name}({value});")
- end
-
redef fun type_test(value, mtype, tag)
do
self.add("/* {value.inspect} isa {mtype} */")
self.add("count_type_test_resolved_{tag}++;")
end
else
- self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); exit(1);")
+ self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); show_backtrace(1);")
end
# check color is in table
self.add_decl("const char* {res};")
if value.mtype.ctype == "val*" then
self.add "{res} = {value} == NULL ? \"null\" : {value}->type->name;"
+ else if value.mtype isa MClassType and value.mtype.as(MClassType).mclass.kind == extern_kind then
+ self.add "{res} = \"{value.mtype.as(MClassType).mclass}\";"
else
self.require_declaration("type_{value.mtype.c_name}")
self.add "{res} = type_{value.mtype.c_name}.name;"
self.add("((struct instance_{nclass.c_name}*){nat})->values[{i}] = (val*) {r};")
end
self.send(self.get_property("with_native", arrayclass.intro.bound_mtype), [res, nat, length])
- self.check_init_instance(res, arraytype)
self.add("\}")
return res
end
v.add("return {frame.returnvar.as(not null)};")
end
v.add("\}")
+ if not self.c_name.has_substring("VIRTUAL", 0) then compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
end
end
v.add("return {frame.returnvar.as(not null)};")
end
v.add("\}")
+ if not self.c_name.has_substring("VIRTUAL", 0) then compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}--{mmethoddef.location.line_start})"
end
# TODO ?