self.toolcontext.info(command, 2)
var res
- if self.toolcontext.verbose_level >= 3 then
+ if self.toolcontext.verbose_level >= 3 or is_windows then
res = sys.system("{command} 2>&1")
else
res = sys.system("{command} 2>&1 >/dev/null")
self.header.add_decl("#include <inttypes.h>\n")
self.header.add_decl("#include \"gc_chooser.h\"")
self.header.add_decl("#ifdef __APPLE__")
+ self.header.add_decl(" #include <TargetConditionals.h>")
+ self.header.add_decl(" #include <syslog.h>")
self.header.add_decl(" #include <libkern/OSByteOrder.h>")
self.header.add_decl(" #define be32toh(x) OSSwapBigToHostInt32(x)")
self.header.add_decl("#endif")
+ self.header.add_decl("#ifdef _WIN32")
+ self.header.add_decl(" #define be32toh(val) _byteswap_ulong(val)")
+ self.header.add_decl("#endif")
self.header.add_decl("#ifdef __pnacl__")
self.header.add_decl(" #define be16toh(val) (((val) >> 8) | ((val) << 8))")
self.header.add_decl(" #define be32toh(val) ((be16toh((val) << 16) | (be16toh((val) >> 16))))")
self.header.add_decl(" #endif")
self.header.add_decl(" #include <android/log.h>")
self.header.add_decl(" #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)")
+ self.header.add_decl("#elif TARGET_OS_IPHONE")
+ self.header.add_decl(" #define PRINT_ERROR(...) syslog(LOG_ERR, __VA_ARGS__)")
self.header.add_decl("#else")
self.header.add_decl(" #define PRINT_ERROR(...) fprintf(stderr, __VA_ARGS__)")
self.header.add_decl("#endif")
v.add "\}"
end
+ # Hook to add specif piece of code before the the main C function.
+ #
+ # Is called by `compile_main_function`
+ fun compile_before_main(v: VISITOR)
+ do
+ end
+
+ # Hook to add specif piece of code at the begin on the main C function.
+ #
+ # Is called by `compile_main_function`
+ fun compile_begin_main(v: VISITOR)
+ do
+ end
+
# Generate the main C function.
#
# This function:
v.add_decl("\}")
v.add_decl("void sig_handler(int signo)\{")
+ v.add_decl "#ifdef _WIN32"
+ v.add_decl "PRINT_ERROR(\"Caught signal : %s\\n\", signo);"
+ v.add_decl "#else"
v.add_decl("PRINT_ERROR(\"Caught signal : %s\\n\", strsignal(signo));")
+ v.add_decl "#endif"
v.add_decl("show_backtrace();")
# rethrows
v.add_decl("signal(signo, SIG_DFL);")
+ v.add_decl "#ifndef _WIN32"
v.add_decl("kill(getpid(), signo);")
+ v.add_decl "#endif"
v.add_decl("\}")
v.add_decl("void fatal_exit(int status) \{")
v.add_decl("exit(status);")
v.add_decl("\}")
+ compile_before_main(v)
+
if no_main then
v.add_decl("int nit_main(int argc, char** argv) \{")
else
v.add_decl("int main(int argc, char** argv) \{")
end
+ compile_begin_main(v)
+
v.add "#if !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE)"
v.add("signal(SIGABRT, sig_handler);")
v.add("signal(SIGFPE, sig_handler);")
v.add("signal(SIGTERM, sig_handler);")
v.add("signal(SIGSEGV, sig_handler);")
v.add "#endif"
+ v.add "#ifndef _WIN32"
v.add("signal(SIGPIPE, SIG_IGN);")
+ v.add "#endif"
v.add("glob_argc = argc; glob_argv = argv;")
v.add("catchStack.cursor = -1;")
fun finalize_ffi_for_module(mmodule: MModule) do mmodule.finalize_ffi(self)
end
-# A file unit (may be more than one file if
-# A file unit aim to be autonomous and is made or one or more `CodeWriter`s
+# C code file generated from the `writers` and the `required_declarations`
+#
+# A file unit aims to be autonomous and is made or one or more `CodeWriter`s.
class CodeFile
+ # Basename of the file, will be appended by `.h` and `.c`
var name: String
+
+ # `CodeWriter` used in sequence to fill the top of the body, then the bottom
var writers = new Array[CodeWriter]
+
+ # Required declarations keys
+ #
+ # See: `provide_declaration`
var required_declarations = new HashSet[String]
end
-# Where to store generated lines
+# Store generated lines
+#
+# Instances are added to `file.writers` at construction.
class CodeWriter
+ # Parent `CodeFile`
var file: CodeFile
+
+ # Main lines of code (written at the bottom of the body)
var lines = new Array[String]
+
+ # Lines of code for declarations (written at the top of the body)
var decl_lines = new Array[String]
- # Add a line in the main part of the generated C
+ # Add a line in the main lines of code (to `lines`)
fun add(s: String) do self.lines.add(s)
- # Add a line in the
- # (used for local or global declaration)
+ # Add a declaration line (to `decl_lines`)
+ #
+ # Used for local and global declaration.
fun add_decl(s: String) do self.decl_lines.add(s)
init
fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable is abstract
- fun calloc_array(ret_type: MType, arguments: Array[RuntimeVariable]) is abstract
-
fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]): Bool do return false
# Return an element of a native array.
# The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
fun native_array_set(native_array: RuntimeVariable, index: Int, value: RuntimeVariable) is abstract
+ # Allocate `size` bytes with the low_level `nit_alloc` C function
+ #
+ # This method can be redefined to inject statistic or tracing code.
+ #
+ # `tag` if any, is used to mark the class of the allocated object.
+ fun nit_alloc(size: String, tag: nullable String): String
+ do
+ return "nit_alloc({size})"
+ end
+
# Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
# This method is used to manage varargs in signatures and returns the real array
# of runtime variables to use in the call.
v.ret(v.new_expr("!{res}", ret.as(not null)))
return true
else if pname == "new" then
- v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
+ var alloc = v.nit_alloc(arguments[1].to_s, "NativeString")
+ v.ret(v.new_expr("(char*){alloc}", ret.as(not null)))
return true
else if pname == "fetch_4_chars" then
v.ret(v.new_expr("(long)*((uint32_t*)({arguments[0]} + {arguments[1]}))", ret.as(not null)))
else if pname == "sys" then
v.ret(v.new_expr("glob_sys", ret.as(not null)))
return true
- else if pname == "calloc_string" then
- v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
- return true
- else if pname == "calloc_array" then
- v.calloc_array(ret.as(not null), arguments)
- return true
else if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true