summaryrefslogtreecommitdiff
path: root/content/bootstrapGcc/14_g++4.6.4.md
blob: 9df600f1f2e7b8b856283611b1f090f07df7138b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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<iostream>

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:
    <!-- Using a markdown fenced code block here fails -->

    <pre class="language-diff">
        <code class="language-diff">
         (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"))))
        </code>
    </pre>

### 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.