Revert "toolchain: gcc: Simplify `GEN_ABSOLUTE_SYM` and `GEN_ABSOLUTE_SYM_KCONFIG`"

This reverts commit 87779e73f8.

Commit 87779e73f8 ("toolchain: gcc: Simplify GEN_ABSOLUTE_SYM and
GEN_ABSOLUTE_SYM_KCONFIG") "unified the variants from using a
target-specific dialects to a target-agnostic solution". While reducing
duplication is always desired, this "unification" got rid of some
differences between architectures. Among others, this commit generalized
the use of the `c` constant operand modifier in the `GEN_ABSOLUTE_SYM()`
macro. Before this commit, the `c` modifier was NOT in use in a number
of architectures!

Generally speaking, reducing copy/paste/diverge must always be performed
in _two_ distinct phases with ample testing time between the two phases:

1. First, perform functional changes that remove the divergence.

   < give plenty enough time for testing >

2. Finally, remove the identical copies.

More specifically, I understand the `c` modifier may be required by some
architectures, but it's causing problems on other(s). Notably, it broke
the build with one pre-C11, gcc-based Xtensa toolchain:

```
14:03:17 kernel_offsets.h: Assembler messages:
14:03:17 kernel_offsets.h:28: Error: bad expression
14:03:17 kernel_offsets.h:28: Error: junk at end of line,
                                first unrecognized character is `c'
14:03:17 kernel_offsets.h:29: Error: bad expression
14:03:17 kernel_offsets.h:29: Error: junk at end of line,
                                first unrecognized character is `c'
...
```

While newer Xtensa toolchains accept `c`, they also ignore it. `c` makes
no difference whatsoever with all the (working) Xtensa toolchains I
tested. So for `Xtensa`, `c` is a best useless and at worse breaking the
build.

Up to gcc version 12 (2022), the `c` constant modifier was documented as
X86-specific!
https://gcc.gnu.org/onlinedocs/gcc-12.3.0/gcc/Extended-Asm.html#x86Operandmodifiers

Only starting with gcc version 13 (2023), the `c` modifier was
officially supported as "generic":
https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Extended-Asm.html#Generic-Operand-Modifiers

`c` was very likely working with other architectures before 2023, but
not officially and we don't know which architectures and we don't know
when.

Note toolchain/gcc.h is included by toolchain/llvm.h and also used by
clang. The status of `c` across clang versions is unknown.

While I personally hate copy/paste/diverge with a passion, these macros
GEN_ABSOLUTE_SYM() and GEN_ABSOLUTE_SYM_KCONFIG() are very small so that
particular duplication is very reasonable. Architecture-specific code is
tricky and portability across toolchain and toolchain versions even
more. Testing low-level changes like this across different architectures
would also require demanding and unlikely coordination across different
architectures/companies.

Signed-off-by: Marc Herbert <marc.herbert@intel.com>
This commit is contained in:
Marc Herbert 2024-04-12 18:11:26 +00:00 committed by Anas Nashif
parent 51d80a9838
commit 89493ee56b
1 changed files with 76 additions and 43 deletions

View File

@ -489,52 +489,85 @@ do { \
* to generate named symbol/value pairs for kconfigs.
*/
#if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_ARC) || defined(CONFIG_ARM64) || \
defined(CONFIG_NIOS2) || defined(CONFIG_XTENSA) || defined(CONFIG_MIPS) || \
defined(CONFIG_ARCH_POSIX) || defined(CONFIG_SPARC)
#if defined(CONFIG_ARM)
#define GEN_ABSOLUTE_SYM(name, value) \
do { \
__asm__(".global " #name); \
__asm__(".set " #name ", %c0" ::"n"(value)); \
__asm__(".type " #name ", STT_OBJECT"); \
} while (false)
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
do { \
__asm__(".global " #name); \
__asm__(".set " #name ", " #value); \
__asm__(".type " #name ", STT_OBJECT"); \
} while (false)
/* The following is a workaround for the RISC-V target, which
* has a bug so it errors out on the target-agnostic '%c'.
*
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112434
*
* > error: invalid 'asm': invalid use of '%c'
*
* According to commit cd83e85edc5d741f6b52c6b5995303c30bda443a,
* '%0' is equivalent to '%c0' for the RISC-V target. We use
* this as a workaround for now.
*
* This workaround should be removed when the above bug is fixed
* in all supported Zephyr toolchain versions.
/*
* GNU/ARM backend does not have a proper operand modifier which does not
* produces prefix # followed by value, such as %0 for PowerPC, Intel, and
* MIPS. The workaround performed here is using %B0 which converts
* the value to ~(value). Thus "n"(~(value)) is set in operand constraint
* to output (value) in the ARM specific GEN_OFFSET macro.
*/
#elif defined(CONFIG_RISCV)
#define GEN_ABSOLUTE_SYM(name, value) \
do { \
__asm__(".global " #name); \
__asm__(".set " #name ", %0" ::"n"(value)); \
__asm__(".type " #name ", STT_OBJECT"); \
} while (false)
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
do { \
__asm__(".global " #name); \
__asm__(".set " #name ", " #value); \
__asm__(".type " #name ", STT_OBJECT"); \
} while (false)
#define GEN_ABSOLUTE_SYM(name, value) \
__asm__(".globl\t" #name "\n\t.equ\t" #name \
",%B0" \
"\n\t.type\t" #name ",%%object" : : "n"(~(value)))
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__asm__(".globl\t" #name \
"\n\t.equ\t" #name "," #value \
"\n\t.type\t" #name ",%object")
#elif defined(CONFIG_X86)
#define GEN_ABSOLUTE_SYM(name, value) \
__asm__(".globl\t" #name "\n\t.equ\t" #name \
",%c0" \
"\n\t.type\t" #name ",@object" : : "n"(value))
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__asm__(".globl\t" #name \
"\n\t.equ\t" #name "," #value \
"\n\t.type\t" #name ",@object")
#elif defined(CONFIG_ARC) || defined(CONFIG_ARM64)
#define GEN_ABSOLUTE_SYM(name, value) \
__asm__(".globl\t" #name "\n\t.equ\t" #name \
",%c0" \
"\n\t.type\t" #name ",@object" : : "n"(value))
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__asm__(".globl\t" #name \
"\n\t.equ\t" #name "," #value \
"\n\t.type\t" #name ",@object")
#elif defined(CONFIG_NIOS2) || defined(CONFIG_RISCV) || \
defined(CONFIG_XTENSA) || defined(CONFIG_MIPS)
/* No special prefixes necessary for constants in this arch AFAICT */
#define GEN_ABSOLUTE_SYM(name, value) \
__asm__(".globl\t" #name "\n\t.equ\t" #name \
",%0" \
"\n\t.type\t" #name ",%%object" : : "n"(value))
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__asm__(".globl\t" #name \
"\n\t.equ\t" #name "," #value \
"\n\t.type\t" #name ",%object")
#elif defined(CONFIG_ARCH_POSIX)
#define GEN_ABSOLUTE_SYM(name, value) \
__asm__(".globl\t" #name "\n\t.equ\t" #name \
",%c0" \
"\n\t.type\t" #name ",@object" : : "n"(value))
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__asm__(".globl\t" #name \
"\n\t.equ\t" #name "," #value \
"\n\t.type\t" #name ",@object")
#elif defined(CONFIG_SPARC)
#define GEN_ABSOLUTE_SYM(name, value) \
__asm__(".global\t" #name "\n\t.equ\t" #name \
",%0" \
"\n\t.type\t" #name ",#object" : : "n"(value))
#define GEN_ABSOLUTE_SYM_KCONFIG(name, value) \
__asm__(".globl\t" #name \
"\n\t.equ\t" #name "," #value \
"\n\t.type\t" #name ",#object")
#else
#error processor architecture not supported