Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ void *jl_emit_native_impl(jl_array_t *codeinfos, LLVMOrcThreadSafeModuleRef llvm
else {
jl_value_t *sig = jl_array_ptr_ref(codeinfos, ++i);
assert(jl_is_type(item) && jl_is_type(sig));
jl_compile_extern_c(wrap(&clone), &params, NULL, item, sig);
jl_generate_ccallable(clone.getModuleUnlocked(), nullptr, item, sig, params);
}
}
// finally, make sure all referenced methods get fixed up, particularly if the user declined to compile them
Expand Down
1 change: 0 additions & 1 deletion src/codegen-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ JL_DLLEXPORT void jl_get_llvm_gvs_fallback(void *native_code, arraylist_t *gvs)
JL_DLLEXPORT void jl_get_llvm_external_fns_fallback(void *native_code, arraylist_t *gvs) UNAVAILABLE
JL_DLLEXPORT void jl_get_llvm_mis_fallback(void *native_code, arraylist_t* MIs) UNAVAILABLE

JL_DLLEXPORT void jl_extern_c_fallback(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE
JL_DLLEXPORT jl_value_t *jl_dump_method_asm_fallback(jl_method_instance_t *linfo, size_t world,
char emit_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary) UNAVAILABLE
JL_DLLEXPORT jl_value_t *jl_dump_function_ir_fallback(jl_llvmf_dump_t *dump, char strip_ir_metadata, char dump_module, const char *debuginfo) UNAVAILABLE
Expand Down
38 changes: 38 additions & 0 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4585,6 +4585,44 @@ JL_DLLEXPORT void jl_typeinf_timing_end(uint64_t start, int is_recompile)
}
}

// declare a C-callable entry point; called during code loading from the toplevel
JL_DLLEXPORT void jl_extern_c(jl_value_t *declrt, jl_tupletype_t *sigt)
{
// validate arguments. try to do as many checks as possible here to avoid
// throwing errors later during codegen.
JL_TYPECHK(@ccallable, type, declrt);
if (!jl_is_tuple_type(sigt))
jl_type_error("@ccallable", (jl_value_t*)jl_anytuple_type_type, (jl_value_t*)sigt);
// check that f is a guaranteed singleton type
jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt);
if (!jl_is_datatype(ft) || !jl_is_datatype_singleton(ft))
jl_error("@ccallable: function object must be a singleton");

// compute / validate return type
if (!jl_is_concrete_type(declrt) || jl_is_kind(declrt))
jl_error("@ccallable: return type must be concrete and correspond to a C type");
if (!jl_type_mappable_to_c(declrt))
jl_error("@ccallable: return type doesn't correspond to a C type");

// validate method signature
size_t i, nargs = jl_nparams(sigt);
for (i = 1; i < nargs; i++) {
jl_value_t *ati = jl_tparam(sigt, i);
if (!jl_is_concrete_type(ati) || jl_is_kind(ati) || !jl_type_mappable_to_c(ati))
jl_error("@ccallable: argument types must be concrete");
}

// save a record of this so that the alias is generated when we write an object file
jl_method_t *meth = (jl_method_t*)jl_methtable_lookup(ft->name->mt, (jl_value_t*)sigt, jl_atomic_load_acquire(&jl_world_counter));
if (!jl_is_method(meth))
jl_error("@ccallable: could not find requested method");
JL_GC_PUSH1(&meth);
meth->ccallable = jl_svec2(declrt, (jl_value_t*)sigt);
jl_gc_wb(meth, meth->ccallable);
JL_GC_POP();
}


#ifdef __cplusplus
}
#endif
134 changes: 0 additions & 134 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,140 +805,6 @@ void jl_emit_codeinst_to_jit_impl(
}


const char *jl_generate_ccallable(Module *llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t &params);

// compile a C-callable alias
extern "C" JL_DLLEXPORT_CODEGEN
int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *sysimg, jl_value_t *declrt, jl_value_t *sigt)
{
auto ct = jl_current_task;
bool timed = (ct->reentrant_timing & 1) == 0;
if (timed)
ct->reentrant_timing |= 1;
uint64_t compiler_start_time = 0;
uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
if (measure_compile_time_enabled)
compiler_start_time = jl_hrtime();
jl_codegen_params_t *pparams = (jl_codegen_params_t*)p;
DataLayout DL = pparams ? pparams->DL : jl_ExecutionEngine->getDataLayout();
Triple TargetTriple = pparams ? pparams->TargetTriple : jl_ExecutionEngine->getTargetTriple();
orc::ThreadSafeContext ctx;
auto into = unwrap(llvmmod);
orc::ThreadSafeModule backing;
bool success = true;
const char *name = "";
if (into == NULL) {
ctx = pparams ? pparams->tsctx : jl_ExecutionEngine->makeContext();
backing = jl_create_ts_module("cextern", ctx, DL, TargetTriple);
into = &backing;
}
{ // params scope
jl_codegen_params_t params(into->getContext(), DL, TargetTriple);
if (pparams == NULL) {
params.cache = p == NULL;
params.imaging_mode = 0;
params.tsctx.getContext()->setDiscardValueNames(true);
pparams = &params;
}
Module &M = *into->getModuleUnlocked();
assert(pparams->tsctx.getContext() == &M.getContext());
name = jl_generate_ccallable(&M, sysimg, declrt, sigt, *pparams);
if (!sysimg && !p) {
{ // drop lock to keep analyzer happy (since it doesn't know we have the only reference to it)
auto release = std::move(params.tsctx_lock);
}
{ // lock scope
jl_unique_gcsafe_lock lock(extern_c_lock);
if (jl_ExecutionEngine->getGlobalValueAddress(name))
success = false;
}
params.tsctx_lock = params.tsctx.getLock(); // re-acquire lock
if (success && params.cache) {
size_t newest_world = jl_atomic_load_acquire(&jl_world_counter);
for (auto &it : params.workqueue) { // really just zero or one, and just the ABI not the rest of the metadata
jl_code_instance_t *codeinst = it.first;
JL_GC_PROMISE_ROOTED(codeinst);
jl_code_instance_t *newest_ci = jl_type_infer(jl_get_ci_mi(codeinst), newest_world, SOURCE_MODE_ABI);
if (newest_ci) {
if (jl_egal(codeinst->rettype, newest_ci->rettype))
it.first = codeinst;
jl_compile_codeinst_now(newest_ci);
}
}
jl_analyze_workqueue(nullptr, params, true);
assert(params.workqueue.empty());
finish_params(&M, params, sharedmodules);
}
}
pparams = nullptr;
}
if (!sysimg && success && llvmmod == NULL) {
{ // lock scope
jl_unique_gcsafe_lock lock(extern_c_lock);
if (!jl_ExecutionEngine->getGlobalValueAddress(name)) {
{
auto Lock = backing.getContext().getLock();
jl_ExecutionEngine->optimizeDLSyms(*backing.getModuleUnlocked()); // safepoint
}
jl_ExecutionEngine->addModule(std::move(backing));
success = jl_ExecutionEngine->getGlobalValueAddress(name);
assert(success);
}
}
}
if (timed) {
if (measure_compile_time_enabled) {
auto end = jl_hrtime();
jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, end - compiler_start_time);
}
ct->reentrant_timing &= ~1ull;
}
return success;
}

// declare a C-callable entry point; called during code loading from the toplevel
extern "C" JL_DLLEXPORT_CODEGEN
void jl_extern_c_impl(jl_value_t *declrt, jl_tupletype_t *sigt)
{
// validate arguments. try to do as many checks as possible here to avoid
// throwing errors later during codegen.
JL_TYPECHK(@ccallable, type, declrt);
if (!jl_is_tuple_type(sigt))
jl_type_error("@ccallable", (jl_value_t*)jl_anytuple_type_type, (jl_value_t*)sigt);
// check that f is a guaranteed singleton type
jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt);
if (!jl_is_datatype(ft) || !jl_is_datatype_singleton(ft))
jl_error("@ccallable: function object must be a singleton");

// compute / validate return type
if (!jl_is_concrete_type(declrt) || jl_is_kind(declrt))
jl_error("@ccallable: return type must be concrete and correspond to a C type");
if (!jl_type_mappable_to_c(declrt))
jl_error("@ccallable: return type doesn't correspond to a C type");

// validate method signature
size_t i, nargs = jl_nparams(sigt);
for (i = 1; i < nargs; i++) {
jl_value_t *ati = jl_tparam(sigt, i);
if (!jl_is_concrete_type(ati) || jl_is_kind(ati) || !jl_type_mappable_to_c(ati))
jl_error("@ccallable: argument types must be concrete");
}

// save a record of this so that the alias is generated when we write an object file
jl_method_t *meth = (jl_method_t*)jl_methtable_lookup(ft->name->mt, (jl_value_t*)sigt, jl_atomic_load_acquire(&jl_world_counter));
if (!jl_is_method(meth))
jl_error("@ccallable: could not find requested method");
JL_GC_PUSH1(&meth);
meth->ccallable = jl_svec2(declrt, (jl_value_t*)sigt);
jl_gc_wb(meth, meth->ccallable);
JL_GC_POP();

// create the alias in the current runtime environment
int success = jl_compile_extern_c(NULL, NULL, NULL, declrt, (jl_value_t*)sigt);
if (!success)
jl_error("@ccallable was already defined for this method name");
}

extern "C" JL_DLLEXPORT_CODEGEN
int jl_compile_codeinst_impl(jl_code_instance_t *ci)
{
Expand Down
2 changes: 2 additions & 0 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ struct jl_codegen_params_t {
~jl_codegen_params_t() JL_NOTSAFEPOINT JL_NOTSAFEPOINT_LEAVE = default;
};

const char *jl_generate_ccallable(Module *llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t &params);

jl_llvm_functions_t jl_emit_code(
orc::ThreadSafeModule &M,
jl_method_instance_t *mi,
Expand Down
2 changes: 0 additions & 2 deletions src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,6 @@
YY(jl_dump_function_ir) \
YY(jl_dump_method_asm) \
YY(jl_emit_codeinst_to_jit) \
YY(jl_extern_c) \
YY(jl_get_llvmf_defn) \
YY(jl_get_llvm_function) \
YY(jl_get_llvm_module) \
Expand All @@ -532,7 +531,6 @@
YY(jl_register_fptrs) \
YY(jl_generate_fptr_for_unspecialized) \
YY(jl_compile_codeinst) \
YY(jl_compile_extern_c) \
YY(jl_teardown_codegen) \
YY(jl_jit_total_bytes) \
YY(jl_create_native) \
Expand Down
1 change: 0 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -2201,7 +2201,6 @@ typedef enum {
// A loaded, but unparsed .ji or .so image file
typedef struct {
jl_image_kind_t kind;
void *handle;
const void *pointers; // jl_image_pointers_t *
const char *data;
size_t size;
Expand Down
1 change: 0 additions & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1991,7 +1991,6 @@ JL_DLLEXPORT uint32_t jl_crc32c(uint32_t crc, const char *buf, size_t len);

JL_DLLIMPORT void jl_generate_fptr_for_unspecialized(jl_code_instance_t *unspec);
JL_DLLIMPORT int jl_compile_codeinst(jl_code_instance_t *unspec);
JL_DLLIMPORT int jl_compile_extern_c(LLVMOrcThreadSafeModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt);
JL_DLLIMPORT void jl_emit_codeinst_to_jit(jl_code_instance_t *codeinst, jl_code_info_t *src);

typedef struct {
Expand Down
Loading