[[!meta copyright="Copyright © 2011, 2012, 2013, 2016 Free Software
Foundation, Inc."]]

[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable
id="license" text="Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no Invariant
Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the license
is included in the section entitled [[GNU Free Documentation
License|/fdl]]."]]"""]]

[[!meta title="Enable Ada programming (GCC: GNAT)"]]

[[!tag open_issue_gcc]]

Make the Ada programming language available on GNU/Hurd in its [[GCC]] GNAT
implementation, and enable Hurd-specific features.

There is a [[!FF_project 259]][[!tag bounty]] on this task.

---


# Part I

First, make the language functional, have its test suite pass without errors.

Using, for example, the build instructions from [[GCC]], you'll need to add
`ada` to `--enable-languages`.


## Original [[community/GSoC]] Task Description

[[!inline pages=community/gsoc/project_ideas/gnat feeds=no]]


## Debian GCC

There has a patch been added for GNU/kFreeBSD:
`bfe081336914729fc0180c07ab4afa41965100f2`, `git-svn-id:
svn://svn.debian.org/gcccvs/branches/sid@5638
6ca36cf4-e1d1-0310-8c6f-e303bb2178ca'


## IRC, freenode, #hurd, 2012-07-17

    <gnu_srs> I've found the remaining problem with gnat backtrace for Hurd!
      Related to the stack frame.
    <gnu_srs> This version does not work: one relying on static assumptions
      about the frame layout
    <gnu_srs> Causing segfaults.
    <gnu_srs> Any interest to create a test case out of that piece of code,
      taken from gcc/ada/tracebak.c?
    <braunr> gnu_srs: sure


### IRC, freenode, #hurd, 2012-07-18

    <braunr> "Digging further revealed that the GNU/Hurd stack frame does not
      seem to
    <braunr> be static enough to define USE_GENERIC_UNWINDER in
      gcc/ada/tracebak.c.
    <braunr> "
    <braunr> what do you mean by a "stack frame does not seem to be static
      enough" ?
    <gnu_srs> I can qoute from the source file if you want. Otherwise look at
      the code yourself: gcc/ada/tracebak,c
    <gnu_srs> I mean that something is wrong with the stack frame for
      Hurd. This is the code I wanted to use as a test case for the stack.
    <gnu_srs> Remember?
    <braunr> more or less
    <braunr> ah, "static assumptions"
    <braunr> all right, i don't think anything is "wrong" with stack frames
    <braunr> but if you use a recent version of gcc, as indicated in the code,
      -fomit-frame-pointer is enabled by default
    <braunr> so your stack frame won't look like it used to be without the
      option
    <braunr> hence the need for USE_GCC_UNWINDER
    <braunr> http://en.wikipedia.org/wiki/Call_stack explains this very well
    <gnu_srs> However, kfreebsd does not seem to need USE_GCC_UNWINDER, how
      come?
    <braunr> i guess they don't omit the frame pointer
    <braunr> your fix is good btw
    <gnu_srs> thanks


### IRC, freenode, #hurd, 2012-07-19

    <gnu_srs> tschwinge: The bug in #681998 should go upstream. Applied in
      Debian already. Hopefully this is the last patch needed for the port of
      GNAT to Hurd.

### 2015-11-27

Is this related to:

`gcc/ada/tracebak.c`:

    #if (defined (__x86_64__) || defined (__linux__)) && !defined (__USING_SJLJ_EXCEPTIONS__)
    #define USE_GCC_UNWINDER
    #else
    #define USE_GENERIC_UNWINDER


## Svante's patch

A basic port has been done by Svante, [[!debbug 668425]], [[!debbug 681998]],
[[!message-id "1333104917.2962.439.camel@s1499.it.kth.se"]], but there's still
lots of work remaining.
The port is not yet upstream: the maintainer raised some concerns that
[[I|tschwinge]] have not yet found the time to follow up on, [[!message-id
"1339857758-5032-1-git-send-email-thomas@codesourcery.com"]].
While the test
results of the GCC/GNAT testsuite don't look bad (but there are a few
unresolved issues, and the testsuite appears to be a rather small one), I don't
know if the port has yet seen any real-world usage, such as using it for any
bigger Ada code bases, or any Ada testsuites.

### "try2"

[[!message-id "1456875776.5852.194.camel@gmail.com"]].
GCC trunk r234252.
Still incomplete.


## `getcontext`/`makecontext`/`setcontext`/`swapcontext` usage analysis

In context of [[glibc/t/tls-threadvar]].  Looking at GCC trunk commit
f6568ea476aa52a6e23c6db43b3e240cde55783a (2013-04-26).

    gcc/ada/init.c:  sigaltstack (&stack, NULL);
    gcc/ada/init.c:      sigaltstack (&stack, NULL);
    gcc/ada/init.c:  sigaltstack (&stack, NULL);
    gcc/ada/s-osinte-aix.ads:   function sigaltstack
    gcc/ada/s-osinte-aix.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-android.ads:   function sigaltstack
    gcc/ada/s-osinte-android.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-darwin.ads:   function sigaltstack
    gcc/ada/s-osinte-darwin.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-freebsd.ads:   function sigaltstack
    gcc/ada/s-osinte-freebsd.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-hpux.ads:   function sigaltstack
    gcc/ada/s-osinte-hpux.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-kfreebsd-gnu.ads:   function sigaltstack
    gcc/ada/s-osinte-kfreebsd-gnu.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-linux.ads:   function sigaltstack
    gcc/ada/s-osinte-linux.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-osinte-rtems.adb:   -- sigaltstack --
    gcc/ada/s-osinte-rtems.adb:   function sigaltstack
    gcc/ada/s-osinte-rtems.adb:   end sigaltstack;
    gcc/ada/s-osinte-rtems.ads:   function sigaltstack
    gcc/ada/s-osinte-solaris-posix.ads:   function sigaltstack
    gcc/ada/s-osinte-solaris-posix.ads:   pragma Import (C, sigaltstack, "sigaltstack");
    gcc/ada/s-taprop-linux.adb:            Result := sigaltstack (Stack'Access, null);
    gcc/ada/s-taprop-posix.adb:            Result := sigaltstack (Stack'Access, null);
    gcc/ada/init.c:  stack.ss_sp = __gnat_alternate_stack;
    gcc/ada/init.c:      stack.ss_sp = __gnat_alternate_stack;
    gcc/ada/init.c:  stack.ss_sp = __gnat_alternate_stack;
    gcc/ada/s-osinte-aix.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-android.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-darwin.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-darwin.ads:      uc_stack    : stack_t;          --  Stack Used By This Context
    gcc/ada/s-osinte-freebsd.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-hpux.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-kfreebsd-gnu.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-linux.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-rtems.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-solaris-posix.ads:      ss_sp    : System.Address;
    gcc/ada/s-osinte-solaris.ads:      ss_sp        : System.Address;
    gcc/ada/s-osinte-solaris.ads:      uc_stack     : record_type_2;
    gcc/ada/s-taprop-linux.adb:            Stack.ss_sp    := Self_ID.Common.Task_Alternate_Stack;
    gcc/ada/s-taprop-posix.adb:            Stack.ss_sp    := Self_ID.Common.Task_Alternate_Stack;

    gcc/ada/init.c:  act.sa_flags |= SA_ONSTACK;
    gcc/ada/init.c:      act.sa_flags |= SA_ONSTACK;
    gcc/ada/init.c:  act.sa_flags = SA_SIGINFO | SA_ONSTACK;
    gcc/ada/init.c:  act.sa_flags |= SA_ONSTACK;
    gcc/ada/s-intman-posix.adb:                  act.sa_flags := act.sa_flags + SA_ONSTACK;
    gcc/ada/s-linux-alpha.ads:   SA_ONSTACK  : constant := 16#01#;
    gcc/ada/s-linux-hppa.ads:   SA_ONSTACK : constant := 16#01#;
    gcc/ada/s-linux-mipsel.ads:   SA_ONSTACK  : constant := 16#08000000#;
    gcc/ada/s-linux-sparc.ads:   SA_ONSTACK  : constant := 16#001#;
    gcc/ada/s-linux.ads:   SA_ONSTACK  : constant := 16#08000000#;
    gcc/ada/s-osinte-aix.ads:   SA_ONSTACK : constant := 16#0001#;
    gcc/ada/s-osinte-android.ads:   SA_ONSTACK : constant := System.Linux.SA_ONSTACK;
    gcc/ada/s-osinte-darwin.ads:   SA_ONSTACK : constant := 16#0001#;
    gcc/ada/s-osinte-freebsd.ads:   SA_ONSTACK : constant := 16#0001#;
    gcc/ada/s-osinte-hpux-dce.ads:   SA_ONSTACK  : constant  := 16#01#;
    gcc/ada/s-osinte-hpux.ads:   SA_ONSTACK : constant := 16#01#;
    gcc/ada/s-osinte-kfreebsd-gnu.ads:   SA_ONSTACK : constant := 16#0001#;
    gcc/ada/s-osinte-linux.ads:   SA_ONSTACK : constant := System.Linux.SA_ONSTACK;
    gcc/ada/s-osinte-lynxos.ads:   SA_ONSTACK : constant := 16#00#;
    gcc/ada/s-osinte-lynxos.ads:   --  SA_ONSTACK is not defined on LynxOS, but it is referred to in the POSIX
    gcc/ada/s-osinte-rtems.ads:   SA_ONSTACK : constant := 16#00#;
    gcc/ada/s-osinte-rtems.ads:   --  SA_ONSTACK is not defined on RTEMS, but it is referred to in the POSIX
    gcc/ada/s-osinte-solaris-posix.ads:   SA_ONSTACK : constant := 16#0001#;
    gcc/ada/s-osinte-vxworks.ads:   SA_ONSTACK : constant := 16#0004#;

## TODO

    diff --git ./gcc/ada/init.c ./gcc/ada/init.c
    @@ -2002,6 +2021,15 @@ __gnat_install_handler (void)
      trap_0_entry->inst_fourth = 0xa1480000;
    #endif
    
    {+#if (defined (i386) || defined (__i386__)) && !defined (VTHREADS)+}
    {+  /*  By experiment, found that sysModel () returns the following string+}
    {+      prefix for vxsim when running on Linux and Windows.  */+}
    {+  model = sysModel ();+}
    {+  if ((strncmp (model, "Linux", 5) == 0)+}
    {+      || (strncmp (model, "Windows", 7) == 0))+}
    {+    is_vxsim = 1;+}
    {+#endif+}
    
      __gnat_handler_installed = 1;
    }
    
    diff --git ./gcc/ada/sigtramp.h ./gcc/ada/sigtramp.h
    @@ -62,8 +62,14 @@ typedef struct ucontext
         system headers so call it something unique.  */
      typedef void __sigtramphandler_t (int signo, void *siginfo, void *sigcontext);
    
    {+#if CPU == SIMNT || CPU == SIMPENTIUM || CPU == SIMLINUX+}
    {+  /* Vxsim requires a specially compiled handler.  */+}
    {+  void __gnat_sigtramp_vxsim  (int signo, void *siginfo, void *sigcontext,+}
    {+                       __sigtramphandler_t * handler);+}
    {+#else+}
      void __gnat_sigtramp  (int signo, void *siginfo, void *sigcontext,
                             __sigtramphandler_t * handler);
    {+#endif+}
    
    diff --git ./gcc/ada/gcc-interface/Makefile.in ./gcc/ada/gcc-interface/Makefile.in
    @@ -923,13 +928,49 @@ ifeq ($(strip $(filter-out %86 wrs vxworks vxworks7,$(target_cpu) $(target_vendo
    {+  VXSIM_CPU =+}
    
    {+  ifeq ($(strip $(filter-out vxworks rtp rtp-smp,$(target_os) $(THREAD_KIND))),)+}
    {+      VXSIM_CPU = SIMPENTIUM+}
    {+  else+}
    {+    ifeq ($(strip $(filter-out kernel kernel-smp rtp rtp-smp,$(THREAD_KIND))),)+}
    {+      ifeq ($(strip $(filter-out linux%,$(host_os))),)+}
    {+        # Linux+}
    {+        VXSIM_CPU = SIMLINUX+}
    {+      else+}
    {+        # Windows+}
    {+        VXSIM_CPU = SIMNT+}
    {+      endif+}
    {+    endif+}
    
    diff --git ./gcc/ada/gcc-interface/Makefile.in ./gcc/ada/gcc-interface/Makefile.in
    @@ -2413,6 +2468,14 @@ ifeq ($(filter a-except%,$(LIBGNAT_TARGET_PAIRS)),)
    {+# Configuration of host tools+}
    
    {+# Under linux, host tools need to be linked with -ldl+}
    
    {+ifeq ($(strip $(filter-out linux%,$(host_os))),)+}
    {+   TOOLS1_LIBS=-ldl+}
    {+endif+}
    
    diff --git ./gcc/ada/s-osinte-linux.ads ./gcc/ada/s-osinte-linux.ads
    @@ -224,6 +224,10 @@ package System.OS_Interface is
       {+function clock_gettime+}
    {+     (clock_id : clockid_t; tp : access timespec) return int;+}
    {+   pragma Import (C, clock_gettime, "clock_gettime");+}
    
    diff --git ./gcc/ada/s-taprop-linux.adb ./gcc/ada/s-taprop-linux.adb
    @@ -39,7 +39,6 @@ pragma Polling (Off);
    with Interfaces.C;
    [-with Interfaces.C.Extensions;-]
    @@ -64,7 +63,6 @@ package body System.Task_Primitives.Operations is
       use Interfaces.C;
    [-   use Interfaces.C.Extensions;-]
    @@ -629,30 +627,14 @@ package body System.Task_Primitives.Operations is
       function Monotonic_Clock return Duration is
          [-use Interfaces;-]
    
    [-      procedure timeval_to_duration-]
    [-        (T    : not null access timeval;-]
    [-         sec  : not null access C.Extensions.long_long;-]
    [-         usec : not null access C.long);-]
    [-      pragma Import (C, timeval_to_duration, "__gnat_timeval_to_duration");-]
    
    [-      Micro  : constant := 10**6;-]
    [-      sec    : aliased C.Extensions.long_long;-]
    [-      usec   : aliased C.long;-]
    [-      TV-]{+TS+}     : aliased [-timeval;-]{+timespec;+}
          Result : int;
    
    [-      function gettimeofday-]
    [-        (Tv : access timeval;-]
    [-         Tz : System.Address := System.Null_Address) return int;-]
    [-      pragma Import (C, gettimeofday, "gettimeofday");-]
    
       begin
          Result := [-gettimeofday (TV'Access, System.Null_Address);-]{+clock_gettime+}
    {+        (clock_id => OSC.CLOCK_RT_Ada, tp => TS'Unchecked_Access);+}
          pragma Assert (Result = 0);
    [-timeval_to_duration (TV'Access, sec'Access, usec'Access);-]
          return [-Duration (sec) + Duration (usec) / Micro;-]{+To_Duration (TS);+}
       end Monotonic_Clock;


    diff --git ./gcc/ada/adaint.c ./gcc/ada/adaint.c
    @@ -3220,6 +3220,107 @@ __gnat_kill (int pid, int sig, int close ATTRIBUTE_UNUSED)
    #endif
    }
    
    {+void __gnat_killprocesstree (int pid, int sig_num)+}
    {+{+}
    {+[...]+}
    {+#elif defined (__linux__)+}
    {+  DIR *dir;+}
    {+  struct dirent *d;+}
    
    {+  /*  read all processes' pid and ppid */+}
    
    {+  dir = opendir ("/proc");+}
    {+[...]+}
    {+  /* kill process */+}
    
    {+  __gnat_kill (pid, sig_num, 1);+}
    {+#else+}
    {+  __gnat_kill (pid, sig_num, 1);+}
    {+#endif+}
    {+[...]+}
    {+}+}

    diff --git ./gcc/ada/s-os_lib.ads ./gcc/ada/s-os_lib.ads
    @@ -740,6 +744,19 @@ package System.OS_Lib is
    {+   procedure Kill_Process_Tree (Pid : Process_Id; Hard_Kill : Boolean := True);+}
    {+   --  Kill the process designated by Pid and all it's children processes.+}
    {+   --  [...]
    {+   --  Note that this routine is not atomic and is supported only on Linux+}
    {+   --  and Windows. On other OS it will only kill the process identified by+}
    {+   --  Pid.+}

GCC includes (TODO: some version of) the Ada Conformity Assessment Test Suite
(ACATS), <http://ada-auth.org/acats.html>.  Additional tests to be found at
<http://ada-auth.org/submit.html>.  TODO: results?


---


# Part II

Next, Hurd-specific features can be added.  Add an interface to the
language/environment for being able to do [[RPC]] calls, in order to program
[[hurd/translator]]s natively in Ada.


## Original [[community/GSoC]] Task Description

[[!inline pages=community/gsoc/project_ideas/language_bindings feeds=no]]