diff gcc/ada/vxlink-bind.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/ada/vxlink-bind.adb	Thu Oct 25 07:37:49 2018 +0900
@@ -0,0 +1,390 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                          V X L I N K . B I N D                           --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                     Copyright (C) 2018, AdaCore                          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
+-- for  more details.  You should have  received  a copy of the GNU General --
+-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license.          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Text_IO;       use Ada.Text_IO;
+with Ada.IO_Exceptions;
+with Ada.Strings.Fixed;
+
+with GNAT.Regpat;       use GNAT.Regpat;
+
+package body VxLink.Bind is
+
+   function Split_Lines (S : String) return Strings_List.Vector;
+
+   function Split (S : String; C : Character) return Strings_List.Vector;
+
+   function Parse_Nm_Output (S : String) return Symbol_Sets.Set;
+
+   procedure Emit_Module_Dtor
+     (FP : File_Type);
+
+   procedure Emit_CDtor
+     (FP  : File_Type;
+      Var : String;
+      Set : Symbol_Sets.Set);
+
+   -----------------
+   -- Split_Lines --
+   -----------------
+
+   function Split_Lines (S : String) return Strings_List.Vector
+   is
+      Last : Natural := S'First;
+      Ret  : Strings_List.Vector;
+   begin
+      for J in S'Range loop
+         if S (J) = ASCII.CR
+           and then J < S'Last
+           and then S (J + 1) = ASCII.LF
+         then
+            Ret.Append (S (Last .. J - 1));
+            Last := J + 2;
+         elsif S (J) = ASCII.LF then
+            Ret.Append (S (Last .. J - 1));
+            Last := J + 1;
+         end if;
+      end loop;
+
+      if Last <= S'Last then
+         Ret.Append (S (Last .. S'Last));
+      end if;
+
+      return Ret;
+   end Split_Lines;
+
+   -----------
+   -- Split --
+   -----------
+
+   function Split (S : String; C : Character) return Strings_List.Vector
+   is
+      Last : Natural := S'First;
+      Ret  : Strings_List.Vector;
+   begin
+      for J in S'Range loop
+         if S (J) = C then
+            if J > Last then
+               Ret.Append (S (Last .. J - 1));
+            end if;
+
+            Last := J + 1;
+         end if;
+      end loop;
+
+      if Last <= S'Last then
+         Ret.Append (S (Last .. S'Last));
+      end if;
+
+      return Ret;
+   end Split;
+
+   ---------------------
+   -- Parse_Nm_Output --
+   ---------------------
+
+   function Parse_Nm_Output (S : String) return Symbol_Sets.Set
+   is
+      Nm_Regexp        : constant Pattern_Matcher :=
+                           Compile ("^[0-9A-Za-z]* ([a-zA-Z]) (.*)$");
+      type CDTor_Type is
+        (CTOR_Diab,
+         CTOR_Gcc,
+         DTOR_Diab,
+         DTOR_Gcc);
+      subtype CTOR_Type is CDTor_Type range CTOR_Diab .. CTOR_Gcc;
+      CTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
+                           Compile ("^__?STI__*([0-9]+)_");
+      CTOR_GCC_Regexp  : aliased constant Pattern_Matcher :=
+                           Compile ("^__?GLOBAL_.I._*([0-9]+)_");
+      DTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
+                           Compile ("^__?STD__*([0-9]+)_");
+      DTOR_GCC_Regexp  : aliased constant Pattern_Matcher :=
+                           Compile ("^__?GLOBAL_.D._*([0-9]+)_");
+      type Regexp_Access is access constant Pattern_Matcher;
+      CDTor_Regexps    : constant array (CDTor_Type) of Regexp_Access :=
+                           (CTOR_Diab => CTOR_DIAB_Regexp'Access,
+                            CTOR_Gcc  => CTOR_GCC_Regexp'Access,
+                            DTOR_Diab => DTOR_DIAB_Regexp'Access,
+                            DTOR_Gcc  => DTOR_GCC_Regexp'Access);
+      Result           : Symbol_Sets.Set;
+
+   begin
+      for Line of Split_Lines (S) loop
+         declare
+            Sym     : Symbol;
+            Nm_Grps : Match_Array (0 .. 2);
+            Ctor_Grps : Match_Array (0 .. 1);
+         begin
+            Match (Nm_Regexp, Line, Nm_Grps);
+
+            if Nm_Grps (0) /= No_Match then
+               declare
+                  Sym_Type : constant Character :=
+                               Line (Nm_Grps (1).First);
+                  Sym_Name : constant String :=
+                               Line (Nm_Grps (2).First .. Nm_Grps (2).Last);
+               begin
+                  Sym :=
+                    (Name     => To_Unbounded_String (Sym_Name),
+                     Cat      => Sym_Type,
+                     Internal => False,
+                     Kind     => Sym_Other,
+                     Priority => -1);
+
+                  for J in CDTor_Regexps'Range loop
+                     Match (CDTor_Regexps (J).all, Sym_Name, Ctor_Grps);
+
+                     if Ctor_Grps (0) /= No_Match then
+                        if J in CTOR_Type then
+                           Sym.Kind := Sym_Ctor;
+                        else
+                           Sym.Kind := Sym_Dtor;
+                        end if;
+
+                        Sym.Priority := Integer'Value
+                          (Line (Ctor_Grps (1).First .. Ctor_Grps (1).Last));
+
+                        exit;
+                     end if;
+                  end loop;
+
+                  Result.Include (Sym);
+               end;
+            end if;
+         end;
+      end loop;
+
+      return Result;
+   end Parse_Nm_Output;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize
+     (Binder      : out VxLink_Binder;
+      Object_File : String)
+   is
+      Args                   : Arguments_List;
+      Module_Dtor_Not_Needed : Boolean := False;
+      Module_Dtor_Needed     : Boolean := False;
+
+   begin
+      Args.Append (Nm);
+      Args.Append (Object_File);
+
+      declare
+         Output  : constant String := Run (Args);
+         Symbols : Symbol_Sets.Set;
+      begin
+         if Is_Error_State then
+            return;
+         end if;
+
+         Symbols := Parse_Nm_Output (Output);
+
+         for Sym of Symbols loop
+            if Sym.Kind = Sym_Ctor then
+               Binder.Constructors.Insert (Sym);
+            elsif Sym.Kind = Sym_Dtor then
+               Binder.Destructors.Insert (Sym);
+            elsif Match ("_?__.*_atexit$", To_String (Sym.Name)) then
+               if Sym.Cat = 'T' then
+                  Module_Dtor_Not_Needed := True;
+               elsif Sym.Cat = 'U' then
+                  Module_Dtor_Needed := True;
+               end if;
+            end if;
+         end loop;
+
+         Binder.Module_Dtor_Needed :=
+           not Module_Dtor_Not_Needed and then Module_Dtor_Needed;
+      end;
+   end Initialize;
+
+   --------------------
+   -- Parse_Tag_File --
+   --------------------
+
+   procedure Parse_Tag_File
+     (Binder : in out VxLink_Binder;
+      File   : String)
+   is
+      FP   : Ada.Text_IO.File_Type;
+
+   begin
+      Open
+        (FP,
+         Mode => In_File,
+         Name => File);
+      loop
+         declare
+            Line   : constant String :=
+                      Ada.Strings.Fixed.Trim
+                        (Get_Line (FP), Ada.Strings.Both);
+            Tokens : Strings_List.Vector;
+
+         begin
+            if Line'Length = 0 then
+               --  Skip empty lines
+               null;
+
+            elsif Line (Line'First) = '#' then
+               --  Skip comment
+               null;
+
+            else
+               Tokens := Split (Line, ' ');
+               if Tokens.First_Element = "section" then
+                  --  Sections are not used for tags, only when building
+                  --  kernels. So skip for now
+                  null;
+               else
+                  Binder.Tags_List.Append (Line);
+               end if;
+            end if;
+         end;
+      end loop;
+
+   exception
+      when Ada.IO_Exceptions.End_Error =>
+         Close (FP);
+      when others =>
+         Log_Error ("Cannot open file " & File &
+                      ". DKM tags won't be generated");
+   end Parse_Tag_File;
+
+   ----------------------
+   -- Emit_Module_Dtor --
+   ----------------------
+
+   procedure Emit_Module_Dtor
+     (FP : File_Type)
+   is
+      Dtor_Name : constant String := "_GLOBAL__D_65536_0_cxa_finalize";
+   begin
+      Put_Line (FP, "extern void __cxa_finalize(void *);");
+      Put_Line (FP, "static void " & Dtor_Name & "()");
+      Put_Line (FP, "{");
+      Put_Line (FP, "  __cxa_finalize(&__dso_handle);");
+      Put_Line (FP, "}");
+      Put_Line (FP, "");
+   end Emit_Module_Dtor;
+
+   ----------------
+   -- Emit_CDtor --
+   ----------------
+
+   procedure Emit_CDtor
+     (FP  : File_Type;
+      Var : String;
+      Set : Symbol_Sets.Set)
+   is
+   begin
+      for Sym of Set loop
+         if not Sym.Internal then
+            Put_Line (FP, "extern void " & To_String (Sym.Name) & "();");
+         end if;
+      end loop;
+
+      New_Line (FP);
+
+      Put_Line (FP, "extern void (*" & Var & "[])();");
+      Put_Line (FP, "void (*" & Var & "[])() =");
+      Put_Line (FP, "  {");
+      for Sym of Set loop
+         Put_Line (FP, "  " & To_String (Sym.Name) & ",");
+      end loop;
+      Put_Line (FP, "  0};");
+      New_Line (FP);
+   end Emit_CDtor;
+
+   ---------------
+   -- Emit_CTDT --
+   ---------------
+
+   procedure Emit_CTDT
+     (Binder    : in out VxLink_Binder;
+      Namespace : String)
+   is
+      FP         : Ada.Text_IO.File_Type;
+      CDtor_File : constant String := Namespace & "-cdtor.c";
+   begin
+      Binder.CTDT_File := To_Unbounded_String (CDtor_File);
+      Create
+        (File => FP,
+         Name => CDtor_File);
+      Put_Line (FP, "#if defined(_HAVE_TOOL_XTORS)");
+      Put_Line (FP, "#include <vxWorks.h>");
+      if Binder.Module_Dtor_Needed then
+         Put_Line (FP, "#define _WRS_NEED_CALL_CXA_FINALIZE");
+      end if;
+      Put_Line (FP, "#include TOOL_HEADER (toolXtors.h)");
+      Put_Line (FP, "#else");
+      Put_Line (FP, "");
+
+      if Binder.Module_Dtor_Needed then
+         Emit_Module_Dtor (FP);
+      end if;
+
+      Emit_CDtor (FP, "_ctors", Binder.Constructors);
+      Emit_CDtor (FP, "_dtors", Binder.Destructors);
+
+      Put_Line (FP, "#endif");
+
+      if not Binder.Tags_List.Is_Empty then
+         New_Line (FP);
+         Put_Line (FP, "/* build variables */");
+         Put_Line (FP, "__asm(""  .section \"".wrs_build_vars\"",\""a\"""");");
+         for Tag of Binder.Tags_List loop
+            Put_Line (FP, "__asm(""  .ascii \""" & Tag & "\"""");");
+            Put_Line (FP, "__asm(""  .byte 0"");");
+         end loop;
+         Put_Line (FP, "__asm(""  .ascii \""end\"""");");
+         Put_Line (FP, "__asm(""  .byte 0"");");
+      end if;
+
+      Close (FP);
+
+   exception
+      when others =>
+         Close (FP);
+         Set_Error_State ("Internal error");
+         raise;
+   end Emit_CTDT;
+
+   ---------------
+   -- CTDT_File --
+   ---------------
+
+   function CTDT_File (Binder : VxLink_Binder) return String
+   is
+   begin
+      return To_String (Binder.CTDT_File);
+   end CTDT_File;
+
+end VxLink.Bind;