X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 1a1bb07..cff93bd 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -25,6 +25,7 @@ private import annotation import mixin import counter import pkgconfig +private import explain_assert_api # Add compiling options redef class ToolContext @@ -74,6 +75,8 @@ redef class ToolContext var opt_release = new OptionBool("Compile in release mode and finalize application", "--release") # -g var opt_debug = new OptionBool("Compile in debug mode (no C-side optimization)", "-g", "--debug") + # --trace + var opt_trace = new OptionBool("Compile with lttng's instrumentation", "--trace") redef init do @@ -86,6 +89,7 @@ redef class ToolContext self.option_context.add_option(self.opt_release) self.option_context.add_option(self.opt_max_c_lines, self.opt_group_c_files) self.option_context.add_option(self.opt_debug) + self.option_context.add_option(self.opt_trace) opt_no_main.hidden = true end @@ -232,6 +236,16 @@ class MakefileToolchain compiler.files_to_copy.add "{clib}/gc_chooser.c" compiler.files_to_copy.add "{clib}/gc_chooser.h" + # Add lttng traces provider to external bodies + if toolcontext.opt_trace.value then + #-I. is there in order to make the TRACEPOINT_INCLUDE directive in clib/traces.h refer to the directory in which gcc was invoked. + var traces = new ExternCFile("traces.c", "-I.") + traces.pkgconfigs.add "lttng-ust" + compiler.extern_bodies.add(traces) + compiler.files_to_copy.add "{clib}/traces.c" + compiler.files_to_copy.add "{clib}/traces.h" + end + # FFI for m in compiler.mainmodule.in_importation.greaters do compiler.finalize_ffi_for_module(m) @@ -375,6 +389,8 @@ LDFLAGS ?= LDLIBS ?= -lm {{{linker_options.join(" ")}}} \n""" + if self.toolcontext.opt_trace.value then makefile.write "LDLIBS += -llttng-ust -ldl\n" + makefile.write "\n# SPECIAL CONFIGURATION FLAGS\n" if platform.supports_libunwind then if toolcontext.opt_no_stacktrace.value then @@ -705,6 +721,7 @@ abstract class AbstractCompiler self.header.add_decl("#endif") self.header.add_decl("#include \n") self.header.add_decl("#include \"gc_chooser.h\"") + if modelbuilder.toolcontext.opt_trace.value then self.header.add_decl("#include \"traces.h\"") self.header.add_decl("#ifdef __APPLE__") self.header.add_decl(" #include ") self.header.add_decl(" #include ") @@ -714,10 +731,6 @@ abstract class AbstractCompiler 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("#ifdef ANDROID") self.header.add_decl(" #ifndef be32toh") self.header.add_decl(" #define be32toh(val) betoh32(val)") @@ -766,9 +779,10 @@ abstract class AbstractCompiler self.header.add_decl """ struct catch_stack_t { int cursor; - jmp_buf envs[100]; + int currentSize; + jmp_buf *envs; }; -extern struct catch_stack_t catchStack; +extern __thread struct catch_stack_t catchStack; """ end @@ -869,7 +883,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); v.add_decl("int glob_argc;") v.add_decl("char **glob_argv;") v.add_decl("val *glob_sys;") - v.add_decl("struct catch_stack_t catchStack;") + v.add_decl("__thread struct catch_stack_t catchStack = \{-1, 0, NULL\};") if self.modelbuilder.toolcontext.opt_typing_test_metrics.value then for tag in count_type_test_tags do @@ -970,7 +984,6 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); v.add "#endif" v.add("glob_argc = argc; glob_argv = argv;") - v.add("catchStack.cursor = -1;") v.add("initialize_gc_option();") v.add "initialize_nitni_global_refs();" @@ -1391,6 +1404,11 @@ abstract class AbstractCompilerVisitor mtype = self.anchor(mtype) var valmtype = value.mcasttype + # CPrimitive is the best you can do + if valmtype.is_c_primitive then + return value + end + # Do nothing if useless autocast if valmtype.is_subtype(self.compiler.mainmodule, null, mtype) then return value @@ -3503,6 +3521,14 @@ redef class ADoExpr redef fun stmt(v) do if self.n_catch != null then + v.add("if(catchStack.currentSize == 0) \{") + v.add(" catchStack.cursor = -1;") + v.add(" catchStack.currentSize = 100;") + v.add(" catchStack.envs = malloc(sizeof(jmp_buf)*100);") + v.add("\} else if(catchStack.cursor == catchStack.currentSize - 1) \{") + v.add(" catchStack.currentSize *= 2;") + v.add(" catchStack.envs = realloc(catchStack.envs, sizeof(jmp_buf)*catchStack.currentSize);") + v.add("\}") v.add("catchStack.cursor += 1;") v.add("if(!setjmp(catchStack.envs[catchStack.cursor]))\{") v.stmt(self.n_block) @@ -3615,6 +3641,9 @@ redef class AAssertExpr var cond = v.expr_bool(self.n_expr) v.add("if (unlikely(!{cond})) \{") v.stmt(self.n_else) + + explain_assert v + var nid = self.n_id if nid != null then v.add_abort("Assert '{nid.text}' failed") @@ -3623,6 +3652,27 @@ redef class AAssertExpr end v.add("\}") end + + # Explain assert if it fails + private fun explain_assert(v: AbstractCompilerVisitor) + do + var explain_assert_str = explain_assert_str + if explain_assert_str == null then return + + var nas = v.compiler.modelbuilder.model.get_mclasses_by_name("NativeArray") + if nas == null then return + + nas = v.compiler.modelbuilder.model.get_mclasses_by_name("Array") + if nas == null or nas.is_empty then return + + var expr = explain_assert_str.expr(v) + if expr == null then return + + var cstr = v.send(v.get_property("to_cstring", expr.mtype), [expr]) + if cstr == null then return + + v.add "PRINT_ERROR(\"Runtime assert: %s\\n\", {cstr});" + end end redef class AOrExpr