Fix failure when -fno-rtti test is run in C++17 or later
[official-gcc.git] / gcc / ada / vxlink-bind.adb
blob9f456944506d67bfe606e6dc008d1980f2f3ce96
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- V X L I N K . B I N D --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2018, AdaCore --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 pragma Ada_2012;
28 with Ada.Text_IO; use Ada.Text_IO;
29 with Ada.IO_Exceptions;
30 with Ada.Strings.Fixed;
32 with GNAT.Regpat; use GNAT.Regpat;
34 package body VxLink.Bind is
36 function Split_Lines (S : String) return Strings_List.Vector;
38 function Split (S : String; C : Character) return Strings_List.Vector;
40 function Parse_Nm_Output (S : String) return Symbol_Sets.Set;
42 procedure Emit_Module_Dtor
43 (FP : File_Type);
45 procedure Emit_CDtor
46 (FP : File_Type;
47 Var : String;
48 Set : Symbol_Sets.Set);
50 -----------------
51 -- Split_Lines --
52 -----------------
54 function Split_Lines (S : String) return Strings_List.Vector
56 Last : Natural := S'First;
57 Ret : Strings_List.Vector;
58 begin
59 for J in S'Range loop
60 if S (J) = ASCII.CR
61 and then J < S'Last
62 and then S (J + 1) = ASCII.LF
63 then
64 Ret.Append (S (Last .. J - 1));
65 Last := J + 2;
66 elsif S (J) = ASCII.LF then
67 Ret.Append (S (Last .. J - 1));
68 Last := J + 1;
69 end if;
70 end loop;
72 if Last <= S'Last then
73 Ret.Append (S (Last .. S'Last));
74 end if;
76 return Ret;
77 end Split_Lines;
79 -----------
80 -- Split --
81 -----------
83 function Split (S : String; C : Character) return Strings_List.Vector
85 Last : Natural := S'First;
86 Ret : Strings_List.Vector;
87 begin
88 for J in S'Range loop
89 if S (J) = C then
90 if J > Last then
91 Ret.Append (S (Last .. J - 1));
92 end if;
94 Last := J + 1;
95 end if;
96 end loop;
98 if Last <= S'Last then
99 Ret.Append (S (Last .. S'Last));
100 end if;
102 return Ret;
103 end Split;
105 ---------------------
106 -- Parse_Nm_Output --
107 ---------------------
109 function Parse_Nm_Output (S : String) return Symbol_Sets.Set
111 Nm_Regexp : constant Pattern_Matcher :=
112 Compile ("^[0-9A-Za-z]* ([a-zA-Z]) (.*)$");
113 type CDTor_Type is
114 (CTOR_Diab,
115 CTOR_Gcc,
116 DTOR_Diab,
117 DTOR_Gcc);
118 subtype CTOR_Type is CDTor_Type range CTOR_Diab .. CTOR_Gcc;
119 CTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
120 Compile ("^__?STI__*([0-9]+)_");
121 CTOR_GCC_Regexp : aliased constant Pattern_Matcher :=
122 Compile ("^__?GLOBAL_.I._*([0-9]+)_");
123 DTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
124 Compile ("^__?STD__*([0-9]+)_");
125 DTOR_GCC_Regexp : aliased constant Pattern_Matcher :=
126 Compile ("^__?GLOBAL_.D._*([0-9]+)_");
127 type Regexp_Access is access constant Pattern_Matcher;
128 CDTor_Regexps : constant array (CDTor_Type) of Regexp_Access :=
129 (CTOR_Diab => CTOR_DIAB_Regexp'Access,
130 CTOR_Gcc => CTOR_GCC_Regexp'Access,
131 DTOR_Diab => DTOR_DIAB_Regexp'Access,
132 DTOR_Gcc => DTOR_GCC_Regexp'Access);
133 Result : Symbol_Sets.Set;
135 begin
136 for Line of Split_Lines (S) loop
137 declare
138 Sym : Symbol;
139 Nm_Grps : Match_Array (0 .. 2);
140 Ctor_Grps : Match_Array (0 .. 1);
141 begin
142 Match (Nm_Regexp, Line, Nm_Grps);
144 if Nm_Grps (0) /= No_Match then
145 declare
146 Sym_Type : constant Character :=
147 Line (Nm_Grps (1).First);
148 Sym_Name : constant String :=
149 Line (Nm_Grps (2).First .. Nm_Grps (2).Last);
150 begin
151 Sym :=
152 (Name => To_Unbounded_String (Sym_Name),
153 Cat => Sym_Type,
154 Internal => False,
155 Kind => Sym_Other,
156 Priority => -1);
158 for J in CDTor_Regexps'Range loop
159 Match (CDTor_Regexps (J).all, Sym_Name, Ctor_Grps);
161 if Ctor_Grps (0) /= No_Match then
162 if J in CTOR_Type then
163 Sym.Kind := Sym_Ctor;
164 else
165 Sym.Kind := Sym_Dtor;
166 end if;
168 Sym.Priority := Integer'Value
169 (Line (Ctor_Grps (1).First .. Ctor_Grps (1).Last));
171 exit;
172 end if;
173 end loop;
175 Result.Include (Sym);
176 end;
177 end if;
178 end;
179 end loop;
181 return Result;
182 end Parse_Nm_Output;
184 ----------------
185 -- Initialize --
186 ----------------
188 procedure Initialize
189 (Binder : out VxLink_Binder;
190 Object_File : String)
192 Args : Arguments_List;
193 Module_Dtor_Not_Needed : Boolean := False;
194 Module_Dtor_Needed : Boolean := False;
196 begin
197 Args.Append (Nm);
198 Args.Append (Object_File);
200 declare
201 Output : constant String := Run (Args);
202 Symbols : Symbol_Sets.Set;
203 begin
204 if Is_Error_State then
205 return;
206 end if;
208 Symbols := Parse_Nm_Output (Output);
210 for Sym of Symbols loop
211 if Sym.Kind = Sym_Ctor then
212 Binder.Constructors.Insert (Sym);
213 elsif Sym.Kind = Sym_Dtor then
214 Binder.Destructors.Insert (Sym);
215 elsif Match ("_?__.*_atexit$", To_String (Sym.Name)) then
216 if Sym.Cat = 'T' then
217 Module_Dtor_Not_Needed := True;
218 elsif Sym.Cat = 'U' then
219 Module_Dtor_Needed := True;
220 end if;
221 end if;
222 end loop;
224 Binder.Module_Dtor_Needed :=
225 not Module_Dtor_Not_Needed and then Module_Dtor_Needed;
226 end;
227 end Initialize;
229 --------------------
230 -- Parse_Tag_File --
231 --------------------
233 procedure Parse_Tag_File
234 (Binder : in out VxLink_Binder;
235 File : String)
237 FP : Ada.Text_IO.File_Type;
239 begin
240 Open
241 (FP,
242 Mode => In_File,
243 Name => File);
244 loop
245 declare
246 Line : constant String :=
247 Ada.Strings.Fixed.Trim
248 (Get_Line (FP), Ada.Strings.Both);
249 Tokens : Strings_List.Vector;
251 begin
252 if Line'Length = 0 then
253 -- Skip empty lines
254 null;
256 elsif Line (Line'First) = '#' then
257 -- Skip comment
258 null;
260 else
261 Tokens := Split (Line, ' ');
262 if Tokens.First_Element = "section" then
263 -- Sections are not used for tags, only when building
264 -- kernels. So skip for now
265 null;
266 else
267 Binder.Tags_List.Append (Line);
268 end if;
269 end if;
270 end;
271 end loop;
273 exception
274 when Ada.IO_Exceptions.End_Error =>
275 Close (FP);
276 when others =>
277 Log_Error ("Cannot open file " & File &
278 ". DKM tags won't be generated");
279 end Parse_Tag_File;
281 ----------------------
282 -- Emit_Module_Dtor --
283 ----------------------
285 procedure Emit_Module_Dtor
286 (FP : File_Type)
288 Dtor_Name : constant String := "_GLOBAL__D_65536_0_cxa_finalize";
289 begin
290 Put_Line (FP, "extern void __cxa_finalize(void *);");
291 Put_Line (FP, "static void " & Dtor_Name & "()");
292 Put_Line (FP, "{");
293 Put_Line (FP, " __cxa_finalize(&__dso_handle);");
294 Put_Line (FP, "}");
295 Put_Line (FP, "");
296 end Emit_Module_Dtor;
298 ----------------
299 -- Emit_CDtor --
300 ----------------
302 procedure Emit_CDtor
303 (FP : File_Type;
304 Var : String;
305 Set : Symbol_Sets.Set)
307 begin
308 for Sym of Set loop
309 if not Sym.Internal then
310 Put_Line (FP, "extern void " & To_String (Sym.Name) & "();");
311 end if;
312 end loop;
314 New_Line (FP);
316 Put_Line (FP, "extern void (*" & Var & "[])();");
317 Put_Line (FP, "void (*" & Var & "[])() =");
318 Put_Line (FP, " {");
319 for Sym of Set loop
320 Put_Line (FP, " " & To_String (Sym.Name) & ",");
321 end loop;
322 Put_Line (FP, " 0};");
323 New_Line (FP);
324 end Emit_CDtor;
326 ---------------
327 -- Emit_CTDT --
328 ---------------
330 procedure Emit_CTDT
331 (Binder : in out VxLink_Binder;
332 Namespace : String)
334 FP : Ada.Text_IO.File_Type;
335 CDtor_File : constant String := Namespace & "-cdtor.c";
336 begin
337 Binder.CTDT_File := To_Unbounded_String (CDtor_File);
338 Create
339 (File => FP,
340 Name => CDtor_File);
341 Put_Line (FP, "#if defined(_HAVE_TOOL_XTORS)");
342 Put_Line (FP, "#include <vxWorks.h>");
343 if Binder.Module_Dtor_Needed then
344 Put_Line (FP, "#define _WRS_NEED_CALL_CXA_FINALIZE");
345 end if;
346 Put_Line (FP, "#include TOOL_HEADER (toolXtors.h)");
347 Put_Line (FP, "#else");
348 Put_Line (FP, "");
350 if Binder.Module_Dtor_Needed then
351 Emit_Module_Dtor (FP);
352 end if;
354 Emit_CDtor (FP, "_ctors", Binder.Constructors);
355 Emit_CDtor (FP, "_dtors", Binder.Destructors);
357 Put_Line (FP, "#endif");
359 if not Binder.Tags_List.Is_Empty then
360 New_Line (FP);
361 Put_Line (FP, "/* build variables */");
362 Put_Line (FP, "__asm("" .section \"".wrs_build_vars\"",\""a\"""");");
363 for Tag of Binder.Tags_List loop
364 Put_Line (FP, "__asm("" .ascii \""" & Tag & "\"""");");
365 Put_Line (FP, "__asm("" .byte 0"");");
366 end loop;
367 Put_Line (FP, "__asm("" .ascii \""end\"""");");
368 Put_Line (FP, "__asm("" .byte 0"");");
369 end if;
371 Close (FP);
373 exception
374 when others =>
375 Close (FP);
376 Set_Error_State ("Internal error");
377 raise;
378 end Emit_CTDT;
380 ---------------
381 -- CTDT_File --
382 ---------------
384 function CTDT_File (Binder : VxLink_Binder) return String
386 begin
387 return To_String (Binder.CTDT_File);
388 end CTDT_File;
390 end VxLink.Bind;