Dear Ludo, sorry for the belated reply. I missed this original message, thankfully Janneke brought it to my attention during a discussion stemming from our FOSDEM encounter.
On 10/15/24 17:38, Ludovic Courtès wrote: > Hello there, > > Recently, Alexandre Oliva kindly sent me this message, which I’m > forwarding with his permission: > >> The one that may be more promising for now, but that I'm not sure solves >> the problem at all, is CCG. >> https://docs.adacore.com/live/wave/gnat_ccg/html/gnatccg_ug/gnat_ccg/gnat_ccg.html >> >> IIUC, it's GNAT-llvm with the backend set to generate C code. So, with >> a preexisting CCG, one could (presumably) translate GNAT to C, verify >> the translation as much as desired, and use the result to build a >> bootstrapping compiler, that could then be used as a starting point to >> build recent and future versions of GNAT. I thought that CCG was "closed source" (for paying customers only), and the GCC backend does seem to be the case. I was aware of GNAT-LLVM [1], but I did not know that the CCG technology based on LLVM was also opensourced with GNAT-LLVM [2]! I tried, just for fun, translating the .ads and .adb sources from GCC into .c files using the GNAT-LLVM CCG system. However, a lot of files failed to translate... Why? Well, the answer is in the documentation link in your email... CCG has some major limitations, such as no exception support... Therefore, a lot of the Ada files cannot be compiled to C. Additionally, the generated C code is something close to glorified assembly. Here are the results from my quick test: Ada file: ```ada pragma Ada_2022; with Ada.Text_IO; use Ada.Text_IO; procedure Passed is type Day_Temperature is record High, Current, Low : Integer; end record with Dynamic_Predicate => Day_Temperature.High >= Day_Temperature.Current and then Day_Temperature.Current >= Day_Temperature.Low; Garden : Day_Temperature := (28, 28, 19); begin Garden.Current := 30; Put_Line ("Garden current temperature is: " & Garden.Current'Image); -- return True; end Passed; ``` Command to translate it: llvm-gcc -x ada -emit-c -gnatA -gnatp -c $i Generated C code: ```c #include <string.h> #include <stdlib.h> typedef struct string_FP string_FP; typedef signed char main_unit__ccg_a1[]; typedef struct string_BOUNDS string_BOUNDS; struct string_FP { main_unit__ccg_a1 * P_DATA; string_BOUNDS * P_BOUNDS; }; struct string_BOUNDS { int LB0; int UB0; }; typedef struct passed__B3b__T11b_BD passed__B3b__T11b_BD; typedef signed char main_unit__ccg_a2[31]; struct passed__B3b__T11b_BD { string_BOUNDS BOUNDS; main_unit__ccg_a2 DATA; }; typedef struct passed__day_temperature passed__day_temperature; struct passed__day_temperature { int high; int current; int low; }; typedef signed char main_unit__ccg_a3[11]; typedef signed char main_unit__ccg_a4[42]; void _ada_passed (void); extern int system__img_int__impl__image_integer (int, string_FP); extern void system__concat_2__str_concat_2 (string_FP, string_FP, string_FP); extern void ada__text_io__put_line__2 (string_FP); const static string_BOUNDS main_unit_for_ref_ = {1, 11}; const static string_BOUNDS main_unit_for_ref_1_ = {1, 42}; const static passed__B3b__T11b_BD main_unit_for_ref_2_ = {{1, 31}, {71, 97, 114, 100, 101, 110, 32, 99, 117, 114, 114, 101, 110, 116, 32, 116, 101, 109, 112, 101, 114, 97, 116, 117, 114, 101, 32, 105, 115, 58, 32}}; static const string_FP ccg_v5 = {NULL, NULL}; static const string_BOUNDS ccg_v6 = {1, 0}; static const string_FP ccg_v7 = {((main_unit__ccg_a1 *) (main_unit__ccg_a2 *) &main_unit_for_ref_2_.DATA), ((string_BOUNDS *) ((unsigned int) (main_unit__ccg_a2 *) &main_unit_for_ref_2_.DATA + -8))}; void _ada_passed (void) { passed__day_temperature garden; main_unit__ccg_a3 S6b; int P7b; main_unit__ccg_a4 S16b; string_BOUNDS ccg_v8; string_BOUNDS ccg_v9; string_FP ccg_v10; string_FP ccg_v11; int R8b; string_FP ccg_v12; string_FP ccg_v13; string_BOUNDS ccg_v14; string_FP ccg_v15; string_FP ccg_v16; string_BOUNDS ccg_v17; string_FP ccg_v18; string_FP ccg_v19; garden.high = 28; garden.current = 28; garden.low = 19; garden.current = 30; ccg_v10.P_DATA = (main_unit__ccg_a1 *) &S6b; ccg_v11 = ccg_v10; ccg_v11.P_BOUNDS = (string_BOUNDS *) &main_unit_for_ref_; P7b = system__img_int__impl__image_integer (garden.current, ccg_v11); R8b = P7b; ccg_v12.P_DATA = (main_unit__ccg_a1 *) &S16b; ccg_v13 = ccg_v12; ccg_v13.P_BOUNDS = (string_BOUNDS *) &main_unit_for_ref_1_; ccg_v14 = ccg_v6; ccg_v14.UB0 = R8b; ccg_v8 = ccg_v14; ccg_v15.P_DATA = (main_unit__ccg_a1 *) &S6b[0]; ccg_v16 = ccg_v15; ccg_v16.P_BOUNDS = &ccg_v8; system__concat_2__str_concat_2 (ccg_v13, ccg_v7, ccg_v16); ccg_v17 = ccg_v6; ccg_v17.UB0 = 1 + ((31 + (R8b > 0 ? R8b : 0)) - 1); ccg_v9 = ccg_v17; ccg_v18.P_DATA = (main_unit__ccg_a1 *) &S16b[0]; ccg_v19 = ccg_v18; ccg_v19.P_BOUNDS = &ccg_v9; ada__text_io__put_line__2 (ccg_v19); return; } ``` As it can be seen, CCG strips a lot of the context and information form the original Ada file. I believe this method will therefore not help us much, as checking for the validity/reproducibility of the code would be quite hard... Nonetheless, I do not come here empty handed. Hopefully there will be a realistic path forward towards bootstrapping Ada in the short term. I hope to be able to give more information in the near future. Best regards and thank you for bringing my attention to CCG, Fer [1] https://github.com/AdaCore/gnat-llvm [2] https://github.com/AdaCore/gnat-llvm/tree/master/llvm-interface/ccg