From 70937646c4ecbf10ae7db1e9de791a4f4215a9e4 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:46:25 -0400 Subject: [PATCH] Add `JL_DLLIMPORT` to `small_typeof` declaration (#50892) Resolves #50714 (cherry picked from commit 91b8c9b99f05b99db8b259257adeb1997f8c4415) --- cli/jl_exports.h | 2 +- src/Makefile | 7 ++++++- src/aotcompile.cpp | 20 ++++++++++---------- src/builtins.c | 2 +- src/cgutils.cpp | 6 +++--- src/codegen.cpp | 6 +++--- src/gc.c | 4 ++-- src/jltypes.c | 20 ++++++++------------ src/julia.expmap.in | 1 - src/julia.h | 16 +++++++++++++--- src/processor.cpp | 2 +- src/processor.h | 6 +++--- src/staticdata.c | 8 ++++---- test/embedding/embedding.c | 6 ++++++ 14 files changed, 61 insertions(+), 45 deletions(-) diff --git a/cli/jl_exports.h b/cli/jl_exports.h index d28958c097edb..f1a05b504d9da 100644 --- a/cli/jl_exports.h +++ b/cli/jl_exports.h @@ -18,7 +18,7 @@ JL_EXPORTED_DATA_SYMBOLS(XX) // define a copy of exported data #define jl_max_tags 64 -JL_DLLEXPORT void *small_typeof[(jl_max_tags << 4) / sizeof(void*)]; // 16-bit aligned, like the GC +JL_DLLEXPORT void *jl_small_typeof[(jl_max_tags << 4) / sizeof(void*)]; // 16-bit aligned, like the GC // Declare list of exported functions (sans type) #define XX(name) JL_DLLEXPORT void name(void); diff --git a/src/Makefile b/src/Makefile index 9e34dfda1c4ed..3ea28e7c40324 100644 --- a/src/Makefile +++ b/src/Makefile @@ -520,7 +520,12 @@ clang-tidy-%: $(SRCDIR)/%.cpp $(build_shlibdir)/libImplicitAtomicsPlugin.$(SHLIB -- $(CLANGSA_FLAGS) $(CLANGSA_CXXFLAGS) $(LLVM_CXXFLAGS) $(JCPPFLAGS_CLANG) $(JCXXFLAGS_CLANG) $(JL_CXXFLAGS) $(DEBUGFLAGS_CLANG) -fcolor-diagnostics --system-header-prefix=llvm -Wno-deprecated-declarations -fno-caret-diagnostics -x c++) # set the exports for the source files based on where they are getting linked -clang-sa-% clang-sagc-% clang-tidy-%: DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS +$(addprefix clang-sa-,$(SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_INTERNAL +$(addprefix clang-sagc-,$(SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_INTERNAL +$(addprefix clang-tidy-,$(SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_INTERNAL +$(addprefix clang-sa-,$(CODEGEN_SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_CODEGEN +$(addprefix clang-sagc-,$(CODEGEN_SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_CODEGEN +$(addprefix clang-tidy-,$(CODEGEN_SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_CODEGEN # Add C files as a target of `analyzesrc` and `analyzegc` and `tidysrc` tidysrc: $(addprefix clang-tidy-,$(filter-out $(basename $(SKIP_IMPLICIT_ATOMICS)),$(CODEGEN_SRCS) $(SRCS))) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index d288586916560..05088394500c1 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -1621,10 +1621,10 @@ void jl_dump_native_impl(void *native_code, // let the compiler know we are going to internalize a copy of this, // if it has a current usage with ExternalLinkage - auto small_typeof_copy = dataM.getGlobalVariable("small_typeof"); - if (small_typeof_copy) { - small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); - small_typeof_copy->setDSOLocal(true); + auto jl_small_typeof_copy = dataM.getGlobalVariable("jl_small_typeof"); + if (jl_small_typeof_copy) { + jl_small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); + jl_small_typeof_copy->setDSOLocal(true); } } @@ -1698,13 +1698,13 @@ void jl_dump_native_impl(void *native_code, auto shards = emit_shard_table(metadataM, T_size, T_psize, threads); auto ptls = emit_ptls_table(metadataM, T_size, T_psize); auto header = emit_image_header(metadataM, threads, nfvars, ngvars); - auto AT = ArrayType::get(T_size, sizeof(small_typeof) / sizeof(void*)); - auto small_typeof_copy = new GlobalVariable(metadataM, AT, false, + auto AT = ArrayType::get(T_size, sizeof(jl_small_typeof) / sizeof(void*)); + auto jl_small_typeof_copy = new GlobalVariable(metadataM, AT, false, GlobalVariable::ExternalLinkage, Constant::getNullValue(AT), - "small_typeof"); - small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); - small_typeof_copy->setDSOLocal(true); + "jl_small_typeof"); + jl_small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); + jl_small_typeof_copy->setDSOLocal(true); AT = ArrayType::get(T_psize, 5); auto pointers = new GlobalVariable(metadataM, AT, false, GlobalVariable::ExternalLinkage, @@ -1712,7 +1712,7 @@ void jl_dump_native_impl(void *native_code, ConstantExpr::getBitCast(header, T_psize), ConstantExpr::getBitCast(shards, T_psize), ConstantExpr::getBitCast(ptls, T_psize), - ConstantExpr::getBitCast(small_typeof_copy, T_psize), + ConstantExpr::getBitCast(jl_small_typeof_copy, T_psize), ConstantExpr::getBitCast(target_ids, T_psize) }), "jl_image_pointers"); diff --git a/src/builtins.c b/src/builtins.c index 4f75fd79eadcc..e2169abb704fc 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -222,7 +222,7 @@ JL_DLLEXPORT int jl_egal__unboxed(const jl_value_t *a JL_MAYBE_UNROOTED, const j JL_DLLEXPORT int jl_egal__bitstag(const jl_value_t *a JL_MAYBE_UNROOTED, const jl_value_t *b JL_MAYBE_UNROOTED, uintptr_t dtag) JL_NOTSAFEPOINT { if (dtag < jl_max_tags << 4) { - switch ((enum jlsmall_typeof_tags)(dtag >> 4)) { + switch ((enum jl_small_typeof_tags)(dtag >> 4)) { case jl_int8_tag: case jl_uint8_tag: return *(uint8_t*)a == *(uint8_t*)b; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 326e4823d6c34..69f620869df93 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -411,7 +411,7 @@ static Constant *literal_pointer_val_slot(jl_codectx_t &ctx, jl_value_t *p) if (addr->smalltag) { // some common builtin datatypes have a special pool for accessing them by smalltag id Constant *tag = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), addr->smalltag << 4); - Constant *smallp = ConstantExpr::getInBoundsGetElementPtr(getInt8Ty(ctx.builder.getContext()), prepare_global_in(jl_Module, jlsmall_typeof_var), tag); + Constant *smallp = ConstantExpr::getInBoundsGetElementPtr(getInt8Ty(ctx.builder.getContext()), prepare_global_in(jl_Module, jl_small_typeof_var), tag); return ConstantExpr::getBitCast(smallp, ctx.types().T_ppjlvalue); } // DataTypes are prefixed with a + @@ -1096,7 +1096,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull if (jl_has_intersect_type_not_kind(typ)) return false; for (size_t i = 0; i < jl_tags_count; i++) { - jl_datatype_t *dt = small_typeof[(i << 4) / sizeof(*small_typeof)]; + jl_datatype_t *dt = jl_small_typeof[(i << 4) / sizeof(*jl_small_typeof)]; if (dt && !jl_has_empty_intersection((jl_value_t*)dt, typ)) return false; } @@ -1457,7 +1457,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, Value *v, bool maybenull, bool just // we lied a bit: this wasn't really an object (though it was valid for GC rooting) // and we need to use it as an index to get the real object now Module *M = jl_Module; - Value *smallp = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), prepare_global_in(M, jlsmall_typeof_var), tag); + Value *smallp = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), prepare_global_in(M, jl_small_typeof_var), tag); smallp = ctx.builder.CreateBitCast(smallp, typetag->getType()->getPointerTo(0)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); auto small = ctx.builder.CreateAlignedLoad(typetag->getType(), smallp, M->getDataLayout().getPointerABIAlignment(0)); diff --git a/src/codegen.cpp b/src/codegen.cpp index 5ad4eb4e6e9a4..f72c2ae2056b9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -649,8 +649,8 @@ static const auto jldlli_var = new JuliaVariable{ true, [](Type *T_size) -> Type * { return getInt8PtrTy(T_size->getContext()); }, }; -static const auto jlsmall_typeof_var = new JuliaVariable{ - XSTR(small_typeof), +static const auto jl_small_typeof_var = new JuliaVariable{ + XSTR(jl_small_typeof), true, [](Type *T_size) -> Type * { return getInt8Ty(T_size->getContext()); }, }; @@ -9032,7 +9032,7 @@ static void init_f16_funcs(void) static void init_jit_functions(void) { - add_named_global(jlsmall_typeof_var, &small_typeof); + add_named_global(jl_small_typeof_var, &jl_small_typeof); add_named_global(jlstack_chk_guard_var, &__stack_chk_guard); add_named_global(jlRTLD_DEFAULT_var, &jl_RTLD_DEFAULT_handle); add_named_global(jlexe_var, &jl_exe_handle); diff --git a/src/gc.c b/src/gc.c index 0d285b7251589..7d847195dce8c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2422,7 +2422,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ vtag == (jl_vararg_tag << 4)) { // these objects have pointers in them, but no other special handling // so we want these to fall through to the end - vtag = (uintptr_t)small_typeof[vtag / sizeof(*small_typeof)]; + vtag = (uintptr_t)ijl_small_typeof[vtag / sizeof(*ijl_small_typeof)]; } else if (vtag < jl_max_tags << 4) { // these objects either have specialing handling @@ -2532,7 +2532,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ objprofile_count(jl_string_type, bits == GC_OLD_MARKED, dtsz); } else { - jl_datatype_t *vt = small_typeof[vtag / sizeof(*small_typeof)]; + jl_datatype_t *vt = ijl_small_typeof[vtag / sizeof(*ijl_small_typeof)]; size_t dtsz = jl_datatype_size(vt); if (update_meta) gc_setmark(ptls, o, bits, dtsz); diff --git a/src/jltypes.c b/src/jltypes.c index 024d0be74e659..8da119248203a 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -20,7 +20,7 @@ extern "C" { #endif _Atomic(jl_value_t*) cmpswap_names JL_GLOBALLY_ROOTED; -jl_datatype_t *small_typeof[(jl_max_tags << 4) / sizeof(*small_typeof)]; // 16-bit aligned, like the GC +jl_datatype_t *ijl_small_typeof[(jl_max_tags << 4) / sizeof(*ijl_small_typeof)]; // 16-bit aligned, like the GC // compute empirical max-probe for a given size #define max_probe(size) ((size) <= 1024 ? 16 : (size) >> 6) @@ -2525,19 +2525,13 @@ static jl_tvar_t *tvar(const char *name) (jl_value_t*)jl_any_type); } -void export_small_typeof(void) +void export_jl_small_typeof(void) { - void *copy; -#ifdef _OS_WINDOWS_ - jl_dlsym(jl_libjulia_handle, "small_typeof", ©, 1); -#else - jl_dlsym(jl_libjulia_internal_handle, "small_typeof", ©, 1); -#endif - memcpy(copy, &small_typeof, sizeof(small_typeof)); + memcpy(&jl_small_typeof, &ijl_small_typeof, sizeof(jl_small_typeof)); } #define XX(name) \ - small_typeof[(jl_##name##_tag << 4) / sizeof(*small_typeof)] = jl_##name##_type; \ + ijl_small_typeof[(jl_##name##_tag << 4) / sizeof(*ijl_small_typeof)] = jl_##name##_type; \ jl_##name##_type->smalltag = jl_##name##_tag; void jl_init_types(void) JL_GC_DISABLED { @@ -3357,7 +3351,8 @@ void jl_init_types(void) JL_GC_DISABLED // override the preferred layout for a couple types jl_lineinfonode_type->name->mayinlinealloc = 0; // FIXME: assumed to be a pointer by codegen - export_small_typeof(); + + export_jl_small_typeof(); } static jl_value_t *core(const char *name) @@ -3438,7 +3433,8 @@ void post_boot_hooks(void) } } } - export_small_typeof(); + + export_jl_small_typeof(); } #undef XX diff --git a/src/julia.expmap.in b/src/julia.expmap.in index 484c83a4b16b2..213d087fdc2ad 100644 --- a/src/julia.expmap.in +++ b/src/julia.expmap.in @@ -7,7 +7,6 @@ ios_*; arraylist_grow; small_arraylist_grow; - small_typeof; jl_*; ijl_*; _jl_mutex_*; diff --git a/src/julia.h b/src/julia.h index 5af8a5bc1a170..f4229eae909ac 100644 --- a/src/julia.h +++ b/src/julia.h @@ -740,7 +740,7 @@ typedef struct { /* XX(slotnumber) */ \ /* XX(ssavalue) */ \ /* end of JL_SMALL_TYPEOF */ -enum jlsmall_typeof_tags { +enum jl_small_typeof_tags { jl_null_tag = 0, #define XX(name) jl_##name##_tag, JL_SMALL_TYPEOF(XX) @@ -749,13 +749,23 @@ enum jlsmall_typeof_tags { jl_bitstags_first = jl_char_tag, // n.b. bool is not considered a bitstype, since it can be compared by pointer jl_max_tags = 64 }; -extern jl_datatype_t *small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +extern JL_DLLIMPORT jl_datatype_t *jl_small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +#ifndef JL_LIBRARY_EXPORTS_INTERNAL static inline jl_value_t *jl_to_typeof(uintptr_t t) { if (t < (jl_max_tags << 4)) - return (jl_value_t*)small_typeof[t / sizeof(*small_typeof)]; + return (jl_value_t*)jl_small_typeof[t / sizeof(*jl_small_typeof)]; return (jl_value_t*)t; } +#else +extern JL_HIDDEN jl_datatype_t *ijl_small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +static inline jl_value_t *jl_to_typeof(uintptr_t t) +{ + if (t < (jl_max_tags << 4)) + return (jl_value_t*)ijl_small_typeof[t / sizeof(*ijl_small_typeof)]; + return (jl_value_t*)t; +} +#endif // kinds diff --git a/src/processor.cpp b/src/processor.cpp index 9a602ba836f89..d2d91d3cd9966 100644 --- a/src/processor.cpp +++ b/src/processor.cpp @@ -812,7 +812,7 @@ static inline jl_image_t parse_sysimg(void *hdl, F &&callback) *tls_offset_idx = (uintptr_t)(jl_tls_offset == -1 ? 0 : jl_tls_offset); } - res.small_typeof = pointers->small_typeof; + res.jl_small_typeof = pointers->jl_small_typeof; return res; } diff --git a/src/processor.h b/src/processor.h index 74610cbe64b28..a3ebdf4f8c605 100644 --- a/src/processor.h +++ b/src/processor.h @@ -88,7 +88,7 @@ typedef struct { const int32_t *gvars_offsets; uint32_t ngvars; jl_image_fptrs_t fptrs; - void **small_typeof; + void **jl_small_typeof; } jl_image_t; // The header for each image @@ -197,8 +197,8 @@ typedef struct { const jl_image_shard_t *shards; // points to header->nshards length array // The TLS data pointer const jl_image_ptls_t *ptls; - // A copy of small_typeof[] - void **small_typeof; + // A copy of jl_small_typeof[] + void **jl_small_typeof; // serialized target data // This contains the number of targets diff --git a/src/staticdata.c b/src/staticdata.c index c05422fd10969..a974d98a39835 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -1984,7 +1984,7 @@ static void jl_update_all_fptrs(jl_serializer_state *s, jl_image_t *image) if (fvars.base == NULL) return; - memcpy(image->small_typeof, &small_typeof, sizeof(small_typeof)); + memcpy(image->jl_small_typeof, &jl_small_typeof, sizeof(jl_small_typeof)); int img_fvars_max = s->fptr_record->size / sizeof(void*); size_t i; @@ -2838,7 +2838,7 @@ JL_DLLEXPORT void jl_set_sysimg_so(void *handle) #endif extern void rebuild_image_blob_tree(void); -extern void export_small_typeof(void); +extern void export_jl_small_typeof(void); static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl_array_t *depmods, uint64_t checksum, /* outputs */ jl_array_t **restored, jl_array_t **init_order, @@ -2914,10 +2914,10 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl *tag = jl_read_value(&s); } #define XX(name) \ - small_typeof[(jl_##name##_tag << 4) / sizeof(*small_typeof)] = jl_##name##_type; + ijl_small_typeof[(jl_##name##_tag << 4) / sizeof(*ijl_small_typeof)] = jl_##name##_type; JL_SMALL_TYPEOF(XX) #undef XX - export_small_typeof(); + export_jl_small_typeof(); jl_global_roots_table = (jl_array_t*)jl_read_value(&s); // set typeof extra-special values now that we have the type set by tags above jl_astaggedvalue(jl_nothing)->header = (uintptr_t)jl_nothing_type | jl_astaggedvalue(jl_nothing)->header; diff --git a/test/embedding/embedding.c b/test/embedding/embedding.c index 1294d4cdafb45..c5b8845b7c823 100644 --- a/test/embedding/embedding.c +++ b/test/embedding/embedding.c @@ -192,6 +192,12 @@ int main() checked_eval_string("f28825()"); } + { + // jl_typeof works (#50714) + jl_value_t *v = checked_eval_string("sqrt(2.0)"); + jl_value_t *t = jl_typeof(v); + } + JL_TRY { jl_error("exception thrown"); }