diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ruby/atomic.h | 26 | ||||
-rw-r--r-- | include/ruby/internal/anyargs.h | 22 | ||||
-rw-r--r-- | include/ruby/internal/attr/nonstring.h | 38 | ||||
-rw-r--r-- | include/ruby/internal/core/rdata.h | 9 | ||||
-rw-r--r-- | include/ruby/internal/core/rtypeddata.h | 26 |
5 files changed, 105 insertions, 16 deletions
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h index e0977d21aa..2f5090e62f 100644 --- a/include/ruby/atomic.h +++ b/include/ruby/atomic.h @@ -302,6 +302,19 @@ typedef unsigned int rb_atomic_t; RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var)) /** +* Identical to #RUBY_ATOMIC_SET, except it expects its arguments are +* `void*`. There are cases where ::rb_atomic_t is 32bit while ::VALUE is +* 64bit. This should be used for pointer related operations to support such +* platforms. +* +* @param var A variable of `void*`. +* @param val Value to set. +* @post `var` holds `val`. +*/ +#define RUBY_ATOMIC_PTR_SET(var, val) \ + rbimpl_atomic_ptr_set((volatile void **)&(var), (val)) + +/** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`. * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This * should be used for size related operations to support such platforms. @@ -791,6 +804,19 @@ rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val) RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) +static inline void +rbimpl_atomic_ptr_set(volatile void **ptr, void *val) +{ + RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); + + const size_t sval = RBIMPL_CAST((size_t)val); + volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); + rbimpl_atomic_size_set(sptr, sval); +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) static inline VALUE rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val) { diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h index e3e1b6166d..e4c6d155cc 100644 --- a/include/ruby/internal/anyargs.h +++ b/include/ruby/internal/anyargs.h @@ -84,12 +84,15 @@ #elif defined(_WIN32) || defined(__CYGWIN__) # /* Skip due to [Bug #16134] */ +# define RBIMPL_CAST_FN_PTR 1 #elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union) # /* :TODO: improve here, please find a way to support. */ +# define RBIMPL_CAST_FN_PTR 1 #elif ! defined(HAVE_VA_ARGS_MACRO) # /* :TODO: improve here, please find a way to support. */ +# define RBIMPL_CAST_FN_PTR 1 #else # /** @cond INTERNAL_MACRO */ @@ -348,6 +351,25 @@ RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *) #endif /* __cplusplus */ +#if defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus) +/* In C23, K&R style prototypes are gone and so `void foo(ANYARGS)` became + * equivalent to `void foo(void)` unlike in earlier versions. This is a problem + * for rb_define_* functions since that makes all valid functions one can pass + * trip -Wincompatible-pointer-types, which we treat as errors. This is mostly + * not a problem for the __builtin_choose_expr path, but outside of that we + * need to add a cast for compatibility. + */ +#define rb_define_method(klass, mid, func, arity) rb_define_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_method_id(klass, mid, func, arity) rb_define_method_id((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_singleton_method(obj, mid, func, arity) rb_define_singleton_method((obj), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_protected_method(klass, mid, func, arity) rb_define_protected_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_private_method(klass, mid, func, arity) rb_define_private_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_module_function(mod, mid, func, arity) rb_define_module_function((mod), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_global_function(mid, func, arity) rb_define_global_function((mid), (VALUE (*)(ANYARGS))(func), (arity)) + +#undef RBIMPL_CAST_FN_PTR +#endif /* defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus) */ + /** * This macro is to properly cast a function parameter of *_define_method * family. It has been around since 1.x era so you can maximise backwards diff --git a/include/ruby/internal/attr/nonstring.h b/include/ruby/internal/attr/nonstring.h new file mode 100644 index 0000000000..9a66180e19 --- /dev/null +++ b/include/ruby/internal/attr/nonstring.h @@ -0,0 +1,38 @@ +#ifndef RBIMPL_ATTR_NONSTRING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NONSTRING_H +/** + * @file + * @author Ruby developers <[email protected]> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NONSTRING. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((nonstring))` */ +#if RBIMPL_HAS_ATTRIBUTE(nonstring) +# define RBIMPL_ATTR_NONSTRING() __attribute__((nonstring)) +# if RBIMPL_COMPILER_SINCE(GCC, 15, 0, 0) +# define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() +# else +# define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ +# endif +#else +# define RBIMPL_ATTR_NONSTRING() /* void */ +# define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ +#endif + +#endif /* RBIMPL_ATTR_NONSTRING_H */ diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h index e4c146a716..cab412af72 100644 --- a/include/ruby/internal/core/rdata.h +++ b/include/ruby/internal/core/rdata.h @@ -133,6 +133,12 @@ struct RData { */ RUBY_DATA_FUNC dmark; + /** Pointer to the actual C level struct that you want to wrap. + * This is in between dmark and dfree to allow DATA_PTR to continue + * to work for both RData and non-embedded RTypedData. + */ + void *data; + /** * This function is called when the object is no longer used. You need to * do whatever necessary to avoid memory leaks. @@ -141,9 +147,6 @@ struct RData { * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dfree; - - /** Pointer to the actual C level struct that you want to wrap. */ - void *data; }; RBIMPL_SYMBOL_EXPORT_BEGIN() diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h index 6c19576c20..b576be779f 100644 --- a/include/ruby/internal/core/rtypeddata.h +++ b/include/ruby/internal/core/rtypeddata.h @@ -114,7 +114,10 @@ #define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 /** @endcond */ -#define TYPED_DATA_EMBEDDED 2 +#define IS_TYPED_DATA ((VALUE)1) +#define TYPED_DATA_EMBEDDED ((VALUE)2) +#define TYPED_DATA_PTR_FLAGS ((VALUE)3) +#define TYPED_DATA_PTR_MASK (~TYPED_DATA_PTR_FLAGS) /** * @private @@ -353,18 +356,16 @@ struct RTypedData { struct RBasic basic; /** + * This is a `const rb_data_type_t *const` value, with the low bits set: + * + * 1: Always set, to differentiate RTypedData from RData. + * 2: Set if object is embedded. + * * This field stores various information about how Ruby should handle a * data. This roughly resembles a Ruby level class (apart from method * definition etc.) */ - const rb_data_type_t *const type; - - /** - * This has to be always 1. - * - * @internal - */ - const VALUE typed_flag; + const VALUE type; /** Pointer to the actual C level struct that you want to wrap. */ void *data; @@ -525,7 +526,7 @@ RTYPEDDATA_EMBEDDED_P(VALUE obj) } #endif - return RTYPEDDATA(obj)->typed_flag & TYPED_DATA_EMBEDDED; + return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED; } static inline void * @@ -561,8 +562,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool rbimpl_rtypeddata_p(VALUE obj) { - VALUE typed_flag = RTYPEDDATA(obj)->typed_flag; - return typed_flag != 0 && typed_flag <= 3; + return RTYPEDDATA(obj)->type & IS_TYPED_DATA; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() @@ -608,7 +608,7 @@ RTYPEDDATA_TYPE(VALUE obj) } #endif - return RTYPEDDATA(obj)->type; + return (const struct rb_data_type_struct *)(RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK); } /** |