From de41c51448d6d193145bd24e3f37f19ce6363558 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Fri, 31 Jan 2025 15:22:54 -0700 Subject: [PATCH] Extend Base.bitcast(ty, v) to all packed isbits types. Previously, `Base.bitcast(ty, v)` only supported primitive types. This commit extends it to support any packed isbits type. --- src/datatype.c | 5 +++++ src/julia.h | 5 +++++ src/julia_internal.h | 1 + src/runtime_intrinsics.c | 12 ++++++++---- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index fd25cca503676..5e906be8ce955 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -371,6 +371,11 @@ int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree) return 0; } +JL_DLLEXPORT int jl_datatype_has_padding(jl_datatype_t *dt) +{ + return jl_is_datatype(dt) && dt->layout && dt->layout->flags.haspadding; +} + static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield) { if (jl_is_uniontype(ty)) { diff --git a/src/julia.h b/src/julia.h index b5416568b7ae9..6553795593b52 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1611,6 +1611,11 @@ STATIC_INLINE int jl_is_primitivetype(void *v) JL_NOTSAFEPOINT return (jl_is_datatype(v) && ((jl_datatype_t*)(v))->isprimitivetype); } +STATIC_INLINE int jl_is_bitstype(void *v) JL_NOTSAFEPOINT +{ + return (jl_is_datatype(v) && ((jl_datatype_t*)(v))->isbitstype); +} + STATIC_INLINE int jl_is_structtype(void *v) JL_NOTSAFEPOINT { return (jl_is_datatype(v) && diff --git a/src/julia_internal.h b/src/julia_internal.h index 3e4967c9d4dca..89fe971debbe0 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -836,6 +836,7 @@ void jl_init_main_module(void); JL_DLLEXPORT int jl_is_submodule(jl_module_t *child, jl_module_t *parent) JL_NOTSAFEPOINT; jl_array_t *jl_get_loaded_modules(void); JL_DLLEXPORT int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree); +JL_DLLEXPORT int jl_datatype_has_padding(jl_datatype_t *dt); int jl_type_equality_is_identity(jl_value_t *t1, jl_value_t *t2) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_eval_const_decl(jl_module_t *m, jl_value_t *arg, jl_value_t *val); diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index 1790b9bd8d106..cba8efc261e0d 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -392,10 +392,14 @@ JL_DLLEXPORT BFLOAT16_TYPE julia__truncdfbf2(double param) JL_NOTSAFEPOINT JL_DLLEXPORT jl_value_t *jl_bitcast(jl_value_t *ty, jl_value_t *v) { JL_TYPECHK(bitcast, datatype, ty); - if (!jl_is_concrete_type(ty) || !jl_is_primitivetype(ty)) - jl_error("bitcast: target type not a leaf primitive type"); - if (!jl_is_primitivetype(jl_typeof(v))) - jl_error("bitcast: value not a primitive type"); + if (!jl_is_concrete_type(ty) || !jl_is_bitstype(ty)) + jl_error("bitcast: target type not a leaf bits type"); + if (!jl_is_bitstype(jl_typeof(v))) + jl_error("bitcast: value not a bits type"); + if (jl_datatype_has_padding((jl_datatype_t*)(ty))) + jl_error("bitcast: target type has padding. Can only bitcast to packed types."); + if (jl_datatype_has_padding((jl_datatype_t*)(jl_typeof(v)))) + jl_error("bitcast: value struct has padding. Can only bitcast from packed types."); if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty)) jl_error("bitcast: argument size does not match size of target type"); if (ty == jl_typeof(v))