From 9b51354a3b153a85cbe9c63c8b54573aa3e64353 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 20 Jul 2023 15:14:05 +0200 Subject: [PATCH] Make it possible to register a LLVM type constructor for codegen. --- base/boot.jl | 10 ++++------ src/builtin_proto.h | 2 ++ src/builtins.c | 12 ++++++++++++ src/cgutils.cpp | 2 ++ src/datatype.c | 1 + src/jltypes.c | 14 ++++++++------ src/julia.h | 3 +++ src/staticdata.c | 5 +++-- 8 files changed, 35 insertions(+), 14 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index 78b7daaf47d64..191abf7ec3340 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -19,14 +19,12 @@ # name::TypeName # super::Type # parameters::Tuple -# names::Tuple # types::Tuple -# ctor # instance -# size::Int32 -# abstract::Bool -# mutable::Bool -# pointerfree::Bool +# layout +# llvm_ctor +# hash::UInt32 +# flags::UInt16 #end #struct Union <: Type diff --git a/src/builtin_proto.h b/src/builtin_proto.h index 64e3fbd1af366..fe8075f42173e 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -52,6 +52,7 @@ DECLARE_BUILTIN(throw); DECLARE_BUILTIN(tuple); DECLARE_BUILTIN(typeassert); DECLARE_BUILTIN(_typebody); +DECLARE_BUILTIN(_typector); DECLARE_BUILTIN(typeof); DECLARE_BUILTIN(_typevar); DECLARE_BUILTIN(donotdelete); @@ -66,6 +67,7 @@ JL_CALLABLE(jl_f__structtype); JL_CALLABLE(jl_f__abstracttype); JL_CALLABLE(jl_f__primitivetype); JL_CALLABLE(jl_f__setsuper); +JL_CALLABLE(jl_f__typector); JL_CALLABLE(jl_f__equiv_typedef); JL_CALLABLE(jl_f_get_binding_type); JL_CALLABLE(jl_f_set_binding_type); diff --git a/src/builtins.c b/src/builtins.c index 4f75fd79eadcc..22431e328fcda 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1787,6 +1787,17 @@ JL_CALLABLE(jl_f__typebody) return jl_nothing; } +JL_CALLABLE(jl_f__typector) +{ + JL_NARGS(_typector!, 2, 2); + jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(args[0]); + JL_TYPECHK(_typector!, datatype, (jl_value_t*)dt); + jl_value_t* ctor = args[1]; + JL_TYPECHK(_typector!, pointer, ctor); + dt->llvm_constructor = (jl_llvm_type_constructor_t) jl_unbox_long(ctor); + return jl_nothing; +} + // this is a heuristic for allowing "redefining" a type to something identical static int equiv_type(jl_value_t *ta, jl_value_t *tb) { @@ -2037,6 +2048,7 @@ void jl_init_primitives(void) JL_GC_DISABLED add_builtin_func("_primitivetype", jl_f__primitivetype); add_builtin_func("_setsuper!", jl_f__setsuper); jl_builtin__typebody = add_builtin_func("_typebody!", jl_f__typebody); + add_builtin_func("_typector!", jl_f__typector); add_builtin_func("_equiv_typedef", jl_f__equiv_typedef); jl_builtin_donotdelete = add_builtin_func("donotdelete", jl_f_donotdelete); jl_builtin_compilerbarrier = add_builtin_func("compilerbarrier", jl_f_compilerbarrier); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 9b3d634c76400..ab8711b4ffe06 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -655,6 +655,8 @@ Type *jl_type_to_llvm_impl(jl_value_t *jt, LLVMContextRef ctxt, bool *isboxed) static Type *bitstype_to_llvm(jl_value_t *bt, LLVMContext &ctxt, bool llvmcall = false) { assert(jl_is_primitivetype(bt)); + if (((jl_datatype_t*)bt)->llvm_constructor != NULL) + return (Type*) ((jl_datatype_t*)bt)->llvm_constructor(&ctxt); if (bt == (jl_value_t*)jl_bool_type) return llvmcall ? getInt1Ty(ctxt) : getInt8Ty(ctxt); if (bt == (jl_value_t*)jl_int32_type) diff --git a/src/datatype.c b/src/datatype.c index 905959fb80e0a..ebff30f7cfe60 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -114,6 +114,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void) t->layout = NULL; t->types = NULL; t->instance = NULL; + t->llvm_constructor = NULL; return t; } diff --git a/src/jltypes.c b/src/jltypes.c index f6c1febc7cf5c..20baca00b6833 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2577,8 +2577,8 @@ void jl_init_types(void) JL_GC_DISABLED jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = type_type; jl_datatype_type->parameters = jl_emptysvec; - jl_datatype_type->name->n_uninitialized = 8 - 3; - jl_datatype_type->name->names = jl_perm_symsvec(8, + jl_datatype_type->name->n_uninitialized = 9 - 3; + jl_datatype_type->name->names = jl_perm_symsvec(9, "name", "super", "parameters", @@ -2586,16 +2586,18 @@ void jl_init_types(void) JL_GC_DISABLED "instance", "layout", "hash", - "flags"); // "hasfreetypevars", "isconcretetype", "isdispatchtuple", "isbitstype", "zeroinit", "has_concrete_subtype", "maybe_subtype_of_cache" - jl_datatype_type->types = jl_svec(8, + "flags", // "hasfreetypevars", "isconcretetype", "isdispatchtuple", "isbitstype", "zeroinit", "has_concrete_subtype", "maybe_subtype_of_cache" + "llvm_constructor"); + jl_datatype_type->types = jl_svec(9, jl_typename_type, jl_datatype_type, jl_simplevector_type, jl_simplevector_type, - jl_any_type, // instance + jl_any_type /*instance*/, jl_any_type /*jl_voidpointer_type*/, jl_any_type /*jl_int32_type*/, - jl_any_type /*jl_uint16_type*/); + jl_any_type /*jl_uint16_type*/, + jl_any_type /*jl_voidpointer_type*/); const static uint32_t datatype_constfields[1] = { 0x00000057 }; // (1<<0)|(1<<1)|(1<<2)|(1<<4)|(1<<6) const static uint32_t datatype_atomicfields[1] = { 0x00000028 }; // (1<<3)|(1<<5) jl_datatype_type->name->constfields = datatype_constfields; diff --git a/src/julia.h b/src/julia.h index 9c5f0d519de0f..71618121b7245 100644 --- a/src/julia.h +++ b/src/julia.h @@ -553,6 +553,8 @@ typedef struct { // }; } jl_datatype_layout_t; +typedef void *(*jl_llvm_type_constructor_t)(void *ctx); + typedef struct _jl_datatype_t { JL_DATA_TYPE jl_typename_t *name; @@ -574,6 +576,7 @@ typedef struct _jl_datatype_t { uint16_t ismutationfree:1; // whether any mutable memory is reachable through this type (in the type or via fields) uint16_t isidentityfree:1; // whether this type or any object reachable through its fields has non-content-based identity uint16_t smalltag:6; // whether this type has a small-tag optimization + jl_llvm_type_constructor_t llvm_constructor; // callable function taking a context argument } jl_datatype_t; typedef struct _jl_vararg_t { diff --git a/src/staticdata.c b/src/staticdata.c index c05422fd10969..f725e1f2ff8cf 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -99,7 +99,7 @@ extern "C" { // TODO: put WeakRefs on the weak_refs list during deserialization // TODO: handle finalizers -#define NUM_TAGS 158 +#define NUM_TAGS 159 // An array of references that need to be restored from the sysimg // This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C. @@ -273,6 +273,7 @@ jl_value_t **const*const get_tags(void) { INSERT_TAG(jl_builtin__expr); INSERT_TAG(jl_builtin_ifelse); INSERT_TAG(jl_builtin__typebody); + INSERT_TAG(jl_builtin__typector); INSERT_TAG(jl_builtin_donotdelete); INSERT_TAG(jl_builtin_compilerbarrier); INSERT_TAG(jl_builtin_getglobal); @@ -447,7 +448,7 @@ static const jl_fptr_args_t id_to_fptrs[] = { &jl_f_arrayref, &jl_f_const_arrayref, &jl_f_arrayset, &jl_f_arraysize, &jl_f_apply_type, &jl_f_applicable, &jl_f_invoke, &jl_f_sizeof, &jl_f__expr, &jl_f__typevar, &jl_f_ifelse, &jl_f__structtype, &jl_f__abstracttype, &jl_f__primitivetype, - &jl_f__typebody, &jl_f__setsuper, &jl_f__equiv_typedef, &jl_f_get_binding_type, + &jl_f__typebody, &jl_f__typector, &jl_f__setsuper, &jl_f__equiv_typedef, &jl_f_get_binding_type, &jl_f_set_binding_type, &jl_f_opaque_closure_call, &jl_f_donotdelete, &jl_f_compilerbarrier, &jl_f_getglobal, &jl_f_setglobal, &jl_f_finalizer, &jl_f__compute_sparams, &jl_f__svec_ref, NULL };