diff --git a/base/reflection.jl b/base/reflection.jl index 4a1b5aa0b245f..6ab945b66a619 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -724,41 +724,27 @@ function method_instances(@nospecialize(f), @nospecialize(t), world::UInt = type return results end -# this type mirrors jl_cghooks_t (documented in julia.h) -struct CodegenHooks - module_setup::Ptr{Void} - module_activation::Ptr{Void} - raise_exception::Ptr{Void} - - CodegenHooks(;module_setup=nothing, module_activation=nothing, raise_exception=nothing) = - new(pointer_from_objref(module_setup), - pointer_from_objref(module_activation), - pointer_from_objref(raise_exception)) -end - # this type mirrors jl_cgparams_t (documented in julia.h) struct CodegenParams cached::Cint - runtime::Cint - exceptions::Cint track_allocations::Cint code_coverage::Cint static_alloc::Cint - dynamic_alloc::Cint + prefer_specsig::Cint - hooks::CodegenHooks + module_setup::Any + module_activation::Any + raise_exception::Any CodegenParams(;cached::Bool=true, - runtime::Bool=true, exceptions::Bool=true, track_allocations::Bool=true, code_coverage::Bool=true, - static_alloc::Bool=true, dynamic_alloc::Bool=true, - hooks::CodegenHooks=CodegenHooks()) = + static_alloc::Bool=true, prefer_specsig::Bool=false, + module_setup=nothing, module_activation=nothing, raise_exception=nothing) = new(Cint(cached), - Cint(runtime), Cint(exceptions), Cint(track_allocations), Cint(code_coverage), - Cint(static_alloc), Cint(dynamic_alloc), - hooks) + Cint(static_alloc), Cint(prefer_specsig), + module_setup, module_activation, raise_exception) end # Printing code representations in IR and assembly diff --git a/src/ccall.cpp b/src/ccall.cpp index 7512f24f0648b..816100bff957a 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1513,12 +1513,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) rt = (jl_value_t*)jl_any_type; // convert return type to jl_value_t* } - // check if we require the runtime - // TODO: could be more fine-grained, - // respecting special functions below that don't require the runtime - if (!llvmcall && (!f_lib || f_lib == JL_DL_LIBNAME)) - JL_FEAT_REQUIRE(ctx, runtime); - // some sanity checking and check whether there's a vararg bool isVa; size_t nargt; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 6dbb982e7223e..a5d8e4c58e518 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -97,22 +97,15 @@ static Value *mark_callee_rooted(IRBuilder<> &irbuilder, Value *V) // --- language feature checks --- -// branch on whether a language feature is enabled or not #define JL_FEAT_TEST(ctx, feature) ((ctx).params->feature) -// require a language feature to be enabled -#define JL_FEAT_REQUIRE(ctx, feature) \ - if (!JL_FEAT_TEST(ctx, feature)) \ - jl_errorf("%s for %s:%d requires the " #feature " language feature, which is disabled", \ - __FUNCTION__, (ctx).file.str().c_str(), *(ctx).line); - // --- hook checks --- -#define JL_HOOK_TEST(params,hook) ((params)->hooks.hook != jl_nothing) +#define JL_HOOK_TEST(params,hook) ((params)->hook != jl_nothing) #define JL_HOOK_CALL(params,hook,argc,...) \ - _hook_call((params)->hooks.hook, {{__VA_ARGS__}}); + _hook_call((params)->hook, {{__VA_ARGS__}}); template static inline void _hook_call(jl_value_t *hook, std::array args) { jl_value_t **argv; @@ -907,7 +900,6 @@ static void raise_exception(jl_codectx_t &ctx, Value *exc, jl_box_voidpointer(wrap(ctx.builder.GetInsertBlock())), jl_box_voidpointer(wrap(exc))); } else { - JL_FEAT_REQUIRE(ctx, runtime); ctx.builder.CreateCall(prepare_call(jlthrow_func), { mark_callee_rooted(exc) }); } ctx.builder.CreateUnreachable(); @@ -2116,8 +2108,6 @@ static void emit_cpointercheck(jl_codectx_t &ctx, const jl_cgval_t &x, const std // allocation for known size object static Value *emit_allocobj(jl_codectx_t &ctx, size_t static_size, Value *jt) { - JL_FEAT_REQUIRE(ctx, dynamic_alloc); - JL_FEAT_REQUIRE(ctx, runtime); Value *ptls_ptr = emit_bitcast(ctx, ctx.ptlsStates, T_pint8); auto call = ctx.builder.CreateCall(prepare_call(jl_alloc_obj_func), {ptls_ptr, ConstantInt::get(T_size, static_size), @@ -2348,14 +2338,12 @@ static int compare_cgparams(const jl_cgparams_t *a, const jl_cgparams_t *b) { return (a->cached == b->cached) && // language features - (a->runtime == b->runtime) && - (a->exceptions == b->exceptions) && (a->track_allocations == b->track_allocations) && (a->code_coverage == b->code_coverage) && (a->static_alloc == b->static_alloc) && - (a->dynamic_alloc == b->dynamic_alloc) && + (a->prefer_specsig == b->prefer_specsig) && // hooks - (a->hooks.module_setup == b->hooks.module_setup) && - (a->hooks.module_activation == b->hooks.module_activation) && - (a->hooks.raise_exception == b->hooks.raise_exception); + (a->module_setup == b->module_setup) && + (a->module_activation == b->module_activation) && + (a->raise_exception == b->raise_exception); } diff --git a/src/codegen.cpp b/src/codegen.cpp index ba9e7aa12b192..f4b9e6a5fe164 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2204,7 +2204,6 @@ static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgva decay_derived(varg2)); } - JL_FEAT_REQUIRE(ctx, runtime); Value *varg1 = mark_callee_rooted(boxed(ctx, arg1)); Value *varg2 = mark_callee_rooted(boxed(ctx, arg2)); return ctx.builder.CreateTrunc(ctx.builder.CreateCall(prepare_call(jlegal_func), {varg1, varg2}), T_int1); @@ -2249,7 +2248,6 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, if (jl_subtype(ty.typ, (jl_value_t*)jl_type_type)) { Value *rt_arg = boxed(ctx, arg); Value *rt_ty = boxed(ctx, ty); - JL_FEAT_REQUIRE(ctx, runtime); ctx.builder.CreateCall(prepare_call(jltypeassert_func), {rt_arg, rt_ty}); *ret = arg; return true; @@ -2290,7 +2288,6 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, nva = ctx.builder.CreateTrunc(nva, T_int32); #endif Value *theArgs = ctx.builder.CreateGEP(ctx.argArray, ConstantInt::get(T_size, ctx.nReqArgs)); - JL_FEAT_REQUIRE(ctx, runtime); Value *r = ctx.builder.CreateCall(prepare_call(jlapply2va_func), { theF, theArgs, nva }); *ret = mark_julia_type(ctx, r, true, jl_any_type); return true; @@ -2955,7 +2952,6 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex) } } } - JL_FEAT_REQUIRE(ctx, runtime); jl_cgval_t result = mark_julia_type(ctx, emit_jlcall( ctx, @@ -3007,16 +3003,6 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex) } } - if (!JL_FEAT_TEST(ctx, runtime)) { - char* name = NULL; - if (jl_is_symbol(args[0])) - name = jl_symbol_name((jl_sym_t*)args[0]); - if (jl_is_globalref(args[0])) - name = jl_symbol_name(jl_globalref_name(args[0])); - jl_errorf("generic call to %s requires the runtime language feature", - name ? name : ""); - } - // emit function and arguments Value *callval = emit_jlcall(ctx, jlapplygeneric_func, nullptr, argv, nargs); return mark_julia_type(ctx, callval, true, rt); @@ -3059,7 +3045,6 @@ static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t b = jl_get_binding(m, s); if (b == NULL) { // var not found. switch to delayed lookup. - JL_FEAT_REQUIRE(ctx, runtime); std::stringstream name; name << "delayedvar" << globalUnique++; Constant *initnul = V_null; @@ -3417,7 +3402,6 @@ static void emit_assignment(jl_codectx_t &ctx, jl_value_t *l, jl_value_t *r) if (bp == NULL && s != NULL) bp = global_binding_pointer(ctx, ctx.module, s, &bnd, true); if (bp != NULL) { // it's a global - JL_FEAT_REQUIRE(ctx, runtime); assert(bnd); Value *rval = mark_callee_rooted(boxed(ctx, emit_expr(ctx, r))); ctx.builder.CreateCall(prepare_call(jlcheckassign_func), @@ -3623,7 +3607,6 @@ static void emit_stmtpos(jl_codectx_t &ctx, jl_value_t *expr) } else if (head == leave_sym) { assert(jl_is_long(args[0])); - JL_FEAT_REQUIRE(ctx, runtime); ctx.builder.CreateCall(prepare_call(jlleave_func), ConstantInt::get(T_int32, jl_unbox_long(args[0]))); } @@ -3733,7 +3716,6 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr) else if (head == method_sym) { jl_value_t *mn = args[0]; assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(mn) || jl_is_slot(mn)); - JL_FEAT_REQUIRE(ctx, runtime); Value *bp = NULL, *name, *bp_owner = V_null; jl_binding_t *bnd = NULL; @@ -3800,7 +3782,6 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr) sym = jl_globalref_name(sym); } if (jl_is_symbol(sym)) { - JL_FEAT_REQUIRE(ctx, runtime); jl_binding_t *bnd = NULL; (void)global_binding_pointer(ctx, mod, sym, &bnd, true); assert(bnd); ctx.builder.CreateCall(prepare_call(jldeclareconst_func), @@ -3830,7 +3811,6 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr) true, jl_any_type); } else if (head == copyast_sym) { - JL_FEAT_REQUIRE(ctx, runtime); jl_value_t *arg = args[0]; if (jl_is_quotenode(arg)) { jl_value_t *arg1 = jl_fieldref(arg, 0); @@ -3868,7 +3848,6 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr) jl_error("syntax: prefix \"$\" in non-quoted expression"); if (jl_is_toplevel_only_expr(expr) && !jl_is_method(ctx.linfo->def.method)) { - JL_FEAT_REQUIRE(ctx, runtime); // call interpreter to run a toplevel expr from inside a // compiled toplevel thunk. Value *args[2] = { @@ -4563,7 +4542,7 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returnin return w; } -static bool uses_specsig(jl_value_t *sig, jl_value_t *rettype, bool needsparam, bool va, jl_code_info_t *src) +static bool uses_specsig(jl_value_t *sig, jl_value_t *rettype, bool needsparam, bool va, jl_code_info_t *src, bool prefer_specsig) { if (va || needsparam) return false; @@ -4576,6 +4555,8 @@ static bool uses_specsig(jl_value_t *sig, jl_value_t *rettype, bool needsparam, if (jl_nparams(sig) == 0) return false; // not invalid, consider if specialized signature is worthwhile + if (prefer_specsig) + return true; if (isbits_spec(rettype, false)) return true; if (jl_is_uniontype(rettype)) { @@ -4829,7 +4810,7 @@ static std::unique_ptr emit_function( } jl_value_t *jlrettype = lam->rettype; - bool specsig = uses_specsig(lam->specTypes, jlrettype, needsparams, va, src); + bool specsig = uses_specsig(lam->specTypes, jlrettype, needsparams, va, src, params->prefer_specsig); if (!specsig) ctx.nReqArgs--; // function not part of argArray in jlcall diff --git a/src/jltypes.c b/src/jltypes.c index 0cf4b69ff82fb..95b215913711e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -127,7 +127,7 @@ jl_value_t *jl_memory_exception; jl_value_t *jl_readonlymemory_exception; union jl_typemap_t jl_cfunction_list; -jl_cgparams_t jl_default_cgparams = {1, 1, 1, 1, 1, 1, 1, {NULL, NULL, NULL}}; +jl_cgparams_t jl_default_cgparams = {1, 1, 1, 1, 0, NULL, NULL, NULL}; // --- type properties and predicates --- @@ -1663,9 +1663,9 @@ void jl_init_types(void) jl_methtable_type = jl_new_uninitialized_datatype(); jl_nothing = jl_gc_permobj(0, NULL); - jl_default_cgparams.hooks.module_setup = jl_nothing; - jl_default_cgparams.hooks.module_activation = jl_nothing; - jl_default_cgparams.hooks.raise_exception = jl_nothing; + jl_default_cgparams.module_setup = jl_nothing; + jl_default_cgparams.module_activation = jl_nothing; + jl_default_cgparams.raise_exception = jl_nothing; jl_emptysvec = (jl_svec_t*)jl_gc_permobj(sizeof(void*), jl_simplevector_type); jl_svec_set_len_unsafe(jl_emptysvec, 0); diff --git a/src/julia.h b/src/julia.h index 32bf56c0d9c25..23e00ceb9c1af 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1806,7 +1806,15 @@ typedef struct { // codegen interface ---------------------------------------------------------- typedef struct { - // to disable a hook: set to NULL or nothing + int cached; // can the compiler use/populate the compilation cache? + + int track_allocations; // can we track allocations? + int code_coverage; // can we measure coverage? + int static_alloc; // is the compiler allowed to allocate statically? + int prefer_specsig; // are specialized function signatures preferred? + + + // hooks // module setup: prepare a module for code emission (data layout, DWARF version, ...) // parameters: LLVMModuleRef as Ptr{Void} @@ -1822,20 +1830,6 @@ typedef struct { // parameters: LLVMBasicBlockRef as Ptr{Void}, LLVMValueRef as Ptr{Void} // return value: none jl_value_t *raise_exception; -} jl_cghooks_t; - -typedef struct { - int cached; // can the compiler use/populate the compilation cache? - - // language features (C-style integer booleans) - int runtime; // can we call into the runtime? - int exceptions; // are exceptions supported (requires runtime)? - int track_allocations; // can we track allocations (don't if disallowed)? - int code_coverage; // can we measure coverage (don't if disallowed)? - int static_alloc; // is the compiler allowed to allocate statically? - int dynamic_alloc; // is the compiler allowed to allocate dynamically (requires runtime)? - - jl_cghooks_t hooks; } jl_cgparams_t; extern JL_DLLEXPORT jl_cgparams_t jl_default_cgparams;