Skip to content

Commit e3d3b3a

Browse files
authored
Merge pull request #18382 from JuliaLang/jn/runtime-intrinsics
hook up runtime intrinsics
2 parents bbda1fe + 8f75347 commit e3d3b3a

13 files changed

+141
-36
lines changed

base/replutil.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ end
9999
function show(io::IO, ::MIME"text/plain", f::Function)
100100
ft = typeof(f)
101101
mt = ft.name.mt
102-
if isa(f, Core.Builtin)
102+
if isa(f, Core.IntrinsicFunction)
103+
show(io, f)
104+
id = Core.Intrinsics.box(Int32, f)
105+
print(io, " (intrinsic function #$id)")
106+
elseif isa(f, Core.Builtin)
103107
print(io, mt.name, " (built-in function)")
104108
else
105109
name = mt.name

base/show.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ function show(io::IO, f::Function)
170170
end
171171

172172
function show(io::IO, x::Core.IntrinsicFunction)
173-
print(io, "(intrinsic function #", box(Int32, unbox(Core.IntrinsicFunction, x)), ")")
173+
name = ccall(:jl_intrinsic_name, Cstring, (Core.IntrinsicFunction,), x)
174+
print(io, unsafe_string(name))
174175
end
175176

176177
function show(io::IO, x::Union)

src/builtins.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ jl_fptr_t jl_get_builtin_fptr(jl_value_t *b)
11241124

11251125
static void add_builtin_func(const char *name, jl_fptr_t fptr)
11261126
{
1127-
add_builtin(name, jl_mk_builtin_func(name, fptr));
1127+
jl_mk_builtin_func(NULL, name, fptr);
11281128
}
11291129

11301130
void jl_init_primitives(void)

src/codegen.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5616,29 +5616,29 @@ static void init_julia_llvm_env(Module *m)
56165616
gcroot_func =
56175617
Function::Create(FunctionType::get(T_ppjlvalue, false),
56185618
Function::ExternalLinkage,
5619-
"julia.gc_root_decl", m);
5619+
"julia.gc_root_decl");
56205620
add_named_global(gcroot_func, (void*)NULL, /*dllimport*/false);
56215621

56225622
gckill_func =
56235623
Function::Create(FunctionType::get(T_void, ArrayRef<Type*>(T_ppjlvalue), false),
56245624
Function::ExternalLinkage,
5625-
"julia.gc_root_kill", m);
5625+
"julia.gc_root_kill");
56265626
add_named_global(gckill_func, (void*)NULL, /*dllimport*/false);
56275627

56285628
jlcall_frame_func =
56295629
Function::Create(FunctionType::get(T_ppjlvalue, ArrayRef<Type*>(T_int32), false),
56305630
Function::ExternalLinkage,
5631-
"julia.jlcall_frame_decl", m);
5631+
"julia.jlcall_frame_decl");
56325632
add_named_global(jlcall_frame_func, (void*)NULL, /*dllimport*/false);
56335633

56345634
gcroot_flush_func = Function::Create(FunctionType::get(T_void, false),
56355635
Function::ExternalLinkage,
5636-
"julia.gcroot_flush", m);
5636+
"julia.gcroot_flush");
56375637
add_named_global(gcroot_flush_func, (void*)NULL, /*dllimport*/false);
56385638

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

src/dump.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,7 +2050,13 @@ static void jl_save_system_image_to_stream(ios_t *f)
20502050
jl_serialize_value(&s, jl_main_module);
20512051
jl_serialize_value(&s, jl_top_module);
20522052
jl_serialize_value(&s, jl_typeinf_func);
2053+
2054+
// deserialize method tables of builtin types
20532055
jl_serialize_value(&s, jl_type_type->name->mt);
2056+
jl_serialize_value(&s, jl_intrinsic_type->name->mt);
2057+
jl_serialize_value(&s, jl_sym_type->name->mt);
2058+
jl_serialize_value(&s, jl_array_type->name->mt);
2059+
jl_serialize_value(&s, jl_module_type->name->mt);
20542060

20552061
jl_prune_type_cache(jl_tuple_typename->cache);
20562062
jl_prune_type_cache(jl_tuple_typename->linearcache);
@@ -2146,10 +2152,17 @@ static void jl_restore_system_image_from_stream(ios_t *f)
21462152
jl_main_module = (jl_module_t*)jl_deserialize_value(&s, NULL);
21472153
jl_top_module = (jl_module_t*)jl_deserialize_value(&s, NULL);
21482154
jl_internal_main_module = jl_main_module;
2155+
21492156
jl_typeinf_func = (jl_function_t*)jl_deserialize_value(&s, NULL);
21502157
jl_type_type_mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
2151-
jl_type_type->name->mt = jl_typector_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt =
2152-
jl_type_type_mt;
2158+
jl_type_type->name->mt = jl_type_type_mt;
2159+
jl_typector_type->name->mt = jl_type_type_mt;
2160+
jl_uniontype_type->name->mt = jl_type_type_mt;
2161+
jl_datatype_type->name->mt = jl_type_type_mt;
2162+
jl_intrinsic_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
2163+
jl_sym_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
2164+
jl_array_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
2165+
jl_module_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL);
21532166

21542167
intptr_t i;
21552168
for(i=0; i < builtin_types.len; i++) {

src/gf.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,14 @@ JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t
154154

155155
JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void);
156156
static jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_t *module, jl_datatype_t *st, int iskw);
157-
jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)
157+
void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr)
158158
{
159159
jl_sym_t *sname = jl_symbol(name);
160-
jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type, 0);
160+
if (dt == NULL) {
161+
jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type, 0);
162+
jl_set_const(jl_core_module, sname, f);
163+
dt = (jl_datatype_t*)jl_typeof(f);
164+
}
161165
jl_lambda_info_t *li = jl_new_lambda_info_uninit();
162166
li->fptr = fptr;
163167
li->code = jl_nothing;
@@ -168,14 +172,13 @@ jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)
168172

169173
li->def = jl_new_method_uninit();
170174
li->def->name = sname;
171-
// li->def->module will be set to jl_core_module by init.c
175+
li->def->module = jl_core_module;
172176
li->def->lambda_template = li;
173177
li->def->sig = jl_anytuple_type;
174178
li->def->tvars = jl_emptysvec;
175179

176-
jl_methtable_t *mt = jl_gf_mtable(f);
180+
jl_methtable_t *mt = dt->name->mt;
177181
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);
178-
return f;
179182
}
180183

181184
/*

src/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ void _julia_init(JL_IMAGE_SEARCH rel)
623623

624624
jl_an_empty_vec_any = (jl_value_t*)jl_alloc_vec_any(0);
625625
jl_init_serializer();
626+
jl_init_intrinsic_properties();
626627

627628
if (!jl_options.image_file) {
628629
jl_core_module = jl_new_module(jl_symbol("Core"));

src/intrinsics.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,13 +923,16 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
923923
f = fptoui_auto;
924924
if (f == fptosi && nargs == 1)
925925
f = fptosi_auto;
926+
if (f == cglobal && nargs == 1)
927+
f = cglobal_auto;
926928
unsigned expected_nargs = intrinsic_nargs[f];
927929
if (expected_nargs && expected_nargs != nargs) {
928930
jl_errorf("intrinsic #%d %s: wrong number of arguments", f, JL_I::jl_intrinsic_name((int)f));
929931
}
930932

931933
switch (f) {
932934
case ccall: return emit_ccall(args, nargs, ctx);
935+
case cglobal_auto:
933936
case cglobal: return emit_cglobal(args, nargs, ctx);
934937
case llvmcall: return emit_llvmcall(args, nargs, ctx);
935938
case arraylen:

src/intrinsics.h

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,14 @@
101101
ADD_I(pointerset, 4) \
102102
/* c interface */ \
103103
ALIAS(ccall, ccall) \
104-
ALIAS(cglobal, cglobal) \
104+
ADD_I(cglobal, 2) \
105105
ALIAS(llvmcall, llvmcall) \
106106
/* object access */ \
107107
ADD_I(arraylen, 1) \
108108
/* hidden intrinsics */ \
109109
ADD_HIDDEN(fptoui_auto, 1) \
110-
ADD_HIDDEN(fptosi_auto, 1)
110+
ADD_HIDDEN(fptosi_auto, 1) \
111+
ADD_HIDDEN(cglobal_auto, 1)
111112

112113
enum intrinsic {
113114
#define ADD_I(func, nargs) func,
@@ -124,7 +125,7 @@ enum intrinsic {
124125
#ifdef __cplusplus
125126
extern "C"
126127
#endif
127-
const char *jl_intrinsic_name(int f)
128+
JL_DLLEXPORT const char *jl_intrinsic_name(int f)
128129
{
129130
switch ((enum intrinsic)f) {
130131
default: return "invalid";
@@ -152,21 +153,25 @@ extern "C"
152153
JL_CALLABLE(jl_f_intrinsic_call)
153154
{
154155
JL_NARGSV(intrinsic_call, 1);
155-
JL_TYPECHK(intrinsic_call, intrinsic, args[0]);
156-
enum intrinsic f = (enum intrinsic)*(uint32_t*)jl_data_ptr(args[0]);
156+
JL_TYPECHK(intrinsic_call, intrinsic, F);
157+
enum intrinsic f = (enum intrinsic)*(uint32_t*)jl_data_ptr(F);
157158
if (f == fptoui && nargs == 1)
158159
f = fptoui_auto;
159160
if (f == fptosi && nargs == 1)
160161
f = fptosi_auto;
162+
if (f == cglobal && nargs == 1)
163+
f = cglobal_auto;
161164
unsigned fargs = intrinsic_nargs[f];
162-
JL_NARGS(intrinsic_call, 1 + fargs, 1 + fargs);
165+
if (!fargs)
166+
jl_error("this intrinsic must be compiled to be called");
167+
JL_NARGS(intrinsic_call, fargs, fargs);
163168
switch (fargs) {
164169
case 1:
165-
return ((intrinsic_call_1_arg)runtime_fp[f])(args[1]);
170+
return ((intrinsic_call_1_arg)runtime_fp[f])(args[0]);
166171
case 2:
167-
return ((intrinsic_call_2_arg)runtime_fp[f])(args[1], args[2]);
172+
return ((intrinsic_call_2_arg)runtime_fp[f])(args[0], args[1]);
168173
case 3:
169-
return ((intrinsic_call_3_arg)runtime_fp[f])(args[1], args[2], args[3]);
174+
return ((intrinsic_call_3_arg)runtime_fp[f])(args[0], args[1], args[2]);
170175
default:
171176
assert(0 && "unexpected number of arguments to an intrinsic function");
172177
}
@@ -191,21 +196,34 @@ static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f)
191196
#ifdef __cplusplus
192197
extern "C"
193198
#endif
194-
void jl_init_intrinsic_functions()
199+
void jl_init_intrinsic_properties(void)
200+
{
201+
#define ADD_I(name, nargs) add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
202+
#define ADD_HIDDEN ADD_I
203+
#define ALIAS(alias, base) add_intrinsic_properties(alias, intrinsic_nargs[base], runtime_fp[base]);
204+
ADD_HIDDEN(reinterpret, 2);
205+
INTRINSICS
206+
#undef ADD_I
207+
#undef ADD_HIDDEN
208+
#undef ALIAS
209+
210+
}
211+
212+
#ifdef __cplusplus
213+
extern "C"
214+
#endif
215+
void jl_init_intrinsic_functions(void)
195216
{
196217
jl_module_t *inm = jl_new_module(jl_symbol("Intrinsics"));
197218
inm->parent = jl_core_module;
198219
jl_set_const(jl_core_module, jl_symbol("Intrinsics"), (jl_value_t*)inm);
220+
jl_mk_builtin_func(jl_intrinsic_type, "IntrinsicFunction", jl_f_intrinsic_call);
199221

200-
#define ADD_I(name, nargs) add_intrinsic(inm, #name, name); add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
201-
#define ADD_HIDDEN(name, nargs) add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
202-
#define ALIAS(alias, base) add_intrinsic(inm, #alias, alias); add_intrinsic_properties(alias, intrinsic_nargs[base], runtime_fp[base]);
203-
ADD_HIDDEN(reinterpret, 2);
222+
#define ADD_I(name, nargs) add_intrinsic(inm, #name, name);
223+
#define ADD_HIDDEN(name, nargs)
224+
#define ALIAS ADD_I
204225
INTRINSICS
205226
#undef ADD_I
206227
#undef ADD_HIDDEN
207228
#undef ALIAS
208-
209-
jl_set_const(inm, jl_symbol("intrinsic_call"),
210-
jl_mk_builtin_func("intrinsic_call", jl_f_intrinsic_call));
211229
}

src/jltypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3948,7 +3948,7 @@ void jl_init_types(void)
39483948
jl_type_type->name->mt;
39493949

39503950
jl_intrinsic_type = jl_new_bitstype((jl_value_t*)jl_symbol("IntrinsicFunction"),
3951-
jl_any_type, jl_emptysvec, 32);
3951+
jl_builtin_type, jl_emptysvec, 32);
39523952

39533953
tv = jl_svec1(tvar("T"));
39543954
jl_ref_type =

src/julia_internal.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv);
269269
jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np);
270270
jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p);
271271
void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype);
272-
jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr);
272+
void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr);
273273
STATIC_INLINE int jl_is_type(jl_value_t *v)
274274
{
275275
jl_value_t *t = jl_typeof(v);
@@ -335,6 +335,7 @@ void jl_init_frontend(void);
335335
void jl_init_primitives(void);
336336
void jl_init_codegen(void);
337337
void jl_init_intrinsic_functions(void);
338+
void jl_init_intrinsic_properties(void);
338339
void jl_init_tasks(void);
339340
void jl_init_stack_limits(int ismaster);
340341
void jl_init_root_task(void *stack, size_t ssize);
@@ -527,11 +528,13 @@ extern JL_DLLEXPORT jl_value_t *jl_segv_exception;
527528
#endif
528529

529530
// -- Runtime intrinsics -- //
530-
const char *jl_intrinsic_name(int f);
531+
JL_DLLEXPORT const char *jl_intrinsic_name(int f);
531532

532533
JL_DLLEXPORT jl_value_t *jl_reinterpret(jl_value_t *ty, jl_value_t *v);
533534
JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t *align);
534535
JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *align, jl_value_t *i);
536+
JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty);
537+
JL_DLLEXPORT jl_value_t *jl_cglobal_auto(jl_value_t *v);
535538

536539
JL_DLLEXPORT jl_value_t *jl_neg_int(jl_value_t *a);
537540
JL_DLLEXPORT jl_value_t *jl_add_int(jl_value_t *a, jl_value_t *b);

src/runtime_intrinsics.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This file is a part of Julia. License is MIT: http://julialang.org/license
22

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

79+
JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
80+
{
81+
JL_TYPECHK(cglobal, type, ty);
82+
jl_value_t *rt =
83+
v == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case
84+
(jl_value_t*)jl_apply_type_((jl_value_t*)jl_pointer_type, &ty, 1);
85+
86+
if (!jl_is_leaf_type(rt))
87+
jl_error("cglobal: type argument not a leaftype");
88+
89+
if (jl_is_tuple(v) && jl_nfields(v) == 1)
90+
v = jl_fieldref(v, 0);
91+
92+
if (jl_is_pointer(v))
93+
return jl_reinterpret(rt, v);
94+
95+
char *f_lib = NULL;
96+
if (jl_is_tuple(v) && jl_nfields(v) > 1) {
97+
jl_value_t *t1 = jl_fieldref(v, 1);
98+
v = jl_fieldref(v, 0);
99+
if (jl_is_symbol(t1))
100+
f_lib = jl_symbol_name((jl_sym_t*)t1);
101+
else if (jl_is_string(t1))
102+
f_lib = jl_string_data(t1);
103+
else
104+
JL_TYPECHK(cglobal, symbol, t1)
105+
}
106+
107+
char *f_name = NULL;
108+
if (jl_is_symbol(v))
109+
f_name = jl_symbol_name((jl_sym_t*)v);
110+
else if (jl_is_string(v))
111+
f_name = jl_string_data(v);
112+
else
113+
JL_TYPECHK(cglobal, symbol, v)
114+
115+
#ifdef _OS_WINDOWS_
116+
if (!f_lib)
117+
f_lib = jl_dlfind_win32(f_name);
118+
#endif
119+
120+
void *ptr = jl_dlsym(jl_get_library(f_lib), f_name);
121+
jl_value_t *jv = jl_gc_alloc_1w();
122+
jl_set_typeof(jv, rt);
123+
*(void**)jl_data_ptr(jv) = ptr;
124+
return jv;
125+
}
126+
127+
JL_DLLEXPORT jl_value_t *jl_cglobal_auto(jl_value_t *v) {
128+
return jl_cglobal(v, (jl_value_t*)jl_void_type);
129+
}
130+
79131
static inline char signbitbyte(void *a, unsigned bytes)
80132
{
81133
// sign bit of an signed number of n bytes, as a byte

test/core.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,13 @@ glotest()
504504
@test glob_x == 88
505505
@test loc_x == 10
506506

507+
# runtime intrinsics
508+
509+
let f = Any[Core.Intrinsics.add_int, Core.Intrinsics.sub_int]
510+
@test f[1](1, 1) == 2
511+
@test f[2](1, 1) == 0
512+
end
513+
507514
# issue #7234
508515
begin
509516
glob_x2 = 24

0 commit comments

Comments
 (0)