Skip to content

Instantly share code, notes, and snippets.

@tautologico
Created June 10, 2012 18:39
Show Gist options
  • Save tautologico/2906865 to your computer and use it in GitHub Desktop.
Save tautologico/2906865 to your computer and use it in GitHub Desktop.
LLVM code dump for Julia functions (hack)
diff --git a/src/builtin_proto.h b/src/builtin_proto.h
index 96040ec..54e8d3b 100644
--- a/src/builtin_proto.h
+++ b/src/builtin_proto.h
@@ -12,6 +12,7 @@ JL_CALLABLE(jl_f_typeof);
JL_CALLABLE(jl_f_subtype);
JL_CALLABLE(jl_f_isa);
JL_CALLABLE(jl_f_typeassert);
+JL_CALLABLE(jl_f_llvm_dump);
JL_CALLABLE(jl_f_apply);
JL_CALLABLE(jl_f_top_eval);
JL_CALLABLE(jl_f_isbound);
diff --git a/src/builtins.c b/src/builtins.c
index 1d5c628..a108b57 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -194,6 +194,29 @@ JL_CALLABLE(jl_f_typeassert)
return args[0];
}
+JL_CALLABLE(jl_f_llvm_dump)
+{
+ JL_NARGS(llvm_dump, 1, 1);
+ jl_lambda_info_t *li = (jl_lambda_info_t*) args[0];
+
+ printf("*** Name: %s\n", li->name->name);
+
+ if (li == NULL)
+ printf("NULL lambda info\n");
+ else if (li->functionObject == NULL) {
+ printf("NULL functionObject, attempt to compile\n");
+ jl_compile_li(li);
+ if (li->functionObject != NULL)
+ jl_llvm_dump(li);
+ else
+ printf("Still no functionObject\n");
+ }
+ else
+ jl_llvm_dump(li);
+
+ return jl_nothing;
+}
+
static jl_function_t *jl_append_any_func;
JL_CALLABLE(jl_f_apply)
@@ -834,6 +857,7 @@ void jl_init_primitives(void)
add_builtin_func("subtype", jl_f_subtype);
add_builtin_func("isa", jl_f_isa);
add_builtin_func("typeassert", jl_f_typeassert);
+ add_builtin_func("llvm_dump", jl_f_llvm_dump);
add_builtin_func("apply", jl_f_apply);
add_builtin_func("throw", jl_f_throw);
add_builtin_func("tuple", jl_f_tuple);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 932a44d..424a609 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -187,11 +193,18 @@ extern "C" void jl_generate_fptr(jl_function_t *f)
JL_SIGATOMIC_BEGIN();
li->fptr = (jl_fptr_t)jl_ExecutionEngine->getPointerToFunction(llvmf);
JL_SIGATOMIC_END();
- llvmf->deleteBody();
+ //llvmf->deleteBody();
}
f->fptr = li->fptr;
}
+extern "C" void jl_llvm_dump(jl_lambda_info_t *li)
+{
+ assert(li->functionObject);
+ Function *llvmf = (Function*) li->functionObject;
+ llvmf->dump();
+}
+
extern "C" void jl_compile(jl_function_t *f)
{
jl_lambda_info_t *li = f->linfo;
@@ -203,6 +216,16 @@ extern "C" void jl_compile(jl_function_t *f)
}
}
+extern "C" void jl_compile_li(jl_lambda_info_t *li)
+{
+ if (li->functionObject == NULL) {
+ // objective: assign li->functionObject
+ li->inCompile = 1;
+ (void)to_function(li);
+ li->inCompile = 0;
+ }
+}
+
extern "C" void jl_delete_function(jl_lambda_info_t *li)
{
// NOTE: this is not safe; there might be closures using this code.
diff --git a/src/dump.c b/src/dump.c
index a9db4bf..5a4d72b 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -1055,23 +1055,23 @@ void jl_init_serializer(void)
VALUE_TAGS = (ptrint_t)ptrhash_get(&ser_tag, jl_null);
void *fptrs[] = { jl_f_new_expr, jl_f_new_box,
- jl_f_throw, jl_f_is,
- jl_f_no_function, jl_f_typeof,
- jl_f_subtype, jl_f_isa,
- jl_f_typeassert, jl_f_apply,
- jl_f_top_eval, jl_f_isbound,
- jl_f_tuple, jl_f_tupleref,
- jl_f_tuplelen, jl_f_get_field,
- jl_f_set_field, jl_f_field_type,
- jl_f_arraylen, jl_f_arrayref,
- jl_f_arrayset, jl_f_arraysize,
+ jl_f_throw, jl_f_is,
+ jl_f_no_function, jl_f_typeof,
+ jl_f_subtype, jl_f_isa,
+ jl_f_typeassert, jl_f_llvm_dump, jl_f_apply,
+ jl_f_top_eval, jl_f_isbound,
+ jl_f_tuple, jl_f_tupleref,
+ jl_f_tuplelen, jl_f_get_field,
+ jl_f_set_field, jl_f_field_type,
+ jl_f_arraylen, jl_f_arrayref,
+ jl_f_arrayset, jl_f_arraysize,
jl_f_instantiate_type,
jl_f_convert_default, jl_f_convert_tuple,
diff --git a/src/julia.h b/src/julia.h
index db83a8a..33d488b 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -768,7 +768,9 @@ DLLEXPORT void *jl_dlsym(uv_lib_t *handle, char *symbol);
// compiler
void jl_compile(jl_function_t *f);
+void jl_compile_li(jl_lambda_info_t *li);
void jl_generate_fptr(jl_function_t *f);
+void jl_llvm_dump(jl_lambda_info_t *li);
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);
julia> lambda_dump(f1, (Int64,))
*** Name: f1
NULL functionObject, attempt to compile
define %jl_value_t* @f1586(%jl_value_t*, %jl_value_t**, i32) {
top:
%3 = alloca [2 x %jl_value_t*], align 8, !dbg !5328
%4 = alloca %jl_gcframe_t, align 8, !dbg !5328
%.sub = getelementptr inbounds [2 x %jl_value_t*]* %3, i64 0, i64 0
%5 = getelementptr %jl_gcframe_t* %4, i64 0, i32 0, !dbg !5328
%6 = bitcast [2 x %jl_value_t*]* %3 to %jl_value_t***, !dbg !5328
store %jl_value_t*** %6, %jl_value_t**** %5, align 8, !dbg !5328
%7 = getelementptr %jl_gcframe_t* %4, i64 0, i32 1, !dbg !5328
store i64 2, i64* %7, align 8, !dbg !5328
%8 = getelementptr %jl_gcframe_t* %4, i64 0, i32 2, !dbg !5328
store i32 0, i32* %8, align 8, !dbg !5328
%9 = getelementptr %jl_gcframe_t* %4, i64 0, i32 3, !dbg !5328
%10 = load %jl_gcframe_t** @jl_pgcstack, align 8, !dbg !5328
store %jl_gcframe_t* %10, %jl_gcframe_t** %9, align 8, !dbg !5328
store %jl_gcframe_t* %4, %jl_gcframe_t** @jl_pgcstack, align 8, !dbg !5328
store %jl_value_t* null, %jl_value_t** %.sub, align 8, !dbg !5328
%11 = getelementptr [2 x %jl_value_t*]* %3, i64 0, i64 1, !dbg !5328
store %jl_value_t* null, %jl_value_t** %11, align 8, !dbg !5328
%12 = icmp eq i32 %2, 1, !dbg !5328
br i1 %12, label %ifcont, label %else, !dbg !5328
else: ; preds = %top
call void @jl_error(i8* getelementptr inbounds ([33 x i8]* @_j_str646, i64 0, i64 0)), !dbg !5328
unreachable
ifcont: ; preds = %top
%13 = load %jl_value_t** %1, align 8, !dbg !5335
%14 = icmp eq %jl_value_t* %13, null, !dbg !5335
br i1 %14, label %err, label %ok, !dbg !5335
err: ; preds = %ifcont
call void @jl_error(i8* getelementptr inbounds ([21 x i8]* @_j_str647, i64 0, i64 0)), !dbg !5335
unreachable
ok: ; preds = %ifcont
store %jl_value_t* %13, %jl_value_t** %.sub, align 8, !dbg !5335
store %jl_value_t* inttoptr (i64 4328809256 to %jl_value_t*), %jl_value_t** %11, align 8, !dbg !5335
%15 = call %jl_value_t* @jl_apply_generic(%jl_value_t* inttoptr (i64 4331444808 to %jl_value_t*), %jl_value_t** %.sub, i32 2), !dbg !5335
%16 = load %jl_gcframe_t** %9, align 8, !dbg !5335
store %jl_gcframe_t* %16, %jl_gcframe_t** @jl_pgcstack, align 8, !dbg !5335
ret %jl_value_t* %15, !dbg !5335
}
function lambda_dump(f, types)
lambda = getmethods(f, types)[1][3]
# ccall(:jl_dump_lambda_info, Void, (Ptr{Void},), &lambda)
llvm_dump(lambda)
end
f1(x::Int) = x + 55
@StefanKarpinski
Copy link

Ugly hacks that work are infinitely better than beautiful approaches that don't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment