diff --git a/base/util.jl b/base/util.jl index 8a07f708bf80c..c94a02c85c138 100644 --- a/base/util.jl +++ b/base/util.jl @@ -146,6 +146,10 @@ edit(f::Function, t) = edit(function_loc(f,t)...) less(f::Function) = less(function_loc(f)...) less(f::Function, t) = less(function_loc(f,t)...) +function disassemble(f::Function, types) + ccall(:jl_dump_function, Any, (Any,Any), f, types)::ByteString +end + # remote/parallel load include_string(txt::ByteString) = ccall(:jl_load_file_string, Void, (Ptr{Uint8},), txt) diff --git a/src/codegen.cpp b/src/codegen.cpp index 932a44df8d063..b2139e7015037 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -18,6 +18,7 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Support/IRBuilder.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Config/llvm-config.h" #include #include @@ -155,7 +156,8 @@ static Function *to_function(jl_lambda_info_t *li) Function *f = Function::Create(jl_func_sig, Function::ExternalLinkage, li->name->name, jl_Module); assert(!li->inInference); - li->functionObject = (void*)f; + if (li->functionObject == NULL) + li->functionObject = (void*)f; BasicBlock *old = nested_compile ? builder.GetInsertBlock() : NULL; DebugLoc olddl = builder.getCurrentDebugLocation(); bool last_n_c = nested_compile; @@ -203,15 +205,38 @@ extern "C" void jl_compile(jl_function_t *f) } } -extern "C" void jl_delete_function(jl_lambda_info_t *li) +extern "C" jl_function_t *jl_get_specialization(jl_function_t *f, jl_tuple_t *types); + +extern "C" DLLEXPORT +const jl_value_t *jl_dump_function(jl_function_t *f, jl_tuple_t *types) { - // NOTE: this is not safe; there might be closures using this code. - Function *llvmf = (Function*)li->functionObject; - if (llvmf) { - delete llvmf; - li->functionObject = NULL; - li->fptr = &jl_trampoline; + if (!jl_is_function(f) || !jl_is_gf(f)) + return jl_cstr_to_string((char*)""); + jl_function_t *sf = jl_get_specialization(f, types); + if (sf == NULL || sf->linfo == NULL) { + sf = jl_method_lookup_by_type(jl_gf_mtable(f), types, 0); + if (sf == jl_bottom_func) + return jl_cstr_to_string((char*)""); + ios_printf(ios_stderr, + "Warning: Returned code may not match what actually runs.\n"); + } + std::string code; + llvm::raw_string_ostream stream(code); + Function *llvmf; + if (sf->linfo->functionObject == NULL) { + jl_compile(sf); + llvmf = (Function*)sf->linfo->functionObject; + } + else { + if (sf->fptr == &jl_trampoline) { + llvmf = (Function*)sf->linfo->functionObject; + } + else { + llvmf = to_function(sf->linfo); + } } + llvmf->print(stream); + return jl_cstr_to_string((char*)stream.str().c_str()); } // information about the context of a piece of code: its enclosing @@ -503,8 +528,6 @@ static jl_tuple_t *call_arg_types(jl_value_t **args, size_t n, jl_codectx_t *ctx return t; } -extern "C" jl_function_t *jl_get_specialization(jl_function_t *f, jl_tuple_t *types); - static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, jl_codectx_t *ctx, Value **theFptr, Value **theF, diff --git a/src/julia.expmap b/src/julia.expmap index 3a362e6740948..a70417a70b8a7 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -194,6 +194,7 @@ jl_signal_pending; jl_defer_signal; jl_register_toplevel_eh; + jl_dump_function; local: *; }; diff --git a/src/julia.h b/src/julia.h index db83a8a8092ba..ae5837a258a92 100644 --- a/src/julia.h +++ b/src/julia.h @@ -769,7 +769,6 @@ DLLEXPORT void *jl_dlsym(uv_lib_t *handle, char *symbol); // compiler void jl_compile(jl_function_t *f); void jl_generate_fptr(jl_function_t *f); -void jl_delete_function(jl_lambda_info_t *li); DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v); jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e); char *jl_find_file_in_path(const char *fname);