GCC 7.1.1 RISCV compilation (link) failures, incompatible ABI - gcc

I'm having difficulty doing basic compilation & link for RISCV on the latest GCC for RISCV on a windows 7-64bit platform.
Tools installed: 7.1.1-2-20170912-2255 gotten from https://github.com/gnu-mcu-eclipse/riscv-none-gcc/releases/
Platform: Windows 7, 64 bit, no cygwin
Program:
#include <stdint.h>
int32_t iBlahblah;
int main (void)
{
while(1)
iBlahblah++;
return 0;
}
Command line:
"c:\Program Files\GNU MCU Eclipse\RISC-V Embedded GCC\7.1.1-2-20170912-2255\bin\riscv64-unknown-elf-gcc.exe" -c hello.c -o hello -march=rv32imac -mabi=ilp32 -Os
"c:\Program Files\GNU MCU Eclipse\RISC-V Embedded GCC\7.1.1-2-20170912-2255\bin\riscv64-unknown-elf-gcc.exe" -o hello.elf -march=rv32imac -mabi=ilp32 -Os -Wl,-Map=hello.lst hello.o
Output:
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: hello.o: ABI is incompatible with that of the selected emulation: target emulation `elf64-littleriscv' does not match `elf32-littleriscv'
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: failed to merge target specific data of file hello.o
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/lib/rv32imac/ilp32\libg.a(lib_a-exit.o): In function `.L0 ': exit.c:(.text.exit+0x1e): undefined reference to `_exit'
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: hello.elf(.text): relocation "iBlahblah+0x0 (type R_RISCV_HI20)" goes out of range
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: hello.o: file class ELFCLASS64 incompatible with ELFCLASS32
c:/program files/gnu mcu eclipse/risc-v embedded gcc/7.1.1-2-20170912-2255/bin/../lib/gcc/riscv64-unknown-elf/7.1.1/../../../../riscv64-unknown-elf/bin/ld.exe: final link failed: File in wrong format
collect2.exe: error: ld returned 1 exit status
The big question is how do I resolve the "ABI is incompatible with that of the selected emulation"? We can ignore the other issues regarding relocation, exit, etc. because my larger build environment takes care of that (it builds for many platforms, just not RISCV at the moment).

riscv64-unknown-elf-gcc.exe -c hello.c -o hello -march=rv32imac -mabi=ilp32 -Os
This part is wrong. Your gcc tolchain docs says https://gnu-mcu-eclipse.github.io/toolchain/riscv/
riscv64-unknown-elf-gcc vs riscv32-unknown-elf-gcc
With lots of architectures and systems supported, GCC recommends prefixing the binaries with a unique tuple:
<arch>-<vendor>-<os>-<libc/abi>-
The current RISC-V prefixes for the bare metal toolchains are riscv64-unknown-elf- and riscv32-unknown-elf-.
Well, don’t be confused by this unfortunate names. The 64 or 32 attached to the architecture ... It does not mean either that the compiler produces 64-bits or 32-bits RISC-V binaries. Actually, the compilers produce both 32/64-bits binaries, based on -march and -mabi. The only difference are defaults, when the compiler are invoked without the -march and -mabi explicitly set on the command line.
Try to use riscv32-unknown-elf-gcc.exe for compiling programs for 32-bit riscv platform (with arch & abi having r32 & 32 parts in their names), it should use correct 32-bit CRT files.
There is some support for multilib, when riscv64 will search for 32-bit libs (https://gnu-mcu-eclipse.github.io/toolchain/riscv/#multiple-libraries, https://gnu-mcu-eclipse.github.io/blog/2017/09/13/riscv-none-gcc-v7-1-1-2-20170912-released/, https://gcc.gnu.org/onlinedocs/gccint/Target-Fragment.html MULTILIB_OPTIONS), but something was wrong. Please, post gcc -v .... -o your_program.bin results for riscv32 compiler, riscv64 compiler and several march/mabi combinations.

Related

link time warning about VPF registers

I'm trying to port a project from Cortex M0 to Cortex M4 with hardware floating point extension, the new target soc is nRF52832.
The error I am getting from the linker is the following
arm-unknown-eabi/bin/ld: error: x.o uses VFP register arguments, firmware does not
where firmware is the name of the output file fro the linker.
This is an issue with the arm ABI for floating point, I want to use the FPU as it is requested by
the FreeRTOS port I want to use but I don't get how to tweak my linker flags to make it possible.
This is the set of linker flags I'm currently using
-L/path/to/nrfx/mdk
-Wl, --no-undefined
-Wl,--as-needed -march=armv7e-m+fp -mthumb -mfloat-abi=hard -mabi=aapcs
-Wl, --start-group support/libs/libQRCode.a support/libs/libSPIFFS.a
-Wl, --no-undefined
-Wl, --as-needed
-Wl, --gc-sections --specs=nosys.specs -T/path/to/linker_script.ld /toolchain/path/to/lib/libm.a
-Wl, --end-group
The -mfloat-abi flag is a compiler-only flag, so there is no point in passing it to the linker.
In order to be able to build a firmware image that uses the hard-float ABI, all object files passed to the linker must be compiled to use that ABI. You issue is most likely due to the fact that you are passing to the linker one or more object files compiled with the soft-float ABI instead; for example, the /toolchain/path/to/lib/libm.a file path in your linker command line looks suspicious, you should use the hard-float version of libm.a, which you will likely find in the hard/ sub-folder of your toolchain library path.

How can I compile with LLVM/Clang to RISC-V target?

I want to compile a simple program "int main(){return 0;}" to RISC-V processor.
LLVM/Clang version is 9.0 and I want to run the compiled program with a RISC-V simulator like this https://github.com/riscv/riscv-tools
My problem is that I can't list the clang supported targets only the LLC-s whith these commands:
llc --version
llc -march=xxARCHTYPExx -mattr=help
And there is no any type of riscv processor listed.
So I tried to look the triple file: llvm-project\llvm\include\llvm\ADT\Triple.h
and try a command like: clang hello.c -target riscv32 -march=rv32imafd
But I get the following error:
error: unable to create target: 'No available targets are compatible
with triple "riscv32"'
Can somebody help me to how get a valid RISC-V target? I just simple can't compile the program but I know LLVM has a RISC-V support.
LLVM 9 release notes explicitly state that RISC-V support was promoted from experimental to official.
And indeed, on my Fedora 31 machine, the LLVM 9 Fedora package does support RISC-V:
$ llvm-objdump --version | grep riscv
riscv32 - 32-bit RISC-V
riscv64 - 64-bit RISC-V
Also, I can create RISC-V binary code with the LLVM toolchain:
$ clang --target=riscv64 -march=rv64gc rotate.s -c -o rotate.o
$ file rotate.o
rotate.o: ELF 64-bit LSB relocatable, UCB RISC-V, version 1 (SYSV), not stripped
Although it doesn't include a libc for RISC-V targets:
$ clang --target=riscv64 -march=rv64gc hello-world.c -o hello-world
hello-world.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
^~~~~~~~~
1 error generated.
However, you don't really need one - you could directly call syscalls for your hello world, e.g.:
$ clang --target=riscv64 -march=rv64gc hello.s -c -o hello.o
$ ld.lld hello.o -o hello
$ spike --isa=RV64gc ~/local/riscv/pk/riscv64-unknown-elf/bin/pk ./hello
bbl loader
Hello World
I don't use clang for linking because it seems that I can't convince clang with -fuse-ld to use another linker besides /usr/bin/ld.

OpenMP not available on mac with gcc 4.9

The OpenMP website says: "GCC 4.9 supports OpenMP 4.0 for C/C++".
I'm using gcc 4.9.1 from brew, yet I see this error when I try to compile liblinear: omp.h file not found.
Specifically:
Compiling liblinear version 1.93
Source code page:
http://www.csie.ntu.edu.tw/~cjlin/liblinear/
external/liblinear-1.93_multicore/matlab/train.cpp:7:10: fatal error: 'omp.h' file not found
#include <omp.h>
^
1 error generated.
mex: compile of ' "external/liblinear-1.93_multicore/matlab/train.cpp"' failed.
Here's the matlab code used to compile liblinear, which contains a file that contains #include <omp.h>:
% Compile liblinear
if ~exist('liblinear_train')
fprintf('Compiling liblinear version 1.93\n');
fprintf('Source code page:\n');
fprintf(' http://www.csie.ntu.edu.tw/~cjlin/liblinear/\n');
mex -outdir bin ...
COMPFLAGS="$COMPFLAGS -fopenmp" -largeArrayDims ...
external/liblinear-1.93_multicore/matlab/train.cpp ...
external/liblinear-1.93_multicore/matlab/linear_model_matlab.cpp ...
external/liblinear-1.93_multicore/linear.cpp ...
external/liblinear-1.93_multicore/tron.cpp ...
"external/liblinear-1.93_multicore/blas/*.c" ...
-output liblinear_train;
end`
UPDATE
I changed the gcc version in mexopts.sh (side note: I copied it from /Applications/MATLAB_R2013a_Student.app/bin/mexopts.sh to ~/.matlab/R2013a). Specifically, I changed CC=xcrun -sdk macosx10.9 clang to CC='gcc-4.9'.
I think Matlab does indeed use this compiler, because when I run this code:
if ~exist('anigauss')
fprintf('Compiling the anisotropic gauss filtering of:\n');
fprintf(' J. Geusebroek, A. Smeulders, and J. van de Weijer\n');
fprintf(' Fast anisotropic gauss filtering\n');
fprintf(' IEEE Transactions on Image Processing, 2003\n');
fprintf('Source code/Project page:\n');
fprintf(' http://staff.science.uva.nl/~mark/downloads.html#anigauss\n\n');
mex -Dchar16_t=uint16_T -outdir bin ...
selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c ...
selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss.c ...
-output anigauss
end
Matlab prints:
dyld: Library not loaded: /usr/local/opt/mpfr2/lib/libmpfr.1.dylib
Referenced from: /usr/local/Cellar/gcc49/4.9.1/libexec/gcc/x86_64-apple-darwin14.0.0/4.9.1/cc1
Reason: Incompatible library version: cc1 requires version 4.0.0 or later, but libmpfr.1.dylib provides version 3.0.0
gcc-4.9: internal compiler error: Trace/BPT trap: 5 (program cc1)
/Applications/MATLAB_R2013a_Student.app/bin/mex: line 1343: 77128 Abort trap: 6 gcc-4.9 -c -I/Applications/MATLAB_R2013a_Student.app/extern/include -I/Applications/MATLAB_R2013a_Student.app/simulink/include -DMATLAB_MEX_FILE -fno-common -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -mmacosx-version-min=10.9 -fexceptions -Dchar16_t=uint16_T -DMX_COMPAT_32 -O2 -DNDEBUG "selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c" -o bin/anigauss_mex.o
mex: compile of ' "selective_search/SelectiveSearchCodeIJCV/Dependencies/anigaussm/anigauss_mex.c"' failed.
Yet when I try to compile liblinear, I get the very same error message as usual.
COMPFLAGS="$COMPFLAGS /openmp" -largeArrayDims ...
^^^^^^^
This was probably written for Microsoft Visual C/C++ or for Intel C/C++ Compiler on Windows. Unix systems, including OS X, traditionally use - to denote command line flags.
To enable OpenMP support in GCC you should change /openmp to -fopenmp in the compiler flags COMPFLAGS.
It appears that in addition to passing the wrong OpenMP flag, mex is using the wrong compiler. Compare the error outputs from GCC and Clang:
GCC
foo.c:1:25: fatal error: nonexistent.h: No such file or directory
#include <nonexistent.h>
^
compilation terminated.
Clang
foo.c:1:10: fatal error: 'nonexistent.h' file not found
#include <nonexistent.h>
^
1 error generated.
Clang, or at least the version that Apple ships with Xcode, does not support OpenMP. Consult the MATLAB documentation of the mex command on how to select a different compiler. Basically, you have to execute:
mex -setup
If MATLAB detects several usable compilers, it should present you with the ability to pick one of them. Unfortunately, according to this table, MATLAB might not support GCC on OS X (at least it is not listed in the table).

Should gcc builtins always be resolved during the compilation step, or the linker step?

In running gcc 3.4.3 on a Solaris 5.11 box I see that builtin functions are left undefined during compilation, but are resolved against libgcc.a when the Solaris linker links against libgcc.a.
On gcc 4.5.2 on another Solaris box, the same builtin functions are resolved during compilation of the .o, and the linker isn't concerned about them.
A boiled down example file compiled on gcc 3.4.3:
# cat ctzll.c
int func(unsigned long long x)
{
return __builtin_ctzll(x);
}
# cat main.c
int main(void)
{
return func(0xc0ffee);
}
First compile ctzll.c, and check the symbols:
# nm ctzll.o
U __ctzdi2
0000000000000000 T func
Now compile main.c, and link the objects:
# gcc -m64 main.c -c
# gcc -m64 ctzll.o main.o -v
Reading specs from /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/specs
Configured with: /build/i386/components/gcc3/gcc-3.4.3/configure --prefix=/usr/sfw --mandir=/usr/sfw/share/man --infodir=/usr/sfw/share/info --without-gnu-ld --with-ld=/usr/bin/ld --enable-languages=c,c++,f77,objc --enable-shared --with-gnu-as --with-as=/usr/gnu/bin/as
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-20050802)
/usr/sfw/libexec/gcc/i386-pc-solaris2.11/3.4.3/collect2 -V -Y P,/lib/64:/usr/lib/64:/usr/sfw/lib/64 -R /lib/64:/usr/lib/64:/usr/sfw/lib/64 -Qy /usr/lib/amd64/crt1.o /usr/lib/amd64/crti.o /usr/lib/amd64/values-Xa.o /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtbegin.o -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64 -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/../../../amd64 -L/lib/amd64 -L/usr/lib/amd64 ctzll.o main.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtend.o /usr/lib/amd64/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.2276
# nm a.out | grep ctz
0000000000400fd0 T __ctzdi2
So, if I understand correctly, the Solaris linker resolved __ctzdi2 (the internal representation of __builtin_ctzll).
Now, compile with gcc 4.5.2 on the other Solaris machine:
#gcc -m64 ctzll.c -c
# nm ctzll.o
0000000000000000 T func
The symbol has been resolved fine in the object file, and it has been inlined into the .o assembly as:
8: 48 0f bc 45 f8 bsf -0x8(%rbp),%rax
Is the 3.4.3 compiler behaving correctly? I'd have expected the actual compilation to handle the builtins, like 4.5.2, by referencing the 64 bit version of libgcc.a. The lack of uniformity across the compilers is causing upstream problems in my project as the builtin remains undefined and the linker isn't resolving the symbols as I'm not linking against the OS specific 64 bit libraries (libgcc.a). I'm not sure if the 3.4.3 compiler is misconfigured causing the .o files to have undefined builtin functions caught by linking, or if the newer compilers are just smarter and I need to add the 64 bit libraries to the linker to handler the older compiler.
The 3.4.3 seems to show a valid libgcc.a which contains the definition of _ctzdi2:
# gcc -m64 -print-libgcc-file-name
/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a
# nm /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a | grep ctzdi2
0000000000000000 T __ctzdi2
_ctzdi2.o:
The whole point of libgcc.a is to implement builtin operations that gcc can't emit code for (which includes not only __builtin_ functions, but also things like 'long long' math operations on some 32-bit platforms).
Obviously the newer gcc got smarter about emitting code.

Link error when compiling gcc atomic operation in 32-bit mode

I have the following program:
~/test> cat test.cc
int main()
{
int i = 3;
int j = __sync_add_and_fetch(&i, 1);
return 0;
}
I'm compiling this program using GCC 4.2.2 on Linux running on a multi-cpu 64-bit Intel machine:
~/test> uname --all
Linux doom 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
When I compile the program in 64-bit mode, it compiles and links fine:
~/test> /share/tools/gcc-4.2.2/bin/g++ test.cc
~/test>
When I compile it in 32-bit mode, I get the following error:
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccEVHGkB.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test>
Although I will never actually run on a 32-bit processor, I do need a 32-bit executable so I can link with some 32-bit libraries.
My 2 questions are:
Why do I get a link error when I compile in 32-bit mode?
Is there some way to get the program to compile and link, while still being able to link with a 32-bit library?
The answer from Dan Udey was close, close enough in fact to allow me to find the real solution.
According to the man page "-mcpu" is a deprecated synonym for "-mtune" and just means "optimize for a particular CPU (but still run on older CPUs, albeit less optimal)". I tried this, and it did not solve the issue.
However, "-march=" means "generate code for a particular CPU (and don't run on older CPUs)". When I tried this it solved the problem: specifying a CPU of i486 or better got rid of the link error.
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccYnYLj6.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i386 test.cc
/tmp/ccOr3ww8.o(.text+0x22): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i486 test.cc
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=pentium test.cc
From the GCC page on Atomic Builtins:
Not all operations are supported by
all target processors. If a particular
operation cannot be implemented on the
target processor, a warning will be
generated and a call an external
function will be generated. The
external function will carry the same
name as the builtin, with an
additional suffix `_n' where n is the
size of the data type.
Judging from your compiler output, which refers to __sync_add_and_fetch_4, this is what's happening. For some reason, GCC is not generating the external function properly.
This is likely why you're only getting an error in 32-bit mode - when compiling for 64-bit mode, it compiles for your processor more closely. When compiling for 32-bit, it may well be using a generic arch (i386, for example) which does not natively support those features. Try specifying a specific architecture for your chip family (Xeon, Core 2, etc.) via -mcpu and see if that works.
If not, you'll have to figure out why GCC isn't including the appropriate function that it should be generating.

Resources