Title: Milestone – Bootstrapped GCC 4.6.4 for RISC-V Date: 2024-05-17 Category: Tags: Bootstrapping GCC in RISC-V Slug: bootstrapGcc14 Lang: en Summary: So yeah, we bootstrapped GCC 4.6.4 for RISC-V. We even have C++ support! In latest posts we talked about many things: problems, our changes to other projects and other things. Now it's time to actually talk about something we actually *did*. But first, we fixed more extra things... This is a never ending story. ### The things we need to deal with We have been trying to build GCC 4.6.4 with the backported RISC-V support using TinyCC. We already did a GCC 4.6.4 that worked but we only tested it building with a modern GCC. Building with a TinyCC with an incomplete backend that we had to improve ourselves is not that obvious as it would be with the very well established architecture like i386. We could build a minimal GCC, from TinyCC and Musl, but it didn't work. Me and my colleague Andrius Štikonas detected and patched around a problem that we still don't know where it is coming from ([we reported upstream][upstream]). This is the only one we need to apply to GCC, as we fixed many things in TinyCC. [upstream]: https://lists.nongnu.org/archive/html/tinycc-devel/2024-04/msg00028.html This simple patch was enough to build the whole GCC. Can you spot the difference? We find this kind of problems making small reproducers that we tried to tweak, and happened to work if we split things. ``` diff diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index d05f8149170..d4ef8de4813 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -300,6 +300,7 @@ static inline void * ssa_operand_alloc (unsigned size) { char *ptr; + int x; gcc_assert (size == sizeof (struct use_optype_d) || size == sizeof (struct def_optype_d)); @@ -334,8 +335,8 @@ ssa_operand_alloc (unsigned size) gimple_ssa_operands (cfun)->operand_memory_index = 0; } - ptr = &(gimple_ssa_operands (cfun)->operand_memory - ->mem[gimple_ssa_operands (cfun)->operand_memory_index]); + x = gimple_ssa_operands (cfun)->operand_memory_index; + ptr = &(gimple_ssa_operands (cfun)->operand_memory->mem[x]); gimple_ssa_operands (cfun)->operand_memory_index += size; return ptr; } ``` ### We need to rebuild with Musl Once that very first GCC compiles, it's necessary to rebuild Musl with that GCC, and use the new GCC+Musl combination to rebuild GCC, now adding the C++ support we missed first time. This gives us several things: a more stable GCC and a better Musl, that is compatible with GCC. If we don't do that, and we don't rebuild Musl, we see errors when building the second GCC, the `genmddeps` program, which is created and run during build process of GCC just fails. Also, we have to `--disable-bootstrap`, so rebuilding it is like doing the GCC's bootstrap ourselves. ### Backport Musl support to GCC 4.6.4 Next thing, remember from previous posts why we had to use Musl for our process. First, because it's a fully-featured C standard library; second, because it's simple and easy to build and, lastly, because we can't use GlibC: the newest version we can build doesn't support RISC-V. The main problem we have with GCC 4.6.4 since we started with all this journey is that 4.6.4 was written before our architecture, RISC-V, was invented, and this also happened with Musl. Andrius detected some missing declarations during the compilation process of the `libstdc++`, which happened because GCC was trying to use some GlibC specific functions for the build we didn't have, as we were using Musl instead. Turns out GCC needs extra configuration for Musl, that was added after our version was released, so I backported all that (not much) to GCC 4.6.4. Maybe I missed something, but now we can build GCC 4.6.4 with C++ support, using Musl, for RISC-V! ### But it doesn't work! Right after building it, we tried to use it on a simple program: ``` clike #include int main (int argc, char* argv[]){ std::cout << "Hello World" << std::endl; return 10; } ``` But this returns a huge set of errors looking like: ``` something /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L0 ': (.text._ZSt14__convert_to_vIfEvPKcRT_RSt12_Ios_IostateRKPi+0x3a): undefined reference to `operator new[](unsigned long)' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L15': (.text._ZSt14__convert_to_vIfEvPKcRT_RSt12_Ios_IostateRKPi+0x172): undefined reference to `operator delete[](void*)' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L11': (.text._ZSt14__convert_to_vIfEvPKcRT_RSt12_Ios_IostateRKPi+0x190): undefined reference to `__cxa_call_unexpected' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L0 ': (.text._ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi+0x3a): undefined reference to `operator new[](unsigned long)' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L39': (.text._ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi+0x1b4): undefined reference to `__cxa_call_unexpected' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L23': (.text._ZNSi6ignoreEl+0x21c): undefined reference to `__cxa_end_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L24': (.text._ZNSi6ignoreEl+0x22e): undefined reference to `__cxa_end_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.LEHB2': (.text._ZNSi6ignoreEl+0x24c): undefined reference to `__cxa_begin_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L31': (.text._ZNSi6ignoreEl+0x272): undefined reference to `__cxa_rethrow' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.LEHE2': (.text._ZNSi6ignoreEl+0x27c): undefined reference to `__cxa_begin_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L30': (.text._ZNSi6ignoreEl+0x29c): undefined reference to `__cxa_end_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L51': (.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x22c): undefined reference to `__cxa_end_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L52': (.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x23e): undefined reference to `__cxa_end_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.LEHB9': (.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x25c): undefined reference to `__cxa_begin_catch' /gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L59': (.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x282): undefined reference to `__cxa_rethrow' collect2: ld returned 1 exit status ``` Again, Andrius detected there was a line in the huge logs we have that said we were missing the `find` command. So we added it, and worked[^until-it-broke]. [^until-it-broke]: There's something weird in this case, if I do a change like this one below it fails:
        
         (native-inputs `(("gcc" ,gcc-muslboot0)
                          ("libc" ,musl-boot)
    -                     ("find" ,findutils)
                          ,@(modify-inputs (package-native-inputs gcc-muslboot0)
    +                                      (append findutils)
                                           (replace "make" gnu-make-muslboot)
                                           (delete "libc")
                                           (delete "tcc"))))
        
    
### The thing built, and worked! So we managed to make it build and run, improving TinyCC in the process. Now TinyCC can build Musl and GCC 4.6.4 (with a very small patch), and that GCC is able to build itself, adding C++ support. And of course, the thing works! You can try if this thing worked, and see how, in the [`commencement.scm`][commencement] project where I'm keeping track of all this. [commencement]: https://github.com/ekaitz-zarraga/commencement.scm/commit/9bbb1c61a87e206fb275c3040d0493beba6ae0fe ### Next So yeah, success but this didn't end. Now we need to use that GCC to build GCC 7.5, and compile the world with it. Cross fingers.