Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
fix ruby 3.3 crash on sparc64 with gcc15
To:
Jeremy Evans <jeremy@openbsd.org>, ports@openbsd.org
Date:
Wed, 26 Nov 2025 14:18:17 +0100

Download raw body.

Thread
Long story short gcc15 misscompiles rstring.h in ruby 3.3 and causes
miniruby to crash during build.

I found https://bugs.ruby-lang.org/issues/21655 and especially
https://github.com/ruby/ruby/pull/15113 which workaround the gcc15
misscompilation.

With this ruby3.3 builds and seems to work well enough.
ruby 3.4 should have the same bug but the compiler is tickled by something
and does not do the bad optimisation. The diff was committed to the
ruby master branch so I think it will show up in an upcomming release.

-- 
:wq Claudio

Index: Makefile
===================================================================
RCS file: /cvs/ports/lang/ruby/3.3/Makefile,v
diff -u -p -r1.18 Makefile
--- Makefile	24 Oct 2025 13:26:13 -0000	1.18
+++ Makefile	26 Nov 2025 13:10:02 -0000
@@ -1,4 +1,5 @@
 VERSION =		3.3.10
+REVISION =		0
 DISTNAME =		ruby-${VERSION}
 PKGNAME-main =		ruby-${VERSION}
 PKGNAME-ri_docs =	ruby${BINREV}-ri_docs-${VERSION}
Index: patches/patch-include_ruby_internal_core_rstring_h
===================================================================
RCS file: patches/patch-include_ruby_internal_core_rstring_h
diff -N patches/patch-include_ruby_internal_core_rstring_h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-include_ruby_internal_core_rstring_h	25 Nov 2025 19:38:45 -0000
@@ -0,0 +1,98 @@
+gcc15 workaround: https://github.com/ruby/ruby/pull/15113
+
+Index: include/ruby/internal/core/rstring.h
+--- include/ruby/internal/core/rstring.h.orig
++++ include/ruby/internal/core/rstring.h
+@@ -369,43 +369,8 @@ RSTRING_LEN(VALUE str)
+     return RSTRING(str)->len;
+ }
+ 
+-RBIMPL_WARNING_PUSH()
+-#if RBIMPL_COMPILER_IS(Intel)
+-RBIMPL_WARNING_IGNORED(413)
+-#endif
+-
+-RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+ RBIMPL_ATTR_ARTIFICIAL()
+ /**
+- * @private
+- *
+- * "Expands" an embedded  string into an ordinal one.  This  is a function that
+- * returns aggregated type.   The returned struct always  has its `as.heap.len`
+- * an `as.heap.ptr` fields set appropriately.
+- *
+- * This is an implementation detail that 3rd parties should never bother.
+- */
+-static inline struct RString
+-rbimpl_rstring_getmem(VALUE str)
+-{
+-    RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING);
+-
+-    if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) {
+-        return *RSTRING(str);
+-    }
+-    else {
+-        /* Expecting compilers to optimize this on-stack struct away. */
+-        struct RString retval = {RBASIC_INIT};
+-        retval.len = RSTRING_LEN(str);
+-        retval.as.heap.ptr = RSTRING(str)->as.embed.ary;
+-        return retval;
+-    }
+-}
+-
+-RBIMPL_WARNING_POP()
+-
+-RBIMPL_ATTR_ARTIFICIAL()
+-/**
+  * Queries the contents pointer of the string.
+  *
+  * @param[in]  str  String in question.
+@@ -415,7 +380,9 @@ RBIMPL_ATTR_ARTIFICIAL()
+ static inline char *
+ RSTRING_PTR(VALUE str)
+ {
+-    char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr;
++    char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ?
++        RSTRING(str)->as.heap.ptr :
++        RSTRING(str)->as.embed.ary;
+ 
+     if (RUBY_DEBUG && RB_UNLIKELY(! ptr)) {
+         /* :BEWARE: @shyouhei thinks  that currently, there are  rooms for this
+@@ -441,14 +408,17 @@ RBIMPL_ATTR_ARTIFICIAL()
+ static inline char *
+ RSTRING_END(VALUE str)
+ {
+-    struct RString buf = rbimpl_rstring_getmem(str);
++    char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ?
++       RSTRING(str)->as.heap.ptr :
++        RSTRING(str)->as.embed.ary;
++    long len = RSTRING_LEN(str);
+ 
+-    if (RUBY_DEBUG && RB_UNLIKELY(! buf.as.heap.ptr)) {
++    if (RUBY_DEBUG && RB_UNLIKELY(!ptr)) {
+         /* Ditto. */
+         rb_debug_rstring_null_ptr("RSTRING_END");
+     }
+ 
+-    return &buf.as.heap.ptr[buf.len];
++    return &ptr[len];
+ }
+ 
+ RBIMPL_ATTR_ARTIFICIAL()
+@@ -477,16 +447,7 @@ RSTRING_LENINT(VALUE str)
+  * @param  ptrvar  Variable where its contents is stored.
+  * @param  lenvar  Variable where its length is stored.
+  */
+-#ifdef HAVE_STMT_AND_DECL_IN_EXPR
+ # define RSTRING_GETMEM(str, ptrvar, lenvar) \
+-    __extension__ ({ \
+-        struct RString rbimpl_str = rbimpl_rstring_getmem(str); \
+-        (ptrvar) = rbimpl_str.as.heap.ptr; \
+-        (lenvar) = rbimpl_str.len; \
+-    })
+-#else
+-# define RSTRING_GETMEM(str, ptrvar, lenvar) \
+     ((ptrvar) = RSTRING_PTR(str),           \
+      (lenvar) = RSTRING_LEN(str))
+-#endif /* HAVE_STMT_AND_DECL_IN_EXPR */
+ #endif /* RBIMPL_RSTRING_H */