import auto_super_init
import frontend
import common_ffi
+import platform
# Add compiling options
redef class ToolContext
end
redef class ModelBuilder
+ redef init(model, toolcontext)
+ do
+ if toolcontext.opt_no_stacktrace.value and toolcontext.opt_stacktrace.value then
+ print "Cannot use --nit-stacktrace when --no-stacktrace is activated"
+ exit(1)
+ end
+
+ super
+ end
+
+ # The compilation directory
+ var compile_dir: String
+
+ # 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
+ compile_dir = toolchain.compile_dir
+ toolchain.write_and_make compiler
+ end
+end
+
+redef class Platform
+ fun toolchain(toolcontext: ToolContext): Toolchain is abstract
+end
+
+class Toolchain
+ var toolcontext: ToolContext
+
+ fun compile_dir: String
+ do
+ var compile_dir = toolcontext.opt_compile_dir.value
+ if compile_dir == null then compile_dir = ".nit_compile"
+ return compile_dir
+ end
+
+ fun write_and_make(compiler: AbstractCompiler) is abstract
+end
+
+class MakefileToolchain
+ super Toolchain
# The list of directories to search for included C headers (-I for C compilers)
# The list is initially set with :
# * the toolcontext --cc-path option
# Path can be added (or removed) by the client
var cc_paths = new Array[String]
- redef init(model, toolcontext)
+ protected fun gather_cc_paths
do
- super
-
# Look for the the Nit clib path
var path_env = "NIT_DIR".environ
if not path_env.is_empty then
toolcontext.error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.")
end
- if toolcontext.opt_no_stacktrace.value and toolcontext.opt_stacktrace.value then
- print "Cannot use --nit-stacktrace when --no-stacktrace is activated"
- exit(1)
- end
-
# Add user defined cc_paths
cc_paths.append(toolcontext.opt_cc_path.value)
if not path_env.is_empty then
cc_paths.append(path_env.split_with(':'))
end
-
- var compile_dir = toolcontext.opt_compile_dir.value
- if compile_dir == null then compile_dir = ".nit_compile"
- self.compile_dir = compile_dir
end
- # The compilation directory
- var compile_dir: String
-
- protected fun write_and_make(compiler: AbstractCompiler)
+ redef fun write_and_make(compiler)
do
+ gather_cc_paths
+
var mainmodule = compiler.mainmodule
+ var compile_dir = compile_dir
# Generate the .h and .c files
# A single C file regroups many compiled rumtime functions
compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.h"
# FFI
- for m in compiler.mainmodule.in_importation.greaters do if mmodule2nmodule.keys.has(m) then
- var amodule = mmodule2nmodule[m]
+ var m2m = toolcontext.modelbuilder.mmodule2nmodule
+ for m in compiler.mainmodule.in_importation.greaters do if m2m.keys.has(m) then
+ var amodule = m2m[m]
if m.uses_ffi or amodule.uses_legacy_ni then
compiler.finalize_ffi_for_module(amodule)
end
hfile.write "#include \"{hfilename}\"\n"
for key in f.required_declarations do
if not compiler.provided_declarations.has_key(key) then
- print "No provided declaration for {key}"
+ var node = compiler.requirers_of_declarations.get_or_null(key)
+ if node != null then
+ node.debug "No provided declaration for {key}"
+ else
+ print "No provided declaration for {key}"
+ end
abort
end
hfile.write compiler.provided_declarations[key]
end
var linker_options = new HashSet[String]
- for m in mainmodule.in_importation.greaters do if mmodule2nmodule.keys.has(m) then
- var amod = mmodule2nmodule[m]
+ var m2m = toolcontext.modelbuilder.mmodule2nmodule
+ for m in mainmodule.in_importation.greaters do if m2m.keys.has(m) then
+ var amod = m2m[m]
linker_options.add(amod.c_linker_options)
end
makefile.write("all: {outpath}\n\n")
var ofiles = new Array[String]
+ var dep_rules = new Array[String]
# Compile each generated file
for f in cfiles do
var o = f.strip_extension(".c") + ".o"
makefile.write("{o}: {f}\n\t$(CC) $(CFLAGS) $(CINCL) -D NONITCNI -c -o {o} {f}\n\n")
ofiles.add(o)
+ dep_rules.add(o)
end
# Compile each required extern body into a specific .o
var ff = f.filename.basename("")
makefile.write("{o}: {ff}\n\t$(CC) $(CFLAGS) -D NONITCNI {f.cflags} -c -o {o} {ff}\n\n")
ofiles.add(o)
+ dep_rules.add(o)
+ else
+ var o = f.makefile_rule_name
+ var ff = f.filename.basename("")
+ makefile.write("{o}: {ff}\n")
+ makefile.write("\t{f.makefile_rule_content}\n")
+ dep_rules.add(f.makefile_rule_name)
+
+ if f isa ExternCppFile then ofiles.add(o)
end
end
private var provided_declarations = new HashMap[String, String]
+ private var requirers_of_declarations = new HashMap[String, ANode]
+
# Builds the .c and .h files to be used when generating a Stack Trace
# Binds the generated C function names to Nit function names
fun build_c_to_nit_bindings
end
end
+ v.add_decl("void sig_handler(int signo)\{")
+ v.add_decl("printf(\"Caught signal : %s\\n\", strsignal(signo));")
+ v.add_decl("show_backtrace(signo);")
+ v.add_decl("\}")
+
v.add_decl("void show_backtrace (int signo) \{")
if not modelbuilder.toolcontext.opt_no_stacktrace.value then
v.add_decl("char* opt = getenv(\"NIT_NO_STACK\");")
v.add_decl("int main(int argc, char** argv) \{")
- v.add("signal(SIGABRT, show_backtrace);")
- v.add("signal(SIGFPE, show_backtrace);")
- v.add("signal(SIGILL, show_backtrace);")
- v.add("signal(SIGINT, show_backtrace);")
- v.add("signal(SIGTERM, show_backtrace);")
- v.add("signal(SIGSEGV, show_backtrace);")
+ v.add("signal(SIGABRT, sig_handler);")
+ v.add("signal(SIGFPE, sig_handler);")
+ v.add("signal(SIGILL, sig_handler);")
+ v.add("signal(SIGINT, sig_handler);")
+ v.add("signal(SIGTERM, sig_handler);")
+ v.add("signal(SIGSEGV, sig_handler);")
v.add("glob_argc = argc; glob_argv = argv;")
v.add("initialize_gc_option();")
nmodule.finalize_ffi(visitor, modelbuilder)
nmodule.finalize_nitni(visitor)
end
-
- # Does this compiler support the FFI?
- fun supports_ffi: Bool do return false
end
# A file unit (may be more than one file if
# Request the presence of a global declaration
fun require_declaration(key: String)
do
- self.writer.file.required_declarations.add(key)
+ var reqs = self.writer.file.required_declarations
+ if reqs.has(key) then return
+ reqs.add(key)
+ var node = current_node
+ if node != null then compiler.requirers_of_declarations[key] = node
end
# Add a declaration in the local-header
# Call the implicit super-init
var auto_super_inits = self.auto_super_inits
if auto_super_inits != null then
- var selfarg = [arguments.first]
+ var args = [arguments.first]
for auto_super_init in auto_super_inits do
- if auto_super_init.intro.msignature.arity == 0 then
- v.send(auto_super_init, selfarg)
- else
- v.send(auto_super_init, arguments)
+ args.clear
+ for i in [0..auto_super_init.msignature.arity+1[ do
+ args.add(arguments[i])
end
+ v.compile_callsite(auto_super_init, args)
end
end
v.stmt(self.n_block)
for a in self.n_args.n_exprs do
args.add(v.expr(a, null))
end
- if args.length == 1 then
- args = v.frame.arguments
- end
var callsite = self.callsite
if callsite != null then
- if callsite.mproperty.intro.msignature.arity == 0 then
- args = [recv]
+ # Add additionnals arguments for the super init call
+ if args.length == 1 then
+ for i in [0..callsite.mproperty.intro.msignature.arity[ do
+ args.add(v.frame.arguments[i+1])
+ end
end
# Super init call
var res = v.compile_callsite(callsite, args)
return res
end
+ if args.length == 1 then
+ args = v.frame.arguments
+ end
+
# stantard call-next-method
- return v.supercall(v.frame.mpropdef.as(MMethodDef), recv.mtype.as(MClassType), args)
+ return v.supercall(mpropdef.as(not null), recv.mtype.as(MClassType), args)
end
end