Skip to content

Commit

Permalink
Merge pull request #18382 from JuliaLang/jn/runtime-intrinsics
Browse files Browse the repository at this point in the history
hook up runtime intrinsics
  • Loading branch information
vtjnash authored Sep 7, 2016
2 parents bbda1fe + 8f75347 commit e3d3b3a
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 36 deletions.
6 changes: 5 additions & 1 deletion base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ end
function show(io::IO, ::MIME"text/plain", f::Function)
ft = typeof(f)
mt = ft.name.mt
if isa(f, Core.Builtin)
if isa(f, Core.IntrinsicFunction)
show(io, f)
id = Core.Intrinsics.box(Int32, f)
print(io, " (intrinsic function #$id)")
elseif isa(f, Core.Builtin)
print(io, mt.name, " (built-in function)")
else
name = mt.name
Expand Down
3 changes: 2 additions & 1 deletion base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ function show(io::IO, f::Function)
end

function show(io::IO, x::Core.IntrinsicFunction)
print(io, "(intrinsic function #", box(Int32, unbox(Core.IntrinsicFunction, x)), ")")
name = ccall(:jl_intrinsic_name, Cstring, (Core.IntrinsicFunction,), x)
print(io, unsafe_string(name))
end

function show(io::IO, x::Union)
Expand Down
2 changes: 1 addition & 1 deletion src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ jl_fptr_t jl_get_builtin_fptr(jl_value_t *b)

static void add_builtin_func(const char *name, jl_fptr_t fptr)
{
add_builtin(name, jl_mk_builtin_func(name, fptr));
jl_mk_builtin_func(NULL, name, fptr);
}

void jl_init_primitives(void)
Expand Down
10 changes: 5 additions & 5 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5616,29 +5616,29 @@ static void init_julia_llvm_env(Module *m)
gcroot_func =
Function::Create(FunctionType::get(T_ppjlvalue, false),
Function::ExternalLinkage,
"julia.gc_root_decl", m);
"julia.gc_root_decl");
add_named_global(gcroot_func, (void*)NULL, /*dllimport*/false);

gckill_func =
Function::Create(FunctionType::get(T_void, ArrayRef<Type*>(T_ppjlvalue), false),
Function::ExternalLinkage,
"julia.gc_root_kill", m);
"julia.gc_root_kill");
add_named_global(gckill_func, (void*)NULL, /*dllimport*/false);

jlcall_frame_func =
Function::Create(FunctionType::get(T_ppjlvalue, ArrayRef<Type*>(T_int32), false),
Function::ExternalLinkage,
"julia.jlcall_frame_decl", m);
"julia.jlcall_frame_decl");
add_named_global(jlcall_frame_func, (void*)NULL, /*dllimport*/false);

gcroot_flush_func = Function::Create(FunctionType::get(T_void, false),
Function::ExternalLinkage,
"julia.gcroot_flush", m);
"julia.gcroot_flush");
add_named_global(gcroot_flush_func, (void*)NULL, /*dllimport*/false);

except_enter_func = Function::Create(FunctionType::get(T_int32, false),
Function::ExternalLinkage,
"julia.except_enter", m);
"julia.except_enter");
except_enter_func->addFnAttr(Attribute::ReturnsTwice);
add_named_global(except_enter_func, (void*)NULL, /*dllimport*/false);

Expand Down
17 changes: 15 additions & 2 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -2050,7 +2050,13 @@ static void jl_save_system_image_to_stream(ios_t *f)
jl_serialize_value(&s, jl_main_module);
jl_serialize_value(&s, jl_top_module);
jl_serialize_value(&s, jl_typeinf_func);

// deserialize method tables of builtin types
jl_serialize_value(&s, jl_type_type->name->mt);
jl_serialize_value(&s, jl_intrinsic_type->name->mt);
jl_serialize_value(&s, jl_sym_type->name->mt);
jl_serialize_value(&s, jl_array_type->name->mt);
jl_serialize_value(&s, jl_module_type->name->mt);

jl_prune_type_cache(jl_tuple_typename->cache);
jl_prune_type_cache(jl_tuple_typename->linearcache);
Expand Down Expand Up @@ -2146,10 +2152,17 @@ static void jl_restore_system_image_from_stream(ios_t *f)
jl_main_module = (jl_module_t*)jl_deserialize_value(&s, NULL);
jl_top_module = (jl_module_t*)jl_deserialize_value(&s, NULL);
jl_internal_main_module = jl_main_module;

jl_typeinf_func = (jl_function_t*)jl_deserialize_value(&s, NULL);
jl_type_type_mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
jl_type_type->name->mt = jl_typector_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt =
jl_type_type_mt;
jl_type_type->name->mt = jl_type_type_mt;
jl_typector_type->name->mt = jl_type_type_mt;
jl_uniontype_type->name->mt = jl_type_type_mt;
jl_datatype_type->name->mt = jl_type_type_mt;
jl_intrinsic_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
jl_sym_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
jl_array_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
jl_module_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);

intptr_t i;
for(i=0; i < builtin_types.len; i++) {
Expand Down
13 changes: 8 additions & 5 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,14 @@ JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t

JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void);
static jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_t *module, jl_datatype_t *st, int iskw);
jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)
void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr)
{
jl_sym_t *sname = jl_symbol(name);
jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type, 0);
if (dt == NULL) {
jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type, 0);
jl_set_const(jl_core_module, sname, f);
dt = (jl_datatype_t*)jl_typeof(f);
}
jl_lambda_info_t *li = jl_new_lambda_info_uninit();
li->fptr = fptr;
li->code = jl_nothing;
Expand All @@ -168,14 +172,13 @@ jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)

li->def = jl_new_method_uninit();
li->def->name = sname;
// li->def->module will be set to jl_core_module by init.c
li->def->module = jl_core_module;
li->def->lambda_template = li;
li->def->sig = jl_anytuple_type;
li->def->tvars = jl_emptysvec;

jl_methtable_t *mt = jl_gf_mtable(f);
jl_methtable_t *mt = dt->name->mt;
jl_typemap_insert(&mt->cache, (jl_value_t*)mt, jl_anytuple_type, jl_emptysvec, NULL, jl_emptysvec, (jl_value_t*)li, 0, &lambda_cache, NULL);
return f;
}

/*
Expand Down
1 change: 1 addition & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ void _julia_init(JL_IMAGE_SEARCH rel)

jl_an_empty_vec_any = (jl_value_t*)jl_alloc_vec_any(0);
jl_init_serializer();
jl_init_intrinsic_properties();

if (!jl_options.image_file) {
jl_core_module = jl_new_module(jl_symbol("Core"));
Expand Down
3 changes: 3 additions & 0 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,13 +923,16 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
f = fptoui_auto;
if (f == fptosi && nargs == 1)
f = fptosi_auto;
if (f == cglobal && nargs == 1)
f = cglobal_auto;
unsigned expected_nargs = intrinsic_nargs[f];
if (expected_nargs && expected_nargs != nargs) {
jl_errorf("intrinsic #%d %s: wrong number of arguments", f, JL_I::jl_intrinsic_name((int)f));
}

switch (f) {
case ccall: return emit_ccall(args, nargs, ctx);
case cglobal_auto:
case cglobal: return emit_cglobal(args, nargs, ctx);
case llvmcall: return emit_llvmcall(args, nargs, ctx);
case arraylen:
Expand Down
52 changes: 35 additions & 17 deletions src/intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,14 @@
ADD_I(pointerset, 4) \
/* c interface */ \
ALIAS(ccall, ccall) \
ALIAS(cglobal, cglobal) \
ADD_I(cglobal, 2) \
ALIAS(llvmcall, llvmcall) \
/* object access */ \
ADD_I(arraylen, 1) \
/* hidden intrinsics */ \
ADD_HIDDEN(fptoui_auto, 1) \
ADD_HIDDEN(fptosi_auto, 1)
ADD_HIDDEN(fptosi_auto, 1) \
ADD_HIDDEN(cglobal_auto, 1)

enum intrinsic {
#define ADD_I(func, nargs) func,
Expand All @@ -124,7 +125,7 @@ enum intrinsic {
#ifdef __cplusplus
extern "C"
#endif
const char *jl_intrinsic_name(int f)
JL_DLLEXPORT const char *jl_intrinsic_name(int f)
{
switch ((enum intrinsic)f) {
default: return "invalid";
Expand Down Expand Up @@ -152,21 +153,25 @@ extern "C"
JL_CALLABLE(jl_f_intrinsic_call)
{
JL_NARGSV(intrinsic_call, 1);
JL_TYPECHK(intrinsic_call, intrinsic, args[0]);
enum intrinsic f = (enum intrinsic)*(uint32_t*)jl_data_ptr(args[0]);
JL_TYPECHK(intrinsic_call, intrinsic, F);
enum intrinsic f = (enum intrinsic)*(uint32_t*)jl_data_ptr(F);
if (f == fptoui && nargs == 1)
f = fptoui_auto;
if (f == fptosi && nargs == 1)
f = fptosi_auto;
if (f == cglobal && nargs == 1)
f = cglobal_auto;
unsigned fargs = intrinsic_nargs[f];
JL_NARGS(intrinsic_call, 1 + fargs, 1 + fargs);
if (!fargs)
jl_error("this intrinsic must be compiled to be called");
JL_NARGS(intrinsic_call, fargs, fargs);
switch (fargs) {
case 1:
return ((intrinsic_call_1_arg)runtime_fp[f])(args[1]);
return ((intrinsic_call_1_arg)runtime_fp[f])(args[0]);
case 2:
return ((intrinsic_call_2_arg)runtime_fp[f])(args[1], args[2]);
return ((intrinsic_call_2_arg)runtime_fp[f])(args[0], args[1]);
case 3:
return ((intrinsic_call_3_arg)runtime_fp[f])(args[1], args[2], args[3]);
return ((intrinsic_call_3_arg)runtime_fp[f])(args[0], args[1], args[2]);
default:
assert(0 && "unexpected number of arguments to an intrinsic function");
}
Expand All @@ -191,21 +196,34 @@ static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f)
#ifdef __cplusplus
extern "C"
#endif
void jl_init_intrinsic_functions()
void jl_init_intrinsic_properties(void)
{
#define ADD_I(name, nargs) add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
#define ADD_HIDDEN ADD_I
#define ALIAS(alias, base) add_intrinsic_properties(alias, intrinsic_nargs[base], runtime_fp[base]);
ADD_HIDDEN(reinterpret, 2);
INTRINSICS
#undef ADD_I
#undef ADD_HIDDEN
#undef ALIAS

}

#ifdef __cplusplus
extern "C"
#endif
void jl_init_intrinsic_functions(void)
{
jl_module_t *inm = jl_new_module(jl_symbol("Intrinsics"));
inm->parent = jl_core_module;
jl_set_const(jl_core_module, jl_symbol("Intrinsics"), (jl_value_t*)inm);
jl_mk_builtin_func(jl_intrinsic_type, "IntrinsicFunction", jl_f_intrinsic_call);

#define ADD_I(name, nargs) add_intrinsic(inm, #name, name); add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
#define ADD_HIDDEN(name, nargs) add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
#define ALIAS(alias, base) add_intrinsic(inm, #alias, alias); add_intrinsic_properties(alias, intrinsic_nargs[base], runtime_fp[base]);
ADD_HIDDEN(reinterpret, 2);
#define ADD_I(name, nargs) add_intrinsic(inm, #name, name);
#define ADD_HIDDEN(name, nargs)
#define ALIAS ADD_I
INTRINSICS
#undef ADD_I
#undef ADD_HIDDEN
#undef ALIAS

jl_set_const(inm, jl_symbol("intrinsic_call"),
jl_mk_builtin_func("intrinsic_call", jl_f_intrinsic_call));
}
2 changes: 1 addition & 1 deletion src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3948,7 +3948,7 @@ void jl_init_types(void)
jl_type_type->name->mt;

jl_intrinsic_type = jl_new_bitstype((jl_value_t*)jl_symbol("IntrinsicFunction"),
jl_any_type, jl_emptysvec, 32);
jl_builtin_type, jl_emptysvec, 32);

tv = jl_svec1(tvar("T"));
jl_ref_type =
Expand Down
7 changes: 5 additions & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv);
jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np);
jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p);
void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype);
jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr);
void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr);
STATIC_INLINE int jl_is_type(jl_value_t *v)
{
jl_value_t *t = jl_typeof(v);
Expand Down Expand Up @@ -335,6 +335,7 @@ void jl_init_frontend(void);
void jl_init_primitives(void);
void jl_init_codegen(void);
void jl_init_intrinsic_functions(void);
void jl_init_intrinsic_properties(void);
void jl_init_tasks(void);
void jl_init_stack_limits(int ismaster);
void jl_init_root_task(void *stack, size_t ssize);
Expand Down Expand Up @@ -527,11 +528,13 @@ extern JL_DLLEXPORT jl_value_t *jl_segv_exception;
#endif

// -- Runtime intrinsics -- //
const char *jl_intrinsic_name(int f);
JL_DLLEXPORT const char *jl_intrinsic_name(int f);

JL_DLLEXPORT jl_value_t *jl_reinterpret(jl_value_t *ty, jl_value_t *v);
JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t *align);
JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *align, jl_value_t *i);
JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty);
JL_DLLEXPORT jl_value_t *jl_cglobal_auto(jl_value_t *v);

JL_DLLEXPORT jl_value_t *jl_neg_int(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_add_int(jl_value_t *a, jl_value_t *b);
Expand Down
54 changes: 53 additions & 1 deletion src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file is a part of Julia. License is MIT: http://julialang.org/license

// This is in implementation of the Julia intrinsic functions against boxed types
// excluding the c interface (ccall, cglobal, llvmcall)
// excluding the native function call interface (ccall, llvmcall)
//
// this file assumes a little-endian processor, although that isn't too hard to fix
// it also assumes two's complement negative numbers, which might be a bit harder to fix
Expand Down Expand Up @@ -76,6 +76,58 @@ JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t
return p;
}

JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
{
JL_TYPECHK(cglobal, type, ty);
jl_value_t *rt =
v == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case
(jl_value_t*)jl_apply_type_((jl_value_t*)jl_pointer_type, &ty, 1);

if (!jl_is_leaf_type(rt))
jl_error("cglobal: type argument not a leaftype");

if (jl_is_tuple(v) && jl_nfields(v) == 1)
v = jl_fieldref(v, 0);

if (jl_is_pointer(v))
return jl_reinterpret(rt, v);

char *f_lib = NULL;
if (jl_is_tuple(v) && jl_nfields(v) > 1) {
jl_value_t *t1 = jl_fieldref(v, 1);
v = jl_fieldref(v, 0);
if (jl_is_symbol(t1))
f_lib = jl_symbol_name((jl_sym_t*)t1);
else if (jl_is_string(t1))
f_lib = jl_string_data(t1);
else
JL_TYPECHK(cglobal, symbol, t1)
}

char *f_name = NULL;
if (jl_is_symbol(v))
f_name = jl_symbol_name((jl_sym_t*)v);
else if (jl_is_string(v))
f_name = jl_string_data(v);
else
JL_TYPECHK(cglobal, symbol, v)

#ifdef _OS_WINDOWS_
if (!f_lib)
f_lib = jl_dlfind_win32(f_name);
#endif

void *ptr = jl_dlsym(jl_get_library(f_lib), f_name);
jl_value_t *jv = jl_gc_alloc_1w();
jl_set_typeof(jv, rt);
*(void**)jl_data_ptr(jv) = ptr;
return jv;
}

JL_DLLEXPORT jl_value_t *jl_cglobal_auto(jl_value_t *v) {
return jl_cglobal(v, (jl_value_t*)jl_void_type);
}

static inline char signbitbyte(void *a, unsigned bytes)
{
// sign bit of an signed number of n bytes, as a byte
Expand Down
7 changes: 7 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,13 @@ glotest()
@test glob_x == 88
@test loc_x == 10

# runtime intrinsics

let f = Any[Core.Intrinsics.add_int, Core.Intrinsics.sub_int]
@test f[1](1, 1) == 2
@test f[2](1, 1) == 0
end

# issue #7234
begin
glob_x2 = 24
Expand Down

0 comments on commit e3d3b3a

Please sign in to comment.