nitc :: GlobalCompiler :: _classids
Cache for classidnitc :: GlobalCompiler :: _live_primitive_types
Subset of runtime_type_analysis.live_types that contains only primitive typesnitc :: GlobalCompiler :: _runtime_type_analysis
The result of the RTA (used to know live types and methods)nitc :: GlobalCompiler :: _seen
runtime_functions already seen (todo or done)nitc :: GlobalCompiler :: _todos
runtime_functions that need to be compilednitc :: GlobalCompiler :: classid
Return the C symbol associated to a live type runtimenitc :: GlobalCompiler :: classids
Cache for classidnitc :: GlobalCompiler :: classids=
Cache for classidnitc :: GlobalCompiler :: compile_class_names
Compile class names (for the class_name and output_class_name methods)nitc :: GlobalCompiler :: declare_runtimeclass
Declare C structures and identifiers for a runtime classnitc :: GlobalCompiler :: defaultinit
nitc :: GlobalCompiler :: generate_init_instance
Generate the init-instance of a live type (allocate + init-instance)nitc :: GlobalCompiler :: live_primitive_types
Subset of runtime_type_analysis.live_types that contains only primitive typesnitc :: GlobalCompiler :: live_primitive_types=
Subset of runtime_type_analysis.live_types that contains only primitive typesnitc :: GlobalCompiler :: runtime_type_analysis
The result of the RTA (used to know live types and methods)nitc :: GlobalCompiler :: runtime_type_analysis=
The result of the RTA (used to know live types and methods)nitc :: GlobalCompiler :: seen
runtime_functions already seen (todo or done)nitc :: GlobalCompiler :: seen=
runtime_functions already seen (todo or done)nitc :: GlobalCompiler :: todos
runtime_functions that need to be compilednitc :: GlobalCompiler :: todos=
runtime_functions that need to be compilednitc $ GlobalCompiler :: SELF
Type of this instance, automatically specialized in every classnitc $ GlobalCompiler :: VISITOR
nitc $ GlobalCompiler :: compile_header_structs
Declaration of structures the live Nit typesnitc $ GlobalCompiler :: compile_nitni_structs
Declaration of structures for nitni undelying the FFInitc $ GlobalCompiler :: do_compilation
Do the full code generation of the programmainmodule
nitc $ GlobalCompiler :: init
nitc $ GlobalCompiler :: new_visitor
Initialize a visitor specific for a compiler enginenitc :: AbstractCompiler :: VISITOR
nitc :: GlobalCompiler :: _classids
Cache for classidnitc :: AbstractCompiler :: _compiled_callref_thunk
All methods who already has a callref_thunk generated fornitc :: AbstractCompiler :: _compiled_null_types
Cache to avoid multiple compilation of NULL valuesnitc :: AbstractCompiler :: _extern_bodies
List of additional files required to compile (FFI)nitc :: AbstractCompiler :: _files_to_copy
List of source files to copy over to the compile dirnitc :: AbstractCompiler :: _header
Where global declaration are stored (the main .h)nitc :: AbstractCompiler :: _linker_script
Additionnal linker script forld
.
nitc :: GlobalCompiler :: _live_primitive_types
Subset of runtime_type_analysis.live_types that contains only primitive typesnitc :: AbstractCompiler :: _mainmodule
The main module of the program currently compilednitc :: AbstractCompiler :: _modelbuilder
The modelbuilder used to know the model and the ASTnitc :: AbstractCompiler :: _realmainmodule
The real main module of the programnitc :: GlobalCompiler :: _runtime_type_analysis
The result of the RTA (used to know live types and methods)nitc :: GlobalCompiler :: _seen
runtime_functions already seen (todo or done)nitc :: AbstractCompiler :: _seen_extern
This is used to avoid adding an extern file more than oncenitc :: AbstractCompiler :: _target_platform
The targeted specific platformnitc :: GlobalCompiler :: _todos
runtime_functions that need to be compilednitc :: AbstractCompiler :: build_c_to_nit_bindings
Builds the .c and .h files to be used when generating a Stack Tracecore :: Object :: class_factory
Implementation used byget_class
to create the specific class.
nitc :: GlobalCompiler :: classid
Return the C symbol associated to a live type runtimenitc :: GlobalCompiler :: classids
Cache for classidnitc :: GlobalCompiler :: classids=
Cache for classidnitc :: AbstractCompiler :: compile_before_main
Hook to add specif piece of code before the the main C function.nitc :: AbstractCompiler :: compile_begin_main
Hook to add specif piece of code at the begin on the main C function.nitc :: AbstractCompiler :: compile_catch_stack
Stack stocking environment for longjumpsnitc :: GlobalCompiler :: compile_class_names
Compile class names (for the class_name and output_class_name methods)nitc :: AbstractCompiler :: compile_header_structs
Declaration of structures for live Nit typesnitc :: AbstractCompiler :: compile_main_function
Generate the main C function.nitc :: AbstractCompiler :: compile_nitni_global_ref_functions
Copile all C functions related to the [incr|decr]_ref features of the FFInitc :: AbstractCompiler :: compile_nitni_structs
Declaration of structures for nitni undelying the FFInitc :: AbstractCompiler :: compiled_callref_thunk
All methods who already has a callref_thunk generated fornitc :: AbstractCompiler :: compiled_callref_thunk=
All methods who already has a callref_thunk generated fornitc :: AbstractCompiler :: compiled_null_types
Cache to avoid multiple compilation of NULL valuesnitc :: AbstractCompiler :: compiled_null_types=
Cache to avoid multiple compilation of NULL valuesnitc :: GlobalCompiler :: declare_runtimeclass
Declare C structures and identifiers for a runtime classnitc :: GlobalCompiler :: defaultinit
core :: Object :: defaultinit
nitc :: AbstractCompiler :: defaultinit
nitc :: AbstractCompiler :: do_compilation
Do the full code generation of the programmainmodule
nitc :: AbstractCompiler :: extern_bodies
List of additional files required to compile (FFI)nitc :: AbstractCompiler :: extern_bodies=
List of additional files required to compile (FFI)nitc :: AbstractCompiler :: files_to_copy
List of source files to copy over to the compile dirnitc :: AbstractCompiler :: files_to_copy=
List of source files to copy over to the compile dirnitc :: AbstractCompiler :: generate_check_attr
Generate code that check if an attribute is correctly initializednitc :: AbstractCompiler :: generate_init_attr
Generate code that initialize the attributes on a new instancenitc :: GlobalCompiler :: generate_init_instance
Generate the init-instance of a live type (allocate + init-instance)nitc :: AbstractCompiler :: header
Where global declaration are stored (the main .h)nitc :: AbstractCompiler :: header=
Where global declaration are stored (the main .h)core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
nitc :: AbstractCompiler :: linker_script
Additionnal linker script forld
.
nitc :: AbstractCompiler :: linker_script=
Additionnal linker script forld
.
nitc :: GlobalCompiler :: live_primitive_types
Subset of runtime_type_analysis.live_types that contains only primitive typesnitc :: GlobalCompiler :: live_primitive_types=
Subset of runtime_type_analysis.live_types that contains only primitive typesnitc :: AbstractCompiler :: mainmodule
The main module of the program currently compilednitc :: AbstractCompiler :: mainmodule=
The main module of the program currently compilednitc :: AbstractCompiler :: modelbuilder
The modelbuilder used to know the model and the ASTnitc :: AbstractCompiler :: modelbuilder=
The modelbuilder used to know the model and the ASTcore :: Object :: native_class_name
The class name of the object in CString format.nitc :: AbstractCompiler :: new_visitor
Initialize a visitor specific for a compiler enginecore :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: AbstractCompiler :: provide_declaration
Provide a declaration that can be requested (before or latter) by a visitornitc :: AbstractCompiler :: realmainmodule
The real main module of the programnitc :: AbstractCompiler :: realmainmodule=
The real main module of the programnitc :: GlobalCompiler :: runtime_type_analysis
The result of the RTA (used to know live types and methods)nitc :: GlobalCompiler :: runtime_type_analysis=
The result of the RTA (used to know live types and methods)nitc :: GlobalCompiler :: seen
runtime_functions already seen (todo or done)nitc :: GlobalCompiler :: seen=
runtime_functions already seen (todo or done)nitc :: AbstractCompiler :: seen_extern
This is used to avoid adding an extern file more than oncenitc :: AbstractCompiler :: seen_extern=
This is used to avoid adding an extern file more than oncenitc :: AbstractCompiler :: target_platform
The targeted specific platformnitc :: AbstractCompiler :: target_platform=
The targeted specific platformnitc :: GlobalCompiler :: todos
runtime_functions that need to be compilednitc :: GlobalCompiler :: todos=
runtime_functions that need to be compilednitc :: AbstractCompiler :: toolchain=
The associated toolchain
# Compiler that use global compilation and perform hard optimisations like:
# * customization
# * switch dispatch
# * inlining
class GlobalCompiler
super AbstractCompiler
redef type VISITOR: GlobalCompilerVisitor
# The result of the RTA (used to know live types and methods)
var runtime_type_analysis: RapidTypeAnalysis
init
do
var file = new_file("{mainmodule.c_name}.nitgg")
self.header = new CodeWriter(file)
self.live_primitive_types = new Array[MClassType]
for t in runtime_type_analysis.live_types do
if t.is_c_primitive or t.mclass.name == "Pointer" then
self.live_primitive_types.add(t)
end
end
end
redef fun do_compilation
do
var compiler = self
compiler.compile_header
if mainmodule.model.get_mclasses_by_name("Pointer") != null then
runtime_type_analysis.live_types.add(mainmodule.pointer_type)
end
for t in runtime_type_analysis.live_types do
compiler.declare_runtimeclass(t)
end
compiler.compile_class_names
# Init instance code (allocate and init-arguments)
for t in runtime_type_analysis.live_types do
if not t.is_c_primitive then
compiler.generate_init_instance(t)
if t.mclass.kind == extern_kind then
compiler.generate_box_instance(t)
end
else
compiler.generate_box_instance(t)
end
end
# The main function of the C
compiler.compile_nitni_global_ref_functions
compiler.compile_main_function
# Compile until all runtime_functions are visited
while not compiler.todos.is_empty do
var m = compiler.todos.shift
modelbuilder.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3)
m.compile_to_c(compiler)
end
modelbuilder.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2)
end
# Compile class names (for the class_name and output_class_name methods)
protected fun compile_class_names do
var v = new_visitor
self.header.add_decl("extern const char *class_names[];")
v.add("const char *class_names[] = \{")
for t in self.runtime_type_analysis.live_types do
v.add("\"{t}\", /* {self.classid(t)} */")
end
v.add("\};")
end
# Return the C symbol associated to a live type runtime
# REQUIRE: self.runtime_type_analysis.live_types.has(mtype)
fun classid(mtype: MClassType): String
do
if self.classids.has_key(mtype) then
return self.classids[mtype]
end
print_error "No classid for {mtype}"
abort
end
# Cache for classid
protected var classids: HashMap[MClassType, String] = new HashMap[MClassType, String]
# Declaration of structures the live Nit types
# Each live type is generated as an independent C `struct` type.
# They only share a common first field `classid` used to implement the polymorphism.
# Usualy, all C variables that refers to a Nit object are typed on the abstract struct `val` that contains only the `classid` field.
redef fun compile_header_structs do
self.header.add_decl("typedef struct \{int classid;\} val; /* general C type representing a Nit instance. */")
end
# Subset of runtime_type_analysis.live_types that contains only primitive types
# Used to implement the equal test
var live_primitive_types: Array[MClassType] is noinit
# Add a new todo task
fun todo(m: AbstractRuntimeFunction)
do
if seen.has(m) then return
todos.add(m)
seen.add(m)
end
# runtime_functions that need to be compiled
private var todos: List[AbstractRuntimeFunction] = new List[AbstractRuntimeFunction]
# runtime_functions already seen (todo or done)
private var seen: HashSet[AbstractRuntimeFunction] = new HashSet[AbstractRuntimeFunction]
# Declare C structures and identifiers for a runtime class
fun declare_runtimeclass(mtype: MClassType)
do
var v = self.header
assert self.runtime_type_analysis.live_types.has(mtype)
v.add_decl("/* runtime class {mtype} */")
var idnum = classids.length
var idname = "ID_" + mtype.c_name
self.classids[mtype] = idname
v.add_decl("#define {idname} {idnum} /* {mtype} */")
v.add_decl("struct {mtype.c_name} \{")
v.add_decl("int classid; /* must be {idname} */")
if mtype.mclass.name == "NativeArray" then
# NativeArrays are just a instance header followed by an array of values
v.add_decl("int length;")
v.add_decl("{mtype.arguments.first.ctype} values[1];")
end
if all_routine_types_name.has(mtype.mclass.name) then
v.add_decl("val* recv;")
var c_args = ["val* self"]
var c_ret = "void"
var k = mtype.arguments.length
if mtype.mclass.name.has("Fun") then
c_ret = mtype.arguments.last.ctype
k -= 1
end
for i in [0..k[ do
var t = mtype.arguments[i]
c_args.push("{t.ctype} p{i}")
end
var c_sig = c_args.join(", ")
v.add_decl("{c_ret} (*method)({c_sig});")
end
if mtype.ctype_extern != "val*" then
# Is the Nit type is native then the struct is a box with two fields:
# * the `classid` to be polymorph
# * the `value` that contains the native value.
v.add_decl("{mtype.ctype_extern} value;")
end
# Collect all attributes and associate them a field in the structure.
# Note: we do not try to optimize the order and helps CC to optimize the client code.
for cd in mtype.collect_mclassdefs(self.mainmodule) do
for p in cd.intro_mproperties do
if not p isa MAttribute then continue
var t = p.intro.static_mtype.as(not null)
t = t.anchor_to(self.mainmodule, mtype)
v.add_decl("{t.ctype} {p.intro.c_name}; /* {p}: {t} */")
end
end
v.add_decl("\};")
end
# Generate the init-instance of a live type (allocate + init-instance)
fun generate_init_instance(mtype: MClassType)
do
assert self.runtime_type_analysis.live_types.has(mtype)
assert not mtype.is_c_primitive
var v = self.new_visitor
var is_native_array = mtype.mclass.name == "NativeArray"
var is_routine_ref = all_routine_types_name.has(mtype.mclass.name)
var sig
if is_native_array then
sig = "int length"
else
sig = "void"
end
if is_routine_ref then
var c_args = ["val* self"]
var c_ret = "void"
var k = mtype.arguments.length
if mtype.mclass.name.has("Fun") then
c_ret = mtype.arguments.last.ctype
k -= 1
end
for i in [0..k[ do
var t = mtype.arguments[i]
c_args.push("{t.ctype} p{i}")
end
# The underlying method signature
var method_sig = "{c_ret} (*method)({c_args.join(", ")})"
sig = "val* recv, {method_sig}"
end
self.header.add_decl("{mtype.ctype} NEW_{mtype.c_name}({sig});")
v.add_decl("/* allocate {mtype} */")
v.add_decl("{mtype.ctype} NEW_{mtype.c_name}({sig}) \{")
var res = v.new_var(mtype)
res.is_exact = true
if is_native_array then
v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}) + length*sizeof(val*));")
v.add("((struct {mtype.c_name}*){res})->length = length;")
else
v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}));")
end
if is_routine_ref then
v.add("((struct {mtype.c_name}*){res})->recv = recv;")
v.add("((struct {mtype.c_name}*){res})->method = method;")
end
v.add("{res}->classid = {self.classid(mtype)};")
self.generate_init_attr(v, res, mtype)
v.set_finalizer res
v.add("return {res};")
v.add("\}")
end
fun generate_box_instance(mtype: MClassType)
do
assert self.runtime_type_analysis.live_types.has(mtype)
var v = self.new_visitor
self.header.add_decl("val* BOX_{mtype.c_name}({mtype.ctype});")
v.add_decl("/* allocate {mtype} */")
v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{")
v.add("struct {mtype.c_name}*res = nit_alloc(sizeof(struct {mtype.c_name}));")
v.add("res->classid = {self.classid(mtype)};")
v.add("res->value = value;")
v.add("return (val*)res;")
v.add("\}")
end
redef fun new_visitor do return new GlobalCompilerVisitor(self)
private var collect_types_cache: HashMap[MType, Array[MClassType]] = new HashMap[MType, Array[MClassType]]
redef fun compile_nitni_structs
do
self.header.add_decl """
struct nitni_instance \{
struct nitni_instance *next,
*prev; /* adjacent global references in global list */
int count; /* number of time this global reference has been marked */
val *value;
\};"""
super
end
end
src/compiler/global_compiler.nit:71,1--329,3