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


  • Possible path to ... Ludovic Courtès
    • Re: Possible... Development of GNU Guix and the GNU System distribution.

Reply via email to