Ruby 3.2.1p31 (2023-02-08 revision 31819e82c88c6f8ecfaeb162519bfa26a14b21fd)
value_type.h
Go to the documentation of this file.
1#ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_VALUE_TYPE_H
29#include "ruby/internal/cast.h"
33#include "ruby/internal/error.h"
37#include "ruby/internal/value.h"
38#include "ruby/assert.h"
39
40#if defined(T_DATA)
41/*
42 * :!BEWARE!: (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of
43 * T_DATA. Let us stop here. Please have a workaround like this:
44 *
45 * ```C
46 * #include <ruby/ruby.h> // <- Include this one first.
47 * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever.
48 * #include <nfs/nfs.h> // <- OS-provided T_DATA introduced.
49 * ```
50 *
51 * See also [ruby-core:4261]
52 */
53# error Bail out due to conflicting definition of T_DATA.
54#endif
55
56#define T_ARRAY RUBY_T_ARRAY
57#define T_BIGNUM RUBY_T_BIGNUM
58#define T_CLASS RUBY_T_CLASS
59#define T_COMPLEX RUBY_T_COMPLEX
60#define T_DATA RUBY_T_DATA
61#define T_FALSE RUBY_T_FALSE
62#define T_FILE RUBY_T_FILE
63#define T_FIXNUM RUBY_T_FIXNUM
64#define T_FLOAT RUBY_T_FLOAT
65#define T_HASH RUBY_T_HASH
66#define T_ICLASS RUBY_T_ICLASS
67#define T_IMEMO RUBY_T_IMEMO
68#define T_MASK RUBY_T_MASK
69#define T_MATCH RUBY_T_MATCH
70#define T_MODULE RUBY_T_MODULE
71#define T_MOVED RUBY_T_MOVED
72#define T_NIL RUBY_T_NIL
73#define T_NODE RUBY_T_NODE
74#define T_NONE RUBY_T_NONE
75#define T_OBJECT RUBY_T_OBJECT
76#define T_RATIONAL RUBY_T_RATIONAL
77#define T_REGEXP RUBY_T_REGEXP
78#define T_STRING RUBY_T_STRING
79#define T_STRUCT RUBY_T_STRUCT
80#define T_SYMBOL RUBY_T_SYMBOL
81#define T_TRUE RUBY_T_TRUE
82#define T_UNDEF RUBY_T_UNDEF
83#define T_ZOMBIE RUBY_T_ZOMBIE
85#define BUILTIN_TYPE RB_BUILTIN_TYPE
86#define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
87#define RB_INTEGER_TYPE_P rb_integer_type_p
88#define SYMBOL_P RB_SYMBOL_P
89#define rb_type_p RB_TYPE_P
92#define RB_BUILTIN_TYPE RB_BUILTIN_TYPE
93#define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
94#define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P
95#define RB_SYMBOL_P RB_SYMBOL_P
96#define RB_TYPE_P RB_TYPE_P
97#define Check_Type Check_Type
98
99#if !RUBY_DEBUG
100# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t)))
101#else
102# define RBIMPL_ASSERT_TYPE Check_Type
103#endif
107#define TYPE(_) RBIMPL_CAST((int)rb_type(_))
108
110enum
113 RUBY_T_NONE = 0x00,
122 RUBY_T_HASH = 0x08,
125 RUBY_T_FILE = 0x0b,
126 RUBY_T_DATA = 0x0c,
131 RUBY_T_NIL = 0x11,
132 RUBY_T_TRUE = 0x12,
139 RUBY_T_NODE = 0x1b,
144 RUBY_T_MASK = 0x1f
146
168void rb_check_type(VALUE obj, int t);
170
180static inline enum ruby_value_type
181RB_BUILTIN_TYPE(VALUE obj)
182{
183 RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
184
185#if 0 && defined __GNUC__ && !defined __clang__
186 /* Don't move the access to `flags` before the preceding
187 * RB_SPECIAL_CONST_P check. */
188 __asm volatile("": : :"memory");
189#endif
190 VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK;
191 return RBIMPL_CAST((enum ruby_value_type)ret);
192}
193
202static inline bool
204{
205 if (RB_FIXNUM_P(obj)) {
206 return true;
207 }
208 else if (RB_SPECIAL_CONST_P(obj)) {
209 return false;
210 }
211 else {
212 return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM;
213 }
214}
215
223static inline enum ruby_value_type
225{
226 if (! RB_SPECIAL_CONST_P(obj)) {
227 return RB_BUILTIN_TYPE(obj);
228 }
229 else if (obj == RUBY_Qfalse) {
230 return RUBY_T_FALSE;
231 }
232 else if (obj == RUBY_Qnil) {
233 return RUBY_T_NIL;
234 }
235 else if (obj == RUBY_Qtrue) {
236 return RUBY_T_TRUE;
237 }
238 else if (obj == RUBY_Qundef) {
239 return RUBY_T_UNDEF;
240 }
241 else if (RB_FIXNUM_P(obj)) {
242 return RUBY_T_FIXNUM;
243 }
244 else if (RB_STATIC_SYM_P(obj)) {
245 return RUBY_T_SYMBOL;
246 }
247 else {
248 RBIMPL_ASSUME(RB_FLONUM_P(obj));
249 return RUBY_T_FLOAT;
250 }
251}
252
262static inline bool
263RB_FLOAT_TYPE_P(VALUE obj)
264{
265 if (RB_FLONUM_P(obj)) {
266 return true;
267 }
268 else if (RB_SPECIAL_CONST_P(obj)) {
269 return false;
270 }
271 else {
272 return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT;
273 }
274}
275
285static inline bool
286RB_DYNAMIC_SYM_P(VALUE obj)
287{
288 if (RB_SPECIAL_CONST_P(obj)) {
289 return false;
290 }
291 else {
292 return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL;
293 }
294}
295
305static inline bool
306RB_SYMBOL_P(VALUE obj)
307{
308 return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj);
309}
310
324static bool
325rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
326{
327 if (t == RUBY_T_TRUE) {
328 return obj == RUBY_Qtrue;
329 }
330 else if (t == RUBY_T_FALSE) {
331 return obj == RUBY_Qfalse;
332 }
333 else if (t == RUBY_T_NIL) {
334 return obj == RUBY_Qnil;
335 }
336 else if (t == RUBY_T_UNDEF) {
337 return obj == RUBY_Qundef;
338 }
339 else if (t == RUBY_T_FIXNUM) {
340 return RB_FIXNUM_P(obj);
341 }
342 else if (t == RUBY_T_SYMBOL) {
343 return RB_SYMBOL_P(obj);
344 }
345 else if (t == RUBY_T_FLOAT) {
346 return RB_FLOAT_TYPE_P(obj);
347 }
348 else if (RB_SPECIAL_CONST_P(obj)) {
349 return false;
350 }
351 else if (t == RB_BUILTIN_TYPE(obj)) {
352 return true;
353 }
354 else {
355 return false;
356 }
357}
358
374static inline bool
375RB_TYPE_P(VALUE obj, enum ruby_value_type t)
376{
377 if (RBIMPL_CONSTANT_P(t)) {
378 return rbimpl_RB_TYPE_P_fastpath(obj, t);
379 }
380 else {
381 return t == rb_type(obj);
382 }
383}
384
386/* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function
387 * boundary. */
388#if defined(__clang__)
389# undef RB_TYPE_P
390# define RB_TYPE_P(obj, t) \
391 (RBIMPL_CONSTANT_P(t) ? \
392 rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \
393 (RB_TYPE_P)((obj), (t)))
394#endif
395
396/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE
397 * in inline function and caller function
398 * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba
399 */
400#if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0)
401# undef rb_integer_type_p
402# define rb_integer_type_p(obj) \
403 __extension__ ({ \
404 const VALUE integer_type_obj = (obj); \
405 (RB_FIXNUM_P(integer_type_obj) || \
406 (!RB_SPECIAL_CONST_P(integer_type_obj) && \
407 RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \
408 })
409#endif
418static inline bool rbimpl_rtypeddata_p(VALUE obj);
419
431static inline void
432Check_Type(VALUE v, enum ruby_value_type t)
433{
434 if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
435 goto unexpected_type;
436 }
437 else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) {
438 /* Typed data is not simple `T_DATA`, see `rb_check_type` */
439 goto unexpected_type;
440 }
441 else {
442 return;
443 }
444
445 unexpected_type:
446 rb_unexpected_type(v, t);
447}
448
449#endif /* RBIMPL_VALUE_TYPE_H */
Defines RBIMPL_ATTR_ARTIFICIAL.
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition artificial.h:43
#define RBIMPL_ASSERT_OR_ASSUME(expr)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:229
Defines RBIMPL_ATTR_COLD.
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition cold.h:34
Defines RBIMPL_CONSTANT_P.
#define RBIMPL_CONSTANT_P(expr)
Wraps (or simulates) __builtin_constant_p
Definition constant_p.h:35
Tweaking visibility of C variables/functions.
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition dllexport.h:106
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition dllexport.h:97
RBIMPL_ATTR_ENUM_EXTENSIBILITY.
#define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_)
Wraps (or simulates) __attribute__((enum_extensibility))
Defines RBIMPL_ATTR_FORCEINLINE.
#define RBIMPL_ATTR_FORCEINLINE()
Wraps (or simulates) __forceinline.
Definition forceinline.h:37
void rb_unexpected_type(VALUE x, int t)
Fails with the given object's type incompatibility to the type.
Definition error.c:1021
Declares rb_raise().
Defines RBIMPL_HAS_BUILTIN.
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
#define RBIMPL_ASSUME(_)
Wraps (or simulates) __builtin_unreachable.
Definition assume.h:76
Defines RBIMPL_ATTR_PURE.
#define RBIMPL_ATTR_PURE()
Wraps (or simulates) __attribute__((pure))
Definition pure.h:33
#define RBIMPL_ATTR_PURE_UNLESS_DEBUG()
Enables RBIMPL_ATTR_PURE if and only if.
Definition pure.h:38
Defines struct RBasic.
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
Defines enum ruby_special_consts.
C99 shim for <stdbool.h>
Defines VALUE and ID.
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
Definition value_type.h:224
static bool rb_integer_type_p(VALUE obj)
Queries if the object is an instance of rb_cInteger.
Definition value_type.h:203
ruby_value_type
C-level type of an object.
Definition value_type.h:112
@ RUBY_T_SYMBOL
Definition value_type.h:134
@ RUBY_T_MATCH
Definition value_type.h:127
@ RUBY_T_MODULE
Definition value_type.h:117
@ RUBY_T_ICLASS
Hidden classes known as IClasses.
Definition value_type.h:140
@ RUBY_T_MOVED
Definition value_type.h:142
@ RUBY_T_FIXNUM
Integers formerly known as Fixnums.
Definition value_type.h:135
@ RUBY_T_IMEMO
Definition value_type.h:138
@ RUBY_T_NODE
Definition value_type.h:139
@ RUBY_T_OBJECT
Definition value_type.h:115
@ RUBY_T_DATA
Definition value_type.h:126
@ RUBY_T_FALSE
Definition value_type.h:133
@ RUBY_T_UNDEF
Definition value_type.h:136
@ RUBY_T_COMPLEX
Definition value_type.h:128
@ RUBY_T_STRING
Definition value_type.h:119
@ RUBY_T_HASH
Definition value_type.h:122
@ RUBY_T_NIL
Definition value_type.h:131
@ RUBY_T_CLASS
Definition value_type.h:116
@ RUBY_T_ARRAY
Definition value_type.h:121
@ RUBY_T_MASK
Bitmask of ruby_value_type.
Definition value_type.h:144
@ RUBY_T_RATIONAL
Definition value_type.h:129
@ RUBY_T_ZOMBIE
Definition value_type.h:141
@ RUBY_T_BIGNUM
Definition value_type.h:124
@ RUBY_T_TRUE
Definition value_type.h:132
@ RUBY_T_FLOAT
Definition value_type.h:118
@ RUBY_T_STRUCT
Definition value_type.h:123
@ RUBY_T_NONE
Non-object (swept etc.)
Definition value_type.h:113
@ RUBY_T_REGEXP
Definition value_type.h:120
@ RUBY_T_FILE
Definition value_type.h:125