Closed jordancarlin closed 1 month ago
What does riscv64-unknown-elf-gcc -march=help
show?
This is what I get:
/riscv64-unknown-elf-gcc --version
riscv64-unknown-elf-gcc (g04696df0963) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
/riscv64-unknown-elf-gcc -march=help
All available -march extensions for RISC-V:
Name Version
i 2.0, 2.1
e 2.0
m 2.0
a 2.0, 2.1
f 2.0, 2.2
d 2.0, 2.2
c 2.0
v 1.0
h 1.0
zic64b 1.0
zicbom 1.0
zicbop 1.0
zicboz 1.0
ziccamoa 1.0
ziccif 1.0
zicclsm 1.0
ziccrse 1.0
zicntr 2.0
zicond 1.0
zicsr 2.0
zifencei 2.0
zihintntl 1.0
zihintpause 2.0
zihpm 2.0
zmmul 1.0
za128rs 1.0
za64rs 1.0
zawrs 1.0
zfa 1.0
zfh 1.0
zfhmin 1.0
zfinx 1.0
zdinx 1.0
zca 1.0
zcb 1.0
zcd 1.0
zce 1.0
zcf 1.0
zcmp 1.0
zcmt 1.0
zba 1.0
zbb 1.0
zbc 1.0
zbkb 1.0
zbkc 1.0
zbkx 1.0
zbs 1.0
zk 1.0
zkn 1.0
zknd 1.0
zkne 1.0
zknh 1.0
zkr 1.0
zks 1.0
zksed 1.0
zksh 1.0
zkt 1.0
ztso 1.0
zvbb 1.0
zvbc 1.0
zve32f 1.0
zve32x 1.0
zve64d 1.0
zve64f 1.0
zve64x 1.0
zvfbfmin 1.0
zvfh 1.0
zvfhmin 1.0
zvkb 1.0
zvkg 1.0
zvkn 1.0
zvknc 1.0
zvkned 1.0
zvkng 1.0
zvknha 1.0
zvknhb 1.0
zvks 1.0
zvksc 1.0
zvksed 1.0
zvksg 1.0
zvksh 1.0
zvkt 1.0
zvl1024b 1.0
zvl128b 1.0
zvl16384b 1.0
zvl2048b 1.0
zvl256b 1.0
zvl32768b 1.0
zvl32b 1.0
zvl4096b 1.0
zvl512b 1.0
zvl64b 1.0
zvl65536b 1.0
zvl8192b 1.0
zhinx 1.0
zhinxmin 1.0
smaia 1.0
smepmp 1.0
smstateen 1.0
ssaia 1.0
sscofpmf 1.0
ssstateen 1.0
sstc 1.0
svinval 1.0
svnapot 1.0
svpbmt 1.0
xcvalu 1.0
xcvbi 1.0
xcvelw 1.0
xcvmac 1.0
xcvsimd 1.0
xtheadba 1.0
xtheadbb 1.0
xtheadbs 1.0
xtheadcmo 1.0
xtheadcondmov 1.0
xtheadfmemidx 1.0
xtheadfmv 1.0
xtheadint 1.0
xtheadmac 1.0
xtheadmemidx 1.0
xtheadmempair 1.0
xtheadsync 1.0
xtheadvector 1.0
xventanacondops 1.0
The Q/q
extension is not listed there by default so I guess that (since GCC 14?) you may need to explicitly enable such support in the toolchain at configuration and build time?
So far I have been unable to identify a GCC patch on the mailing list that might have caused this change in behaviour between GCC 13 and 14.
Maybe this is relevant...?
But that change dates back 8 years or so...
@cmuellner or @kito-cheng - would you happen to know what patches/changes caused this situation? And why? So far my searches of the patches mailing list for possible candidates/suspects have yielded nothing.
FWIW neither is the Q/q
extension listed as an option for -march=...
in the GCC documentation:
Nor is any Q/q
based ABI listed there either.
I wonder if this gives a clue?
Maybe when Q/q
was accepted it was just at the front and but nothing useful happened at the back end and consequently support was removed? Perhaps until hardware implementing Q
is available and work is done on GCC to properly support it?
@jordancarlin - with GCC 13 did the compiler ever generate any Q/q
instructions for you when that extension was included in the architecture specified?
The update from GCC 13 to GCC 14 seems to have broken the Q extension. Prior to #1531 including q in the march string worked correctly and compiled quad-precision floating-point instructions. Now it fails before it even begins compiling while checking march. If q is left out of the march string it (unsurprisingly) fails on unrecognized instructions when it hits a q instruction in an assembly file. The exact error message is below.
Looking into the history of gcc/config/riscv/riscv.cc
in GCC, I can't see that there was ever Q support in the GCC's RISC-V backend (e.g. look into the FP moves in riscv_output_move()
).
That said, GCC releases before GCC 14 indeed accepted q
as part of the march
string. This was likely addressed (I would even say fixed) by cleanup in the corresponding parser code (gcc/common/config/riscv/riscv-common.cc
) in January 2024. Now only those extensions are accepted, that are indeed supported (i.e., if they are listed in riscv_ext_version_table
).
Note, that Binutils has "Q" support (there is an entry for "q" in bfd/elfxx-riscv.c
). This explains why it looked like the GNU toolchain had "Q" support.
@TommyMurphyTM1234 @cmuellner Thanks for helping look into this. I know that Q was never listed in the march help documentation. When using Q with gcc 13 it was with assembly files, so GCC wasn’t generating any Q instructions from C, but it was able to compile them into an elf file. If this small amount of support was removed since there was no corresponding backend, what is the best path forward for assembly files that contain Q instructions? https://github.com/openhwgroup/cvw implements Q support, so our tool flow for compiling tests breaks with GCC 14 at the moment.
Would it work for you to use the assembler instead of the compiler (e.g. riscv64-unknown-linux-gnu-as -o test.o test.s
)?
I'm not as familiar with using the assembler directly so will need to look into it and get back to you. Thanks for the idea.
I'm not as familiar with using the assembler directly so will need to look into it and get back to you. Thanks for the idea.
You just invoke the assembler directly, as @cmuellner suggested by calling riscv64-unknown-elf-as
directly rather than via the GCC front end riscv64-unknown-elf-gcc
. The latter is normally the recommended way but there can be situations (such as this) where you might need to manually invoke specific tools directly.
The documentation for the assembler is here:
(Thanks for the clarifying info @cmuellner! 👍).
Yes. Just switching to riscv64-unknown-elf-as
instead of riscv64-unknown-elf-gcc
seems to have dramatically changed what is being output, so investigating why that is.
I suspect it has to do with a file that is #included and the assembler not supporting linking. It looks like I will need to directly call the linker first before using the assembler.
I suspect it has to do with a file that is #included and the assembler not supporting linking. It looks like I will need to directly call the linker first before using the assembler.
That doesn't make sense. Linking is the last step in compiling a program and comes before compilation and assembling. Why would you be calling the linker before the assembler and why would that help at all?
Maybe provide a small self-contained test case and people will be able to advise.
Just for completeness on the original issue, this fails:
git clone https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=`pwd`/installed-tools --with-arch=rv64gcq
make 2>&1 | tee build.log
...
cp doc/gcc.1 doc/g++.1
/home/user/issue-1586/build-gcc-newlib-stage1/./gcc/xgcc -B/home/user/issue-1586/build-gcc-newlib-stage1/./gcc/ -xc -nostdinc /dev/null -S -o /dev/null -fself-test=../.././gcc/gcc/testsuite/selftests
xgcc: error: '-march=rv64imafdqc_zicsr_zifencei': extension 'q' is unsupported standard single letter extension
xgcc: error: '-march=rv64imafdqc_zicsr_zifencei': extension 'q' is unsupported standard single letter extension
make[2]: *** [../.././gcc/gcc/c/Make-lang.in:153: s-selftest-c] Error 1
rm gfdl.pod gcc.pod gcov-dump.pod gcov-tool.pod fsf-funding.pod gpl.pod cpp.pod gcov.pod lto-dump.pod
make[2]: Leaving directory '/home/user/issue-1586/build-gcc-newlib-stage1/gcc'
make[1]: *** [Makefile:4689: all-gcc] Error 2
make[1]: Leaving directory '/home/user/issue-1586/build-gcc-newlib-stage1'
make: *** [Makefile:651: stamps/build-gcc-newlib-stage1] Error 2
build.log
: build.log@TommyMurphyTM1234 With GCC 13 we were using the following command in a Makefile to compile tests. I've included one of the simple tests along with the linker script below. The included test doesn't actually have a Q instruction in it because that is a much more complicated test, but should be able to compile with the same options.
%.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile
riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom_zbkb_zbkx_zknd_zkne_zknh -mabi=lp64 -mcmodel=medany -nostartfiles -Tlink.ld $<
I changed the Makefile to use the command below, but get a very different result now. I assume this is because it is not using the linker script. Sorry if that was unclear before.
%.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile
riscv64-unknown-elf-as -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom_zbkb_zbkx_zknd_zkne_zknh -mabi=lp64 $<
I suspect it has to do with a file that is #included and the assembler not supporting linking. It looks like I will need to directly call the linker first before using the assembler.
That doesn't make sense. Linking is the last step in compiling a program and comes before compilation and assembling. Why would you be calling the linker before the assembler and why would that help at all?
Oops. Meant after the assembler
@TommyMurphyTM1234 With GCC 13 we were using the following command in a Makefile to compile tests. I've included one of the simple tests along with the linker script below. The included test doesn't actually have a Q instruction in it because that is a much more complicated test, but should be able to compile with the same options.
%.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom_zbkb_zbkx_zknd_zkne_zknh -mabi=lp64 -mcmodel=medany -nostartfiles -Tlink.ld $<
I changed the Makefile to use the command below, but get a very different result now. I assume this is because it is not using the linker script. Sorry if that was unclear before.
%.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile riscv64-unknown-elf-as -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom_zbkb_zbkx_zknd_zkne_zknh -mabi=lp64 $<
You should probably try changing it with GCC 13 first to ensure that you get the same results with your original Makefile
which just calls gcc
and the modified one that calls as
and ld
separately. Once you have the same results doing that then you know what to do for GCC 14.
Your modified version ONLY seems to call as
? You need to manually call as
for each assembly language source file that has Q
instructions in order to create the corresponding object file. You then need to call ld
(or the gcc
front end) to link these any any other object files, libraries and startup code etc. into a complete ELF file.
(I'm using as
, ld
and gcc
as shorthands for the RISC-V versions here).
Thanks for all the help. Our Q tests are working now. I ended up having to run just the preprocessor of gcc first to handle the #includes, then the assembler for the files that depend on Q, and finally the linker.
The update from GCC 13 to GCC 14 seems to have broken the Q extension. Prior to #1531 including q in the march string worked correctly and compiled quad-precision floating-point instructions. Now it fails before it even begins compiling while checking march. If q is left out of the march string it (unsurprisingly) fails on unrecognized instructions when it hits a q instruction in an assembly file. The exact error message is below.