riscvarchive / riscv-newlib Goto Github PK
View Code? Open in Web Editor NEWRISC-V port of newlib
License: GNU General Public License v2.0
RISC-V port of newlib
License: GNU General Public License v2.0
README for GNU development tools This directory contains various GNU compilers, assemblers, linkers, debuggers, etc., plus their support routines, definitions, and documentation. If you are receiving this as part of a GDB release, see the file gdb/README. If with a binutils release, see binutils/README; if with a libg++ release, see libg++/README, etc. That'll give you info about this package -- supported targets, how to use it, how to report bugs, etc. It is now possible to automatically configure and build a variety of tools with one command. To build all of the tools contained herein, run the ``configure'' script here, e.g.: ./configure make To install them (by default in /usr/local/bin, /usr/local/lib, etc), then do: make install (If the configure script can't determine your type of computer, give it the name as an argument, for instance ``./configure sun4''. You can use the script ``config.sub'' to test whether a name is recognized; if it is, config.sub translates it to a triplet specifying CPU, vendor, and OS.) If you have more than one compiler on your system, it is often best to explicitly set CC in the environment before running configure, and to also set CC when running make. For example (assuming sh/bash/ksh): CC=gcc ./configure make A similar example using csh: setenv CC gcc ./configure make Much of the code and documentation enclosed is copyright by the Free Software Foundation, Inc. See the file COPYING or COPYING.LIB in the various directories, for a description of the GNU General Public License terms under which you can copy the files. REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info on where and how to report problems.
I've rebase newlib to 2.4, it's include git log after 2016/8 which cherry-pick by manual from https://github.com/riscv/riscv-gnu-toolchain and it's also include 2 bug fix patch, can you pull the branch into this repo, and of cause I've run regression test :)
And my next plan is let this repo become a sub-moudle of riscv-gnu-toolchain.
https://github.com/kito-cheng/riscv-newlib
When building the latest riscv-newlib-2.4.0 branch against an upstream gcc configured as riscv32-elf
, it will fail to build, complaining about some lp64 subdir trying to use elf64-littleriscv
:
If using a riscv64-elf
gcc, it will succeed to build:
I would expect newlib to simply not enter 64-bit directories with a 32-bit only toolchain.
Note that upstream binutils 2.28 does not support a generic riscv-elf
target, so it would seem weird to force everyone into using riscv64-elf
for 32-bit development.
Both C and POSIX requires at least 32 functions to be registered by atexit()
, but RISC-V already uses one for __libc_fini_array
in libgloss, so only 31 functions can be registered by users.
#include <stdlib.h>
#include <stdio.h>
void fn(void) {}
int main(void) {
for (int i = 0; i < 32; ++i) {
printf("%d: atexit(fn) = %d\n", i, atexit(fn));
}
return 0;
}
Sample output:
0: atexit(fn) = 0
1: atexit(fn) = 0
2: atexit(fn) = 0
...
30: atexit(fn) = 0
31: atexit(fn) = -1
Perhaps we should use other mechanisms to call __libc_fini_array
or increase _ATEXIT_SIZE
to compensate for that.
I've just built a new version of the RISC-V bare-metal toolchain, using GCC 11.3 and the latest newlib, including the newlinb-nano libraries, and I noticed that the nano.spec
does not replace the -lstdc++
and -lsupc++
with their size optimised nano versions, as the Arm bare-metal toolchains do.
For example, the arm-none-eabi
toolchains uses:
*link:
%(nano_link) %:replace-outfile(-lc -lc_nano) %:replace-outfile(-lg -lg_nano) %:replace-outfile(-lrdimon -lrdimon_nano) %:replace-outfile(-lstdc++ -lstdc++_nano) %:replace-outfile(-lsupc++ -lsupc++_nano)
while the riscv-none-embed
toolchain uses:
*link:
%(nano_link) %:replace-outfile(-lc -lc_nano) %:replace-outfile(-lg -lg_nano) %:replace-outfile(-lm -lm_nano)
Could we add the same substitutions to the RISC-V newlib in order to make applications using newlib-nano benefit from the size optimised versions of the C++ libraries?
If so, what is the procedure to get such a patch accepted upstream?
The startup code expects the main()
arguments to be processed by someone else and does not call SYS_GETCMDLINE
to get them, as specified by Arm semihosting:
This might work on some specific platforms, but generally it fails, since that area is right after the stack, usually an invalid memory region.
The workaround for semihosted applications it to rewrite the startup code.
The solution for newlib is to replicate the logic used by the Arm startup code, which processes the arguments properly.
It might also be a good idea to call SYS_HEAPINFO
and properly process the heap/stack.
I'm trying to compile a simple program for RISCV with newlib that uses fenv to set the rounding mode.
#include <cstdio>
#include <cmath>
#include <cfenv>
int main(int argc, char **argv)
{
float fs1 = 2.0;
float fs2 = 3.0;
float f;
std::fesetround(FE_TONEAREST);
f = fs1 / fs2;
printf("%f\n", f);
std::fesetround(FE_TOWARDZERO);
f = fs1 / fs2;
printf("%f\n", f);
std::fesetround(FE_UPWARD);
f = fs1 / fs2;
printf("%f\n", f);
std::fesetround(FE_DOWNWARD);
f = fs1 / fs2;
printf("%f\n", f);
return 0;
}
This compiles with the linux/glibc build of the toolchain:
$ riscv64-unknown-linux-gnu-g++ -std=c++11 -o /tmp/log2 /tmp/log2.cc
$
but not with newlib:
$ riscv64-unknown-elf-g++ -std=c++11 -o /tmp/fenv-newlib /tmp/fenv-newlib.cc
/tmp/fenv-newlib.cc: In function 'int main(int, char**)':
/tmp/fenv-newlib.cc:11:10: error: 'fesetround' is not a member of 'std'
std::fesetround(FE_TONEAREST);
^~~~~~~~~~
/tmp/fenv-newlib.cc:11:21: error: 'FE_TONEAREST' was not declared in this scope
std::fesetround(FE_TONEAREST);
^~~~~~~~~~~~
/tmp/fenv-newlib.cc:15:10: error: 'fesetround' is not a member of 'std'
std::fesetround(FE_TOWARDZERO);
^~~~~~~~~~
/tmp/fenv-newlib.cc:15:21: error: 'FE_TOWARDZERO' was not declared in this scope
std::fesetround(FE_TOWARDZERO);
^~~~~~~~~~~~~
/tmp/fenv-newlib.cc:19:10: error: 'fesetround' is not a member of 'std'
std::fesetround(FE_UPWARD);
^~~~~~~~~~
/tmp/fenv-newlib.cc:19:21: error: 'FE_UPWARD' was not declared in this scope
std::fesetround(FE_UPWARD);
^~~~~~~~~
/tmp/fenv-newlib.cc:23:10: error: 'fesetround' is not a member of 'std'
std::fesetround(FE_DOWNWARD);
^~~~~~~~~~
/tmp/fenv-newlib.cc:23:21: error: 'FE_DOWNWARD' was not declared in this scope
std::fesetround(FE_DOWNWARD);
^~~~~~~~~~~
$
Looking at the preprocessor output reveals that for the newlib toolchain there is no output from processing cfenv:
...
# 3 "/tmp/fenv-newlib.cc" 2
# 1 "/opt/esperanto/minion-sim-toolchains/gcc-newlib/riscv64-unknown-elf/include/c++/7.0.1/cfenv" 1 3
# 32 "/opt/esperanto/minion-sim-toolchains/gcc-newlib/riscv64-unknown-elf/include/c++/7.0.1/cfenv" 3
# 33 "/opt/esperanto/minion-sim-toolchains/gcc-newlib/riscv64-unknown-elf/include/c++/7.0.1/cfenv" 3
# 4 "/tmp/fenv-newlib.cc" 2
# 5 "/tmp/fenv-newlib.cc"
int main(int argc, char **argv)
{
float fs1 = 2.0;
float fs2 = 3.0;
float f;
std::fesetround(FE_TONEAREST);
f = fs1 / fs2;
printf("%f\n", f);
std::fesetround(FE_TOWARDZERO);
f = fs1 / fs2;
printf("%f\n", f);
std::fesetround(FE_UPWARD);
f = fs1 / fs2;
printf("%f\n", f);
std::fesetround(FE_DOWNWARD);
f = fs1 / fs2;
printf("%f\n", f);
return 0;
}
Looking at the header file, it appears to be expecting the _GLIBCXX_USE_C99_FENV_TR1 macro to be defined:
$ less .../riscv-tools-newlib-stock/riscv64-unknown-elf/include/c++/7.1.1/cfenv
...
#if _GLIBCXX_USE_C99_FENV_TR1
...
namespace std
{
// types
using ::fenv_t;
using ::fexcept_t;
// functions
using ::feclearexcept;
using ::fegetexceptflag;
using ::feraiseexcept;
using ::fesetexceptflag;
using ::fetestexcept;
using ::fegetround;
using ::fesetround;
using ::fegetenv;
using ::feholdexcept;
using ::fesetenv;
using ::feupdateenv;
} // namespace std
#endif // _GLIBCXX_USE_C99_FENV_TR1
...
The symbols in libnosys need leading underscores added in order to be compatible with the naming used in newlib. See discussion with @ilg-ul here for details, including a proposed fix from @jim-wilson here
As discussed at FOSDEM with @arunthomas, for Linux distros like openSUSE to pick up RISC-V toolchains, your target support needs to be in the respective upstream projects (and released tarballs).
At present, binutils 2.28 and gcc 7.0.1 do contain RISC-V target support, but apparently not yet newlib, without which no riscv64-elf gcc cross-toolchain can be packaged by us yet, despite all other pieces being present.
Of course getting such things merged may take time, but there not being a 2.5.0 based branch here yet makes me doubt this is in progress already... Is anything in particular holding this up? I thought only glibc and Linux are blocked by the non-final Privileged ISA Specification, which should not impact, e.g., the HiFive1 board that newlib would be used for?
More general, https://riscv.org/software-tools/risc-v-gnu-compiler-toolchain/ does not seem to textually track the upstreaming progress anywhere, in terms of links to patchsets or done vs. to-do lists? It exclusively refers to your GitHub based projects, no direct instructions for how to configure the official tarballs where upstreaming is completed, and the last toolchain related news items were in early 2015. As convenient as your submodule projects may be for early RISC-V users building toolchains themselves, please understand that your submodules are not suitable for distribution and that they hide important configuration details in your riscv-gnu-toolchain Makefile.in and configure.ac files that would be really useful to clearly state somewhere on the official RISC-V site.
The %f, %g and %e format specifiers for sprintf() and printf() fail to return the proper sign. The result varies depending upon the mix of printf() calls...
The following produces the incorrect sign for all three of the printf() calls:
$ cat /tmp/negfloat.c
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv)
{
char buf[1024];
float minusOnePtOne = -1.1;
printf("%+f\n", minusOnePtOne);
printf("%+g\n", minusOnePtOne);
printf("%+e\n", minusOnePtOne);
}
$ riscv64-unknown-elf-gcc -o /tmp/negfloat-rv64 /tmp/negfloat.c
$ spike pk /tmp/negfloat-rv64
+1.100000
+1.1
+1.100000e+00
$
It appears that just adding a single sprintf() call before the printf() calls forces them to return the correct results:
$ cat /tmp/negfloat.c
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv)
{
char buf[1024];
float minusOnePtOne = -1.1;
sprintf(buf, "%+f", minusOnePtOne);
printf("%+f\n", minusOnePtOne);
printf("%+g\n", minusOnePtOne);
printf("%+e\n", minusOnePtOne);
}
$ riscv64-unknown-elf-gcc -o /tmp/negfloat-rv64 /tmp/negfloat.c
$ spike pk /tmp/negfloat-rv64
-1.100000
-1.1
-1.100000e+00
$
And moving the sprintf() between the first two printf() calls produces the correct result for the second two printf() calls:
$ cat /tmp/negfloat.c
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv)
{
char buf[1024];
float minusOnePtOne = -1.1;
printf("%+f\n", minusOnePtOne);
sprintf(buf, "%+f", minusOnePtOne);
printf("%+g\n", minusOnePtOne);
printf("%+e\n", minusOnePtOne);
}
$ riscv64-unknown-elf-gcc -o /tmp/negfloat-rv64 /tmp/negfloat.c
$ spike pk /tmp/negfloat-rv64
+1.100000
-1.1
-1.100000e+00
$
This is the version of GCC being used:
$ riscv64-unknown-elf-gcc --version
riscv64-unknown-elf-gcc (GCC) 7.1.1 20170509
Copyright (C) 2017 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.
$
I see that sp is used here:
https://github.com/riscv/riscv-newlib/blob/77e11e1800f57cac7f5468b2bd064100a44755d4/libgloss/riscv/crt0.S#L38
But before that it was not set anywhere.
I see that sp is set for ARM:
https://github.com/riscv/riscv-newlib/blob/77e11e1800f57cac7f5468b2bd064100a44755d4/libgloss/arm/crt0.S#L196
I see that sp is set in the RISC-V tests:
https://github.com/riscv/riscv-test-env/blob/68cad7baf3ed0a4553fffd14726d24519ee1296a/v/entry.S#L30
https://github.com/riscv/riscv-tests/blob/c37ac4c0a6d7523c96864861a1c9a1181b5cccd5/benchmarks/common/crt.S#L132
But it is not set in newlib. Why?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.