X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 905812e..5fca1a1 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -349,7 +349,7 @@ class MakefileToolchain end var debug = toolcontext.opt_debug.value - makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g{ if not debug then " -O2 " else " "}-Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n") + makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g{ if not debug then " -O2 " else " "}-Wno-unused-value -Wno-switch -Wno-attributes -Wno-trigraphs\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n") makefile.write "\n# SPECIAL CONFIGURATION FLAGS\n" if platform.supports_libunwind then @@ -654,9 +654,23 @@ abstract class AbstractCompiler self.header.add_decl("#include \n") self.header.add_decl("#include \n") self.header.add_decl("#include \n") + self.header.add_decl("#ifdef __linux__") + self.header.add_decl(" #include ") + self.header.add_decl("#endif") self.header.add_decl("#include \n") self.header.add_decl("#include \"gc_chooser.h\"") + self.header.add_decl("#ifdef __APPLE__") + self.header.add_decl(" #include ") + self.header.add_decl(" #define be32toh(x) OSSwapBigToHostInt32(x)") + 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)") + self.header.add_decl(" #endif") self.header.add_decl(" #include ") self.header.add_decl(" #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)") self.header.add_decl("#else") @@ -853,7 +867,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); v.add_decl("int main(int argc, char** argv) \{") end - v.add "#ifndef ANDROID" + v.add "#if !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE)" v.add("signal(SIGABRT, sig_handler);") v.add("signal(SIGFPE, sig_handler);") v.add("signal(SIGILL, sig_handler);") @@ -1259,17 +1273,21 @@ abstract class AbstractCompilerVisitor do mtype = self.anchor(mtype) var valmtype = value.mcasttype + + # Do nothing if useless autocast if valmtype.is_subtype(self.compiler.mainmodule, null, mtype) then return value end + # Just as_not_null if the target is not nullable. + # + # eg `nullable PreciseType` adapted to `Object` gives precisetype. if valmtype isa MNullableType and valmtype.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then - var res = new RuntimeVariable(value.name, valmtype, valmtype.mtype) - return res - else - var res = new RuntimeVariable(value.name, valmtype, mtype) - return res + mtype = valmtype.mtype end + + var res = new RuntimeVariable(value.name, value.mtype, mtype) + return res end # Generate a super call from a method definition @@ -1337,13 +1355,18 @@ abstract class AbstractCompilerVisitor # Checks + # Can value be null? (according to current knowledge) + fun maybenull(value: RuntimeVariable): Bool + do + return value.mcasttype isa MNullableType or value.mcasttype isa MNullType + end + # Add a check and an abort for a null receiver if needed fun check_recv_notnull(recv: RuntimeVariable) do if self.compiler.modelbuilder.toolcontext.opt_no_check_null.value then return - var maybenull = recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType - if maybenull then + if maybenull(recv) then self.add("if (unlikely({recv} == NULL)) \{") self.add_abort("Receiver is null") self.add("\}") @@ -2032,6 +2055,8 @@ redef class MMethodDef else if node isa AClassdef then # Automatic free init is always inlined since it is empty or contains only attribtes assigments return true + else if node == null then + return true else abort end @@ -2487,9 +2512,22 @@ redef class AMethPropdef else if pname == "fast_cstring" then v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null))) return true + else if pname == "==" then + v.ret(v.equal_test(arguments[0], arguments[1])) + return true + else if pname == "!=" then + var res = v.equal_test(arguments[0], arguments[1]) + 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))) 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))) + return true + else if pname == "fetch_4_hchars" then + v.ret(v.new_expr("(long)be32toh(*((uint32_t*)({arguments[0]} + {arguments[1]})))", ret.as(not null))) + return true end else if cname == "NativeArray" then return v.native_array_def(pname, ret, arguments) @@ -3067,7 +3105,18 @@ redef class AAttrPropdef v.assign(v.frame.returnvar.as(not null), res) else if mpropdef == mwritepropdef then assert arguments.length == 2 - v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1]) + var recv = arguments.first + var arg = arguments[1] + if is_optional and v.maybenull(arg) then + var value = v.new_var(self.mpropdef.static_mtype.as(not null)) + v.add("if ({arg} == NULL) \{") + v.assign(value, evaluate_expr(v, recv)) + v.add("\} else \{") + v.assign(value, arg) + v.add("\}") + arg = value + end + v.write_attribute(self.mpropdef.mproperty, arguments.first, arg) if is_lazy then var ret = self.mtype var useiset = not ret.is_c_primitive and not ret isa MNullableType @@ -3142,8 +3191,7 @@ end redef class AClassdef private fun compile_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) do - if mpropdef == self.mfree_init then - assert mpropdef.mproperty.is_root_init + if mpropdef.mproperty.is_root_init then assert arguments.length == 1 if not mpropdef.is_intro then v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments) @@ -3481,6 +3529,9 @@ redef class AOrElseExpr do var res = v.new_var(self.mtype.as(not null)) var i1 = v.expr(self.n_expr, null) + + if not v.maybenull(i1) then return i1 + v.add("if ({i1}!=NULL) \{") v.assign(res, i1) v.add("\} else \{") @@ -3663,7 +3714,7 @@ redef class AAsNotnullExpr var i = v.expr(self.n_expr, null) if v.compiler.modelbuilder.toolcontext.opt_no_check_assert.value then return i - if i.mtype.is_c_primitive then return i + if not v.maybenull(i) then return i v.add("if (unlikely({i} == NULL)) \{") v.add_abort("Cast failed")