# Simple indirection to `Toolchain::write_and_make`
protected fun write_and_make(compiler: AbstractCompiler)
do
- var platform = compiler.mainmodule.target_platform
- var toolchain
- if platform == null then
- toolchain = new MakefileToolchain(toolcontext)
- else
- toolchain = platform.toolchain(toolcontext)
- end
+ var platform = compiler.target_platform
+ var toolchain = platform.toolchain(toolcontext)
compile_dir = toolchain.compile_dir
toolchain.write_and_make compiler
end
end
redef class Platform
- fun toolchain(toolcontext: ToolContext): Toolchain is abstract
+ # The specific tool-chain associated to the platform
+ fun toolchain(toolcontext: ToolContext): Toolchain do return new MakefileToolchain(toolcontext)
end
class Toolchain
fun write_files(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
do
- var platform = compiler.mainmodule.target_platform
- if self.toolcontext.opt_stacktrace.value == "nitstack" and (platform == null or platform.supports_libunwind) then compiler.build_c_to_nit_bindings
+ var platform = compiler.target_platform
+ if self.toolcontext.opt_stacktrace.value == "nitstack" and platform.supports_libunwind then compiler.build_c_to_nit_bindings
var cc_opt_with_libgc = "-DWITH_LIBGC"
- if platform != null and not platform.supports_libgc then cc_opt_with_libgc = ""
+ if not platform.supports_libgc then cc_opt_with_libgc = ""
# Add gc_choser.h to aditionnal bodies
var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc)
fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
do
var mainmodule = compiler.mainmodule
- var platform = compiler.mainmodule.target_platform
+ var platform = compiler.target_platform
var outname = outfile(mainmodule)
makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n")
var ost = toolcontext.opt_stacktrace.value
- if (ost == "libunwind" or ost == "nitstack") and (platform == null or platform.supports_libunwind) then makefile.write("NEED_LIBUNWIND := YesPlease\n")
+ if (ost == "libunwind" or ost == "nitstack") and platform.supports_libunwind then makefile.write("NEED_LIBUNWIND := YesPlease\n")
# Dynamic adaptations
# While `platform` enable complex toolchains, they are statically applied
dep_rules.add(o)
end
+ # Generate linker script, if any
+ if not compiler.linker_script.is_empty then
+ var linker_script_path = "{compile_dir}/linker_script"
+ ofiles.add "linker_script"
+ var f = new OFStream.open(linker_script_path)
+ for l in compiler.linker_script do
+ f.write l
+ f.write "\n"
+ end
+ f.close
+ end
+
var java_files = new Array[ExternFile]
var pkgconfigs = new Array[String]
# Is hardening asked? (see --hardening)
fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value
+ # The targeted specific platform
+ var target_platform: Platform is noinit
+
init
do
self.realmainmodule = mainmodule
+ target_platform = mainmodule.target_platform or else new Platform
end
+ # Do the full code generation of the program `mainmodule`
+ # It is the main method usually called after the instantiation
+ fun do_compilation is abstract
+
# Force the creation of a new file
# The point is to avoid contamination between must-be-compiled-separately files
fun new_file(name: String): CodeFile
# Where global declaration are stored (the main .h)
var header: CodeWriter is writable, noinit
+ # Additionnal linker script for `ld`.
+ # Mainly used to do specific link-time symbol resolution
+ var linker_script = new Array[String]
+
# Provide a declaration that can be requested (before or latter) by a visitor
fun provide_declaration(key: String, s: String)
do
var v = self.new_visitor
v.add_decl("#include <signal.h>")
var ost = modelbuilder.toolcontext.opt_stacktrace.value
- var platform = mainmodule.target_platform
+ var platform = target_platform
- if platform != null and not platform.supports_libunwind then ost = "none"
+ if not platform.supports_libunwind then ost = "none"
- var no_main = (platform != null and platform.no_main) or modelbuilder.toolcontext.opt_no_main.value
+ var no_main = platform.no_main or modelbuilder.toolcontext.opt_no_main.value
if ost == "nitstack" or ost == "libunwind" then
v.add_decl("#define UNW_LOCAL_ONLY")
v.add("return 0;")
v.add("\}")
+
+ for m in mainmodule.in_importation.greaters do
+ var f = "FILE_"+m.c_name
+ v.add "const char {f}[] = \"{m.location.file.filename.escape_to_c}\";"
+ provide_declaration(f, "extern const char {f}[];")
+ end
end
# Copile all C functions related to the [incr|decr]_ref features of the FFI
# Generate a alloc-instance + init-attributes
fun init_instance(mtype: MClassType): RuntimeVariable is abstract
+ # Allocate and init attributes of an instance of a standard or extern class
+ #
+ # Does not support universals and the pseudo-internal `NativeArray` class.
+ fun init_instance_or_extern(mtype: MClassType): RuntimeVariable
+ do
+ var recv
+ var ctype = mtype.ctype
+ assert mtype.mclass.name != "NativeArray"
+ if ctype == "val*" then
+ recv = init_instance(mtype)
+ else if ctype == "char*" then
+ recv = new_expr("NULL/*special!*/", mtype)
+ else
+ recv = new_expr("({ctype})0/*special!*/", mtype)
+ end
+ return recv
+ end
+
# Set a GC finalizer on `recv`, only if `recv` isa Finalizable
fun set_finalizer(recv: RuntimeVariable)
do
self.require_declaration(s)
end
- # look for a needed .h and .c file for a given .nit source-file
- # FIXME: bad API, parameter should be a `MModule`, not its source-file
- fun add_extern(file: String)
+ # Look for a needed .h and .c file for a given module
+ # This is used for the legacy FFI
+ fun add_extern(mmodule: MModule)
do
+ var file = mmodule.location.file.filename
file = file.strip_extension(".nit")
var tryfile = file + ".nit.h"
if tryfile.file_exists then
fun add_raw_abort
do
- if self.current_node != null and self.current_node.location.file != null then
- self.add("PRINT_ERROR(\" (%s:%d)\\n\", \"{self.current_node.location.file.filename.escape_to_c}\", {current_node.location.line_start});")
+ if self.current_node != null and self.current_node.location.file != null and
+ self.current_node.location.file.mmodule != null then
+ var f = "FILE_{self.current_node.location.file.mmodule.c_name}"
+ self.require_declaration(f)
+ self.add("PRINT_ERROR(\" (%s:%d)\\n\", {f}, {current_node.location.line_start});")
else
self.add("PRINT_ERROR(\"\\n\");")
end
do
var externname
var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
- if at != null then
+ if at != null and at.n_args.length == 1 then
externname = at.arg_as_string(v.compiler.modelbuilder)
if externname == null then return false
else
return false
end
- if location.file != null then
- var file = location.file.filename
- v.add_extern(file)
- end
+ v.add_extern(mpropdef.mclassdef.mmodule)
var res: nullable RuntimeVariable = null
var ret = mpropdef.msignature.return_mtype
if ret != null then
else
return false
end
- if location.file != null then
- var file = location.file.filename
- v.add_extern(file)
- end
+ v.add_extern(mpropdef.mclassdef.mmodule)
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
var ret = arguments.first.mtype
do
var mtype = self.recvtype
assert mtype != null
- var recv
- var ctype = mtype.ctype
+
if mtype.mclass.name == "NativeArray" then
assert self.n_args.n_exprs.length == 1
var l = v.expr(self.n_args.n_exprs.first, null)
assert mtype isa MGenericType
var elttype = mtype.arguments.first
return v.native_array_instance(elttype, l)
- else if ctype == "val*" then
- recv = v.init_instance(mtype)
- else if ctype == "char*" then
- recv = v.new_expr("NULL/*special!*/", mtype)
- else
- recv = v.new_expr("({ctype})0/*special!*/", mtype)
end
+ var recv = v.init_instance_or_extern(mtype)
+
var callsite = self.callsite.as(not null)
var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
var res2 = v.compile_callsite(callsite, args)
# Give requided addinional system libraries (as given to LD_LIBS)
# Note: can return null instead of an empty set
- fun collect_linker_libs: nullable Set[String] do return null
+ fun collect_linker_libs: nullable Array[String] do return null
end
# Create a tool context to handle options and paths