[libcxx-commits] [libcxx] [libc++] Use .set for symbol assignment on Hexagon (PR #211578)
Brian Cain via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 23 08:13:24 PDT 2026
https://github.com/androm3da created https://github.com/llvm/llvm-project/pull/211578
std::__is_function_overridden() defines __impl_ref<_Func>::__impl_ as a local uses asm (`sym = expr`). On Hexagon `=` is the operand assignment operator of the instruction syntax, so the assembler parses that line as an instruction and rejects it:
overridable_function.h:106:11: error: unrecognized instruction
106 | __asm__("%cc0 = %cc1" : : "X"(...), "X"(_Func));
| ^
<inline asm>:1:2: note: instantiated into assembly here
1 | _ZNSt3__110__impl_refIXadL_ZnwjEEE7__impl_Ej = _Znwj
The assembler does accept the similar `.set sym, expr` directive, so let's use that here.
This was encountered in libfuzzer's libc++ - built w/-fno-exceptions.
>From 3e008014c7470fea07fdf89dcdbb3d0bd7e6f649 Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Thu, 23 Jul 2026 09:36:49 -0500
Subject: [PATCH] [libc++] Use .set for symbol assignment on Hexagon
std::__is_function_overridden() defines __impl_ref<_Func>::__impl_ as a local
uses asm (`sym = expr`). On Hexagon `=` is the operand assignment
operator of the instruction syntax, so the assembler parses that line as an
instruction and rejects it:
overridable_function.h:106:11: error: unrecognized instruction
106 | __asm__("%cc0 = %cc1" : : "X"(...), "X"(_Func));
| ^
<inline asm>:1:2: note: instantiated into assembly here
1 | _ZNSt3__110__impl_refIXadL_ZnwjEEE7__impl_Ej = _Znwj
The assembler does accept the similar `.set sym, expr` directive, so
let's use that here.
This was encountered in libfuzzer's libc++ - built w/-fno-exceptions.
---
libcxx/src/include/overridable_function.h | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h
index 307405812f9af..f75a26b4293b1 100644
--- a/libcxx/src/include/overridable_function.h
+++ b/libcxx/src/include/overridable_function.h
@@ -92,16 +92,22 @@ struct __impl_ref<_Func> {
[[gnu::visibility("hidden")]] static _Ret __impl_(_Args...);
};
+# if defined(__hexagon__)
+# define _LIBCPP_ASM_SYMBOL_ASSIGNMENT(__dst, __src) ".set " __dst ", " __src
+# else
+# define _LIBCPP_ASM_SYMBOL_ASSIGNMENT(__dst, __src) __dst " = " __src
+# endif
+
// This takes a function type template argument first so that the second non-type template
// argument (pointer to the public function) gets the benefit of type-aware overload
// resolution, rather than having to use a static_cast.
template <typename T, T* _Func>
_LIBCPP_HIDE_FROM_ABI inline bool __is_function_overridden() noexcept {
-# if !defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2101
- __asm__("%cc0 = %cc1" : : "X"(__impl_ref<_Func>::__impl_), "X"(_Func));
-# else
- __asm__("%c0 = %c1" : : "X"(__impl_ref<_Func>::__impl_), "X"(_Func));
-# endif
+# if !defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2101
+ __asm__(_LIBCPP_ASM_SYMBOL_ASSIGNMENT("%cc0", "%cc1") : : "X"(__impl_ref<_Func>::__impl_), "X"(_Func));
+# else
+ __asm__(_LIBCPP_ASM_SYMBOL_ASSIGNMENT("%c0", "%c1") : : "X"(__impl_ref<_Func>::__impl_), "X"(_Func));
+# endif
// This just has the compiler compare the two symbols. For PIC mode, this will do a
// direct PC-relative materialization for __impl_ref<...>::__impl_ and a GOT load for
// the _Func symbol. The compiler thinks __impl_ref<...>::__impl_ is defined elsewhere
@@ -110,6 +116,8 @@ _LIBCPP_HIDE_FROM_ABI inline bool __is_function_overridden() noexcept {
return __launder_function_pointer(_Func) != __impl_ref<_Func>::__impl_;
}
+# undef _LIBCPP_ASM_SYMBOL_ASSIGNMENT
+
_LIBCPP_END_NAMESPACE_STD
# else // __has_feature(ptrauth_calls)
More information about the libcxx-commits
mailing list