Line data Source code
1 : /* do not edit automatically generated by mc from M2LangDump. */
2 : /* M2LangDump.mod provides support routines for the -flang-dump.
3 :
4 : Copyright (C) 2024-2026 Free Software Foundation, Inc.
5 : Contributed by Gaius Mulley <gaiusmod2@gmail.com>.
6 :
7 : This file is part of GNU Modula-2.
8 :
9 : GNU Modula-2 is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3, or (at your option)
12 : any later version.
13 :
14 : GNU Modula-2 is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GNU Modula-2; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "gcc-consolidation.h"
26 :
27 : #include <stdbool.h>
28 : # if !defined (PROC_D)
29 : # define PROC_D
30 : typedef void (*PROC_t) (void);
31 : typedef struct { PROC_t proc; } PROC;
32 : # endif
33 :
34 : # if !defined (TRUE)
35 : # define TRUE (1==1)
36 : # endif
37 :
38 : # if !defined (FALSE)
39 : # define FALSE (1==0)
40 : # endif
41 :
42 : #if defined(__cplusplus)
43 : # undef NULL
44 : # define NULL 0
45 : #endif
46 : #define _M2LangDump_C
47 :
48 : #include "GM2LangDump.h"
49 : # include "GSYSTEM.h"
50 : # include "GDynamicStrings.h"
51 : # include "GSymbolTable.h"
52 : # include "GM2Options.h"
53 : # include "GM2AsmUtil.h"
54 : # include "GM2GCCDeclare.h"
55 : # include "GFormatStrings.h"
56 : # include "GNameKey.h"
57 : # include "GSymbolConversion.h"
58 : # include "GM2LexBuf.h"
59 : # include "GM2Printf.h"
60 : # include "GM2Error.h"
61 : # include "GM2Batch.h"
62 : # include "Gm2misc.h"
63 : # include "GStrLib.h"
64 : # include "Glibc.h"
65 : # include "GFIO.h"
66 : # include "GSFIO.h"
67 : # include "GStdIO.h"
68 :
69 : # define Debugging false
70 : static FIO_File outputFile;
71 : static bool declActive;
72 : static bool quadActive;
73 : static bool mustClose;
74 : static unsigned int NoOfQuadDumps;
75 : static unsigned int NoOfDeclDumps;
76 :
77 : /*
78 : IsDumpRequiredTree - return TRUE if the gcc tree should be dumped.
79 : */
80 :
81 : extern "C" bool M2LangDump_IsDumpRequiredTree (tree gcctree, bool default_);
82 :
83 : /*
84 : IsDumpRequired - return TRUE if symbol sym should be dumped
85 : according to the rules of the filter.
86 : No filter specified will always return default.
87 : The filter is a comma separated list. Each element
88 : of the list can specify a symbol three ways.
89 : Firstly by DECL name for example: m2pim_NumberIO_HexToStr
90 : Secondly by qualified scope: [pathname.]NumberIO.HexToStr
91 : Thirdly by filename and scope: NumberIO.mod:HexToStr
92 : */
93 :
94 : extern "C" bool M2LangDump_IsDumpRequired (unsigned int sym, bool default_);
95 :
96 : /*
97 : MakeQuadTemplate - return a template for the quad dump file.
98 : */
99 :
100 : extern "C" DynamicStrings_String M2LangDump_MakeQuadTemplate (void);
101 :
102 : /*
103 : MakeGimpleTemplate - return a template for the gimple dump file and assign
104 : len to the max number of characters required to complete
105 : a template (including a nul terminator).
106 : */
107 :
108 : extern "C" DynamicStrings_String M2LangDump_MakeGimpleTemplate (unsigned int *len);
109 :
110 : /*
111 : GetDumpFile - return the dump output file.
112 : */
113 :
114 : extern "C" FIO_File M2LangDump_GetDumpFile (void);
115 :
116 : /*
117 : CreateDumpQuad - create the dump file for a quad dump.
118 : */
119 :
120 : extern "C" void M2LangDump_CreateDumpQuad (const char *title_, unsigned int _title_high);
121 :
122 : /*
123 : CloseDumpQuad - close the dump output file.
124 : */
125 :
126 : extern "C" void M2LangDump_CloseDumpQuad (void);
127 :
128 : /*
129 : CreateDumpDecl - create the dump file for a decl dump.
130 : */
131 :
132 : extern "C" void M2LangDump_CreateDumpDecl (const char *title_, unsigned int _title_high);
133 :
134 : /*
135 : CloseDumpDecl - close the dump output file.
136 : */
137 :
138 : extern "C" void M2LangDump_CloseDumpDecl (void);
139 :
140 : /*
141 : Assert - call InternalError is NOT value.
142 : */
143 :
144 : static void Assert (bool value);
145 :
146 : /*
147 : DumpWrite - writes a single ch to the dump output.
148 : */
149 :
150 : static void DumpWrite (char ch);
151 :
152 : /*
153 : CloseDump - close the dump file and pop the default write procedure.
154 : */
155 :
156 : static void CloseDump (void);
157 :
158 : /*
159 : OpenDump - open filename as a dump file. The filename '-' is treated as stdout.
160 : It pushes a write procedure to StdIO.
161 : */
162 :
163 : static void OpenDump (DynamicStrings_String filename, unsigned int no);
164 :
165 : /*
166 : AddRuleTextDump - filter on the textual name given to GCC.
167 : */
168 :
169 : static void AddRuleTextDump (DynamicStrings_String rule);
170 :
171 : /*
172 : AddRuleScopeQualidentDump -
173 : */
174 :
175 : static void AddRuleScopeQualidentDump (DynamicStrings_String rule, int dot, unsigned int modsym);
176 :
177 : /*
178 : AddRuleScopeDump -
179 : */
180 :
181 : static void AddRuleScopeDump (DynamicStrings_String rule);
182 :
183 : /*
184 : GenQualidentSymString - returns the qualified sym string (including
185 : any nested procedure and modules).
186 : */
187 :
188 : static DynamicStrings_String GenQualidentSymString (unsigned int sym);
189 :
190 : /*
191 : IdentQualidentMatch - return TRUE if sym name matches symstr.
192 : */
193 :
194 : static bool IdentQualidentMatch (unsigned int sym, DynamicStrings_String symstr);
195 :
196 : /*
197 : IsRuleFilenameMatch - return TRUE if rule matches sym.
198 : */
199 :
200 : static bool IsRuleFilenameMatch (DynamicStrings_String rule, unsigned int sym);
201 :
202 : /*
203 : CheckRuleMatch - issue a warning if seenMatch is FALSE and this is the first time
204 : the rule is matched.
205 : */
206 :
207 : static void CheckRuleMatch (bool seenMatch, DynamicStrings_String rule);
208 :
209 : /*
210 : AddRuleFilenameDump -
211 : */
212 :
213 : static void AddRuleFilenameDump (DynamicStrings_String rule);
214 :
215 : /*
216 : AddRuleSymToDump - call appropriate sub rule. FileName if : present.
217 : Scope if . present otherwise assume a text rule.
218 : */
219 :
220 : static void AddRuleSymToDump (DynamicStrings_String rule);
221 :
222 : /*
223 : AddFilterListToDumpWatch -
224 : */
225 :
226 : static void AddFilterListToDumpWatch (void * filter);
227 :
228 : /*
229 : CreateDumpTitle - creates the underlined title.
230 : */
231 :
232 : static void CreateDumpTitle (const char *title_, unsigned int _title_high);
233 :
234 : /*
235 : Match - return TRUE if sym matches any of the filter rules.
236 : */
237 :
238 : static bool Match (void * filter, unsigned int sym);
239 :
240 : /*
241 : MatchRule - return TRUE if rule matches sym.
242 : */
243 :
244 : static bool MatchRule (DynamicStrings_String rule, unsigned int sym);
245 :
246 : /*
247 : MatchRuleFilenameScope - returns TRUE if rule contains filename.ext:qualident
248 : and it matches sym.
249 : */
250 :
251 : static bool MatchRuleFilenameScope (DynamicStrings_String rule, unsigned int sym);
252 :
253 : /*
254 : MatchRuleScope - returns TRUE if rule contains a [libname.]qualified.ident
255 : and it matches sym.
256 : */
257 :
258 : static bool MatchRuleScope (DynamicStrings_String rule, unsigned int sym);
259 :
260 : /*
261 : MatchRuleQualident - returns TRUE if rule matches qualified sym.
262 : PostCondition: subrule will be deallocated upon exit.
263 : TRUE is returned if rule matches qualified sym.
264 : */
265 :
266 : static bool MatchRuleQualident (DynamicStrings_String rule, DynamicStrings_String subrule, int i, unsigned int sym);
267 :
268 : /*
269 : QualifiedScope - PostCondition: true is returned is rule matches a qualified sym.
270 : i is -1 if no more qualifications or libname is found.
271 : scope will be the set to the last outer scope seen.
272 : */
273 :
274 : static bool QualifiedScope (DynamicStrings_String rule, unsigned int sym, int *i, unsigned int *scope);
275 :
276 : /*
277 : OptionalLibname - returns TRUE if rule[0..dot] matches syms libname or
278 : if there is no libname the scope is a module or defimp
279 : symbol.
280 : */
281 :
282 : static bool OptionalLibname (DynamicStrings_String rule, unsigned int sym, int dot, unsigned int scope);
283 :
284 : /*
285 : MatchRuleIdent - return TRUE if ident sym matches rule.
286 : The ident must be in a module or defimp scope.
287 : */
288 :
289 : static bool MatchRuleIdent (DynamicStrings_String rule, unsigned int sym);
290 :
291 : /*
292 : MatchRuleText - returns TRUE if rule matches sym.
293 : */
294 :
295 : static bool MatchRuleText (DynamicStrings_String rule, unsigned int sym);
296 :
297 : /*
298 : TextCompareName - return TRUE if rule matches name.
299 : */
300 :
301 : static bool TextCompareName (DynamicStrings_String rule, NameKey_Name name);
302 :
303 : /*
304 : TextMatch - returns TRUE if rule matches text. Currently this
305 : is a simple string compare, but could be extended
306 : to implement regexp (seen in the rule).
307 : */
308 :
309 : static bool TextMatch (DynamicStrings_String rule, DynamicStrings_String text);
310 :
311 : /*
312 : CreateTemplate - create and return a template filename with extension.
313 : If the user has specified "-" then "-" is returned otherwise
314 : a template is formed from "dumpdir + filename + .%03dl.extension".
315 : */
316 :
317 : static DynamicStrings_String CreateTemplate (DynamicStrings_String filename, DynamicStrings_String extension);
318 :
319 : /*
320 : MakeDeclTemplate - return a template for the decl dump file.
321 : */
322 :
323 : static DynamicStrings_String MakeDeclTemplate (void);
324 :
325 : /*
326 : Init - initialize the module global variables.
327 : */
328 :
329 : static void Init (void);
330 :
331 :
332 : /*
333 : Assert - call InternalError is NOT value.
334 : */
335 :
336 0 : static void Assert (bool value)
337 : {
338 0 : if (! value)
339 : {
340 0 : M2Error_InternalError ((const char *) "assert failed in M2LangDump", 27);
341 : }
342 0 : }
343 :
344 :
345 : /*
346 : DumpWrite - writes a single ch to the dump output.
347 : */
348 :
349 0 : static void DumpWrite (char ch)
350 : {
351 0 : FIO_WriteChar (outputFile, ch);
352 0 : }
353 :
354 :
355 : /*
356 : CloseDump - close the dump file and pop the default write procedure.
357 : */
358 :
359 0 : static void CloseDump (void)
360 : {
361 0 : if (mustClose)
362 : {
363 0 : FIO_Close (outputFile);
364 0 : mustClose = false;
365 : }
366 : else
367 : {
368 0 : FIO_FlushBuffer (outputFile);
369 : }
370 0 : StdIO_PopOutput ();
371 0 : outputFile = FIO_StdOut;
372 0 : }
373 :
374 :
375 : /*
376 : OpenDump - open filename as a dump file. The filename '-' is treated as stdout.
377 : It pushes a write procedure to StdIO.
378 : */
379 :
380 0 : static void OpenDump (DynamicStrings_String filename, unsigned int no)
381 : {
382 0 : if (DynamicStrings_EqualArray (filename, (const char *) "-", 1))
383 : {
384 0 : mustClose = false;
385 0 : outputFile = FIO_StdOut;
386 : }
387 : else
388 : {
389 0 : filename = FormatStrings_Sprintf1 (filename, (const unsigned char *) &no, (sizeof (no)-1));
390 0 : outputFile = SFIO_OpenToWrite (filename);
391 0 : mustClose = FIO_IsNoError (outputFile);
392 : }
393 0 : filename = DynamicStrings_KillString (filename);
394 0 : StdIO_PushOutput ((StdIO_ProcWrite) {(StdIO_ProcWrite_t) DumpWrite});
395 0 : }
396 :
397 :
398 : /*
399 : AddRuleTextDump - filter on the textual name given to GCC.
400 : */
401 :
402 0 : static void AddRuleTextDump (DynamicStrings_String rule)
403 : {
404 0 : unsigned int sym;
405 0 : NameKey_Name key;
406 0 : bool seenMatch;
407 :
408 0 : sym = 1;
409 0 : seenMatch = false;
410 0 : key = NameKey_makekey (DynamicStrings_string (rule));
411 0 : while (sym <= (SymbolTable_FinalSymbol ()))
412 : {
413 0 : if ((SymbolTable_IsProcedure (sym)) && (key == (M2AsmUtil_GetFullSymName (sym))))
414 : {
415 0 : M2GCCDeclare_IncludeDumpSymbol (sym);
416 0 : seenMatch = true;
417 : }
418 0 : sym += 1;
419 : }
420 0 : CheckRuleMatch (seenMatch, rule);
421 0 : }
422 :
423 :
424 : /*
425 : AddRuleScopeQualidentDump -
426 : */
427 :
428 0 : static void AddRuleScopeQualidentDump (DynamicStrings_String rule, int dot, unsigned int modsym)
429 : {
430 0 : DynamicStrings_String modstr;
431 0 : DynamicStrings_String idstr;
432 0 : int start;
433 0 : unsigned int sym;
434 :
435 0 : start = dot+1;
436 0 : dot = DynamicStrings_Index (rule, '.', static_cast<unsigned int> (start));
437 0 : while (dot > 0)
438 : {
439 0 : modstr = DynamicStrings_Slice (rule, start, dot);
440 0 : modsym = SymbolTable_GetLocalSym (modsym, NameKey_makekey (DynamicStrings_string (modstr)));
441 0 : if ((modsym != SymbolTable_NulSym) && (SymbolTable_IsModule (modsym)))
442 : {
443 0 : start = dot+1;
444 0 : dot = DynamicStrings_Index (rule, '.', static_cast<unsigned int> (start));
445 : }
446 : else
447 : {
448 0 : modstr = DynamicStrings_KillString (modstr);
449 0 : return;
450 : }
451 : }
452 0 : idstr = DynamicStrings_Slice (rule, start, 0);
453 0 : sym = SymbolTable_GetLocalSym (modsym, NameKey_makekey (DynamicStrings_string (idstr)));
454 0 : if (sym == SymbolTable_NulSym)
455 : {
456 0 : CheckRuleMatch (false, rule);
457 : }
458 : else
459 : {
460 0 : M2GCCDeclare_IncludeDumpSymbol (sym);
461 : }
462 : }
463 :
464 :
465 : /*
466 : AddRuleScopeDump -
467 : */
468 :
469 0 : static void AddRuleScopeDump (DynamicStrings_String rule)
470 : {
471 0 : unsigned int modsym;
472 0 : DynamicStrings_String libstr;
473 0 : DynamicStrings_String modstr;
474 0 : int start;
475 0 : int dot;
476 :
477 0 : dot = DynamicStrings_Index (rule, '.', 0);
478 0 : Assert (dot != -1);
479 0 : libstr = static_cast<DynamicStrings_String> (NULL);
480 0 : modstr = DynamicStrings_Slice (rule, 0, dot);
481 0 : modsym = M2Batch_Get (NameKey_makekey (DynamicStrings_string (modstr)));
482 0 : if (modsym == SymbolTable_NulSym)
483 : {
484 : /* avoid dangling else. */
485 0 : libstr = modstr;
486 0 : start = dot+1;
487 0 : dot = DynamicStrings_Index (rule, '.', static_cast<unsigned int> (start));
488 0 : if (dot > 0)
489 : {
490 0 : modstr = DynamicStrings_Slice (rule, start, dot);
491 0 : modsym = M2Batch_Get (NameKey_makekey (DynamicStrings_string (modstr)));
492 0 : if ((modsym != SymbolTable_NulSym) && ((NameKey_makekey (DynamicStrings_string (libstr))) == (SymbolTable_GetLibName (modsym))))
493 : {
494 0 : AddRuleScopeQualidentDump (rule, dot, modsym);
495 : }
496 : }
497 : }
498 : else
499 : {
500 0 : AddRuleScopeQualidentDump (rule, dot, modsym);
501 : }
502 0 : }
503 :
504 :
505 : /*
506 : GenQualidentSymString - returns the qualified sym string (including
507 : any nested procedure and modules).
508 : */
509 :
510 0 : static DynamicStrings_String GenQualidentSymString (unsigned int sym)
511 : {
512 0 : DynamicStrings_String identstr;
513 0 : DynamicStrings_String qualidentstr;
514 :
515 0 : qualidentstr = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (sym)));
516 0 : while ((SymbolTable_GetScope (sym)) != SymbolTable_NulSym)
517 : {
518 0 : sym = SymbolTable_GetScope (sym);
519 0 : identstr = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (sym)));
520 0 : identstr = DynamicStrings_ConCatChar (identstr, '.');
521 0 : qualidentstr = DynamicStrings_ConCat (identstr, DynamicStrings_Mark (qualidentstr));
522 : }
523 0 : return qualidentstr;
524 : /* static analysis guarentees a RETURN statement will be used before here. */
525 : __builtin_unreachable ();
526 : }
527 :
528 :
529 : /*
530 : IdentQualidentMatch - return TRUE if sym name matches symstr.
531 : */
532 :
533 0 : static bool IdentQualidentMatch (unsigned int sym, DynamicStrings_String symstr)
534 : {
535 0 : bool success;
536 0 : DynamicStrings_String qualidentstr;
537 :
538 0 : qualidentstr = GenQualidentSymString (sym);
539 0 : success = DynamicStrings_Equal (qualidentstr, symstr);
540 0 : qualidentstr = DynamicStrings_KillString (qualidentstr);
541 0 : return success;
542 : /* static analysis guarentees a RETURN statement will be used before here. */
543 : __builtin_unreachable ();
544 : }
545 :
546 :
547 : /*
548 : IsRuleFilenameMatch - return TRUE if rule matches sym.
549 : */
550 :
551 0 : static bool IsRuleFilenameMatch (DynamicStrings_String rule, unsigned int sym)
552 : {
553 0 : DynamicStrings_String fname;
554 0 : DynamicStrings_String modstr;
555 0 : DynamicStrings_String symstr;
556 0 : DynamicStrings_String filename;
557 0 : unsigned int tokenno;
558 0 : int dot;
559 0 : int colon;
560 0 : bool success;
561 :
562 0 : tokenno = SymbolTable_GetDeclaredMod (sym);
563 0 : filename = M2LexBuf_FindFileNameFromToken (tokenno, 0);
564 0 : fname = static_cast<DynamicStrings_String> (NULL);
565 0 : symstr = static_cast<DynamicStrings_String> (NULL);
566 0 : modstr = static_cast<DynamicStrings_String> (NULL);
567 0 : success = false;
568 0 : colon = DynamicStrings_Index (rule, ':', 0);
569 0 : if (colon > 0)
570 : {
571 0 : fname = DynamicStrings_Slice (rule, 0, colon);
572 0 : if (DynamicStrings_Equal (fname, filename))
573 : {
574 0 : if (((int ) (DynamicStrings_Length (rule))) > colon)
575 : {
576 0 : symstr = DynamicStrings_Slice (rule, colon+1, 0);
577 0 : dot = DynamicStrings_ReverseIndex (symstr, '.', -1);
578 0 : if (dot >= 0)
579 : {
580 0 : success = IdentQualidentMatch (sym, symstr);
581 : }
582 : else
583 : {
584 0 : success = (SymbolTable_GetSymName (sym)) == (NameKey_makekey (DynamicStrings_string (symstr)));
585 : }
586 : }
587 : }
588 : }
589 0 : fname = DynamicStrings_KillString (fname);
590 0 : modstr = DynamicStrings_KillString (modstr);
591 0 : symstr = DynamicStrings_KillString (symstr);
592 0 : return success;
593 : /* static analysis guarentees a RETURN statement will be used before here. */
594 : __builtin_unreachable ();
595 : }
596 :
597 :
598 : /*
599 : CheckRuleMatch - issue a warning if seenMatch is FALSE and this is the first time
600 : the rule is matched.
601 : */
602 :
603 0 : static void CheckRuleMatch (bool seenMatch, DynamicStrings_String rule)
604 : {
605 0 : DynamicStrings_String message;
606 :
607 0 : if ((NoOfDeclDumps == 1) && ! seenMatch)
608 : {
609 0 : message = DynamicStrings_InitString ((const char *) "no symbol matching: %qs has been found when applying the dump filter", 68);
610 0 : m2misc_warning_m2_dump_filter (DynamicStrings_string (message), DynamicStrings_string (rule));
611 : }
612 0 : }
613 :
614 :
615 : /*
616 : AddRuleFilenameDump -
617 : */
618 :
619 0 : static void AddRuleFilenameDump (DynamicStrings_String rule)
620 : {
621 0 : unsigned int sym;
622 0 : bool seenMatch;
623 :
624 0 : sym = 1;
625 0 : seenMatch = false;
626 0 : while (sym <= (SymbolTable_FinalSymbol ()))
627 : {
628 0 : if ((SymbolTable_IsProcedure (sym)) && (IsRuleFilenameMatch (rule, sym)))
629 : {
630 0 : M2GCCDeclare_IncludeDumpSymbol (sym);
631 0 : seenMatch = true;
632 : }
633 0 : sym += 1;
634 : }
635 0 : CheckRuleMatch (seenMatch, rule);
636 0 : }
637 :
638 :
639 : /*
640 : AddRuleSymToDump - call appropriate sub rule. FileName if : present.
641 : Scope if . present otherwise assume a text rule.
642 : */
643 :
644 0 : static void AddRuleSymToDump (DynamicStrings_String rule)
645 : {
646 0 : if ((DynamicStrings_Index (rule, ':', 0)) != -1)
647 : {
648 : /* Filename and scope rule. */
649 0 : AddRuleFilenameDump (rule);
650 : }
651 0 : else if ((DynamicStrings_Index (rule, '.', 0)) != -1)
652 : {
653 : /* avoid dangling else. */
654 : /* Modula-2 scoping tests. */
655 0 : AddRuleScopeDump (rule);
656 : }
657 : else
658 : {
659 : /* avoid dangling else. */
660 : /* Text decl tests. */
661 0 : AddRuleTextDump (rule);
662 : }
663 0 : }
664 :
665 :
666 : /*
667 : AddFilterListToDumpWatch -
668 : */
669 :
670 0 : static void AddFilterListToDumpWatch (void * filter)
671 : {
672 0 : DynamicStrings_String rule;
673 0 : DynamicStrings_String full;
674 0 : int start;
675 0 : int i;
676 :
677 0 : full = DynamicStrings_InitStringCharStar (filter);
678 0 : start = 0;
679 0 : do {
680 0 : i = DynamicStrings_Index (full, ',', static_cast<unsigned int> (start));
681 0 : if (i == -1)
682 : {
683 0 : rule = DynamicStrings_Slice (full, start, 0);
684 : }
685 : else
686 : {
687 0 : rule = DynamicStrings_Slice (full, start, i);
688 : }
689 0 : AddRuleSymToDump (rule);
690 0 : rule = DynamicStrings_KillString (rule);
691 0 : start = i+1;
692 0 : } while (! (i == -1));
693 0 : full = DynamicStrings_KillString (full);
694 0 : }
695 :
696 :
697 : /*
698 : CreateDumpTitle - creates the underlined title.
699 : */
700 :
701 0 : static void CreateDumpTitle (const char *title_, unsigned int _title_high)
702 : {
703 0 : unsigned int len;
704 0 : unsigned int text;
705 0 : unsigned int i;
706 0 : DynamicStrings_String s;
707 0 : char title[_title_high+1];
708 :
709 : /* make a local copy of each unbounded array. */
710 0 : memcpy (title, title_, _title_high+1);
711 :
712 0 : s = FormatStrings_Sprintf0 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) title, _title_high)));
713 0 : s = DynamicStrings_KillString (SFIO_WriteS (M2LangDump_GetDumpFile (), s));
714 0 : len = StrLib_StrLen ((const char *) title, _title_high);
715 0 : i = 0;
716 0 : text = 0;
717 0 : while (i < len)
718 : {
719 0 : if (title[i] == '\\')
720 : {
721 0 : i += 2;
722 : }
723 : else
724 : {
725 0 : i += 1;
726 0 : text += 1;
727 : }
728 : }
729 0 : s = DynamicStrings_Mult (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "=", 1)), text);
730 0 : s = DynamicStrings_KillString (SFIO_WriteS (M2LangDump_GetDumpFile (), s));
731 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "\\n", 2);
732 0 : }
733 :
734 :
735 : /*
736 : Match - return TRUE if sym matches any of the filter rules.
737 : */
738 :
739 0 : static bool Match (void * filter, unsigned int sym)
740 : {
741 0 : bool result;
742 0 : DynamicStrings_String rule;
743 0 : DynamicStrings_String full;
744 0 : int start;
745 0 : int i;
746 :
747 0 : full = DynamicStrings_InitStringCharStar (filter);
748 0 : start = 0;
749 0 : do {
750 0 : i = DynamicStrings_Index (full, ',', static_cast<unsigned int> (start));
751 0 : if (i == -1)
752 : {
753 0 : rule = DynamicStrings_Slice (full, start, 0);
754 : }
755 : else
756 : {
757 0 : rule = DynamicStrings_Slice (full, start, i);
758 : }
759 0 : result = MatchRule (rule, sym);
760 0 : rule = DynamicStrings_KillString (rule);
761 0 : if (result)
762 : {
763 0 : full = DynamicStrings_KillString (full);
764 0 : return true;
765 : }
766 0 : start = i+1;
767 0 : } while (! (i == -1));
768 0 : full = DynamicStrings_KillString (full);
769 0 : return false;
770 : /* static analysis guarentees a RETURN statement will be used before here. */
771 : __builtin_unreachable ();
772 : }
773 :
774 :
775 : /*
776 : MatchRule - return TRUE if rule matches sym.
777 : */
778 :
779 0 : static bool MatchRule (DynamicStrings_String rule, unsigned int sym)
780 : {
781 0 : if ((DynamicStrings_Index (rule, ':', 0)) != -1)
782 : {
783 : /* Filename and scope qualification tests. */
784 0 : return MatchRuleFilenameScope (rule, sym);
785 : }
786 0 : else if ((DynamicStrings_Index (rule, '.', 0)) != -1)
787 : {
788 : /* avoid dangling else. */
789 : /* Modula-2 scoping tests. */
790 0 : return MatchRuleScope (rule, sym);
791 : }
792 : else
793 : {
794 : /* avoid dangling else. */
795 : /* Text decl tests. */
796 0 : return MatchRuleText (rule, sym);
797 : }
798 : /* static analysis guarentees a RETURN statement will be used before here. */
799 : __builtin_unreachable ();
800 : }
801 :
802 :
803 : /*
804 : MatchRuleFilenameScope - returns TRUE if rule contains filename.ext:qualident
805 : and it matches sym.
806 : */
807 :
808 0 : static bool MatchRuleFilenameScope (DynamicStrings_String rule, unsigned int sym)
809 : {
810 0 : DynamicStrings_String rulefile;
811 0 : DynamicStrings_String symfile;
812 0 : DynamicStrings_String subrule;
813 :
814 0 : rulefile = DynamicStrings_Slice (rule, 0, DynamicStrings_Index (rule, ':', 0));
815 : /* Do not deallocate symfile. */
816 0 : symfile = M2LexBuf_FindFileNameFromToken (SymbolTable_GetDeclaredMod (sym), 0);
817 0 : if (TextMatch (rulefile, symfile))
818 : {
819 0 : subrule = DynamicStrings_Slice (rule, (DynamicStrings_Index (rule, ':', 0))+1, 0);
820 0 : if (MatchRuleScope (subrule, sym))
821 : {
822 0 : subrule = DynamicStrings_KillString (subrule);
823 0 : return true;
824 : }
825 : }
826 0 : rulefile = DynamicStrings_KillString (rulefile);
827 0 : return false;
828 : /* static analysis guarentees a RETURN statement will be used before here. */
829 : __builtin_unreachable ();
830 : }
831 :
832 :
833 : /*
834 : MatchRuleScope - returns TRUE if rule contains a [libname.]qualified.ident
835 : and it matches sym.
836 : */
837 :
838 0 : static bool MatchRuleScope (DynamicStrings_String rule, unsigned int sym)
839 : {
840 0 : int i;
841 0 : NameKey_Name name;
842 :
843 0 : if (Debugging)
844 : {
845 : name = SymbolTable_GetSymName (sym);
846 : M2Printf_printf2 ((const char *) "MatchRuleScope (%s, %a)\\n", 25, (const unsigned char *) &rule, (sizeof (rule)-1), (const unsigned char *) &name, (sizeof (name)-1));
847 : }
848 : /* Compare qualident right to left. */
849 0 : i = DynamicStrings_RIndex (rule, '.', 0);
850 0 : if (i == -1)
851 : {
852 : /* No qualification, just the ident. */
853 0 : return MatchRuleIdent (rule, sym);
854 : }
855 : else
856 : {
857 0 : return MatchRuleQualident (rule, DynamicStrings_Slice (rule, i+1, 0), i, sym);
858 : }
859 : /* static analysis guarentees a RETURN statement will be used before here. */
860 : __builtin_unreachable ();
861 : }
862 :
863 :
864 : /*
865 : MatchRuleQualident - returns TRUE if rule matches qualified sym.
866 : PostCondition: subrule will be deallocated upon exit.
867 : TRUE is returned if rule matches qualified sym.
868 : */
869 :
870 0 : static bool MatchRuleQualident (DynamicStrings_String rule, DynamicStrings_String subrule, int i, unsigned int sym)
871 : {
872 0 : unsigned int scope;
873 :
874 0 : if (TextCompareName (subrule, SymbolTable_GetSymName (sym)))
875 : {
876 0 : if (! (QualifiedScope (rule, sym, &i, &scope)))
877 : {
878 : return false;
879 : }
880 0 : if (OptionalLibname (rule, sym, i, scope))
881 : {
882 : return true;
883 : }
884 : }
885 0 : subrule = DynamicStrings_KillString (subrule);
886 0 : if (Debugging)
887 : {
888 : M2Printf_printf0 ((const char *) "MatchRuleQualident FALSE\\n", 26);
889 : }
890 0 : return false;
891 : /* static analysis guarentees a RETURN statement will be used before here. */
892 : __builtin_unreachable ();
893 : }
894 :
895 :
896 : /*
897 : QualifiedScope - PostCondition: true is returned is rule matches a qualified sym.
898 : i is -1 if no more qualifications or libname is found.
899 : scope will be the set to the last outer scope seen.
900 : */
901 :
902 0 : static bool QualifiedScope (DynamicStrings_String rule, unsigned int sym, int *i, unsigned int *scope)
903 : {
904 0 : DynamicStrings_String subrule;
905 0 : int j;
906 0 : NameKey_Name name;
907 :
908 0 : if (Debugging)
909 : {
910 : name = SymbolTable_GetSymName (sym);
911 : M2Printf_printf2 ((const char *) "seen ident name, QualifiedScope (rule = %s, %a)\\n", 49, (const unsigned char *) &rule, (sizeof (rule)-1), (const unsigned char *) &name, (sizeof (name)-1));
912 : }
913 0 : (*scope) = sym;
914 0 : subrule = static_cast<DynamicStrings_String> (NULL);
915 0 : do {
916 0 : j = (*i);
917 0 : (*scope) = SymbolTable_GetScope ((*scope));
918 0 : (*i) = DynamicStrings_ReverseIndex (rule, '.', j-1);
919 0 : if (Debugging)
920 : {
921 : M2Printf_printf2 ((const char *) " reverseindex (rule = %s, '.', j = %d)\\n", 40, (const unsigned char *) &rule, (sizeof (rule)-1), (const unsigned char *) &j, (sizeof (j)-1));
922 : M2Printf_printf1 ((const char *) " returns i = %d\\n", 20, (const unsigned char *) &(*i), (sizeof ((*i))-1));
923 : }
924 0 : if ((*scope) != SymbolTable_NulSym)
925 : {
926 0 : subrule = DynamicStrings_KillString (subrule);
927 0 : subrule = DynamicStrings_Slice (rule, (*i)+1, j);
928 0 : if (Debugging)
929 : {
930 : name = SymbolTable_GetSymName ((*scope));
931 : M2Printf_printf2 ((const char *) "QualifiedScope (subrule = %s, %a)\\n", 35, (const unsigned char *) &subrule, (sizeof (subrule)-1), (const unsigned char *) &name, (sizeof (name)-1));
932 : }
933 0 : if (! (TextCompareName (subrule, SymbolTable_GetSymName ((*scope)))))
934 : {
935 0 : subrule = DynamicStrings_KillString (subrule);
936 0 : if (Debugging)
937 : {
938 : M2Printf_printf0 ((const char *) "QualifiedScope FALSE\\n", 22);
939 : }
940 0 : return false;
941 : }
942 : }
943 0 : } while (! ((((*i) <= 0) || (SymbolTable_IsDefImp ((*scope)))) || (SymbolTable_IsModule ((*scope)))));
944 0 : subrule = DynamicStrings_KillString (subrule);
945 0 : return true;
946 : /* static analysis guarentees a RETURN statement will be used before here. */
947 : __builtin_unreachable ();
948 : }
949 :
950 :
951 : /*
952 : OptionalLibname - returns TRUE if rule[0..dot] matches syms libname or
953 : if there is no libname the scope is a module or defimp
954 : symbol.
955 : */
956 :
957 0 : static bool OptionalLibname (DynamicStrings_String rule, unsigned int sym, int dot, unsigned int scope)
958 : {
959 0 : DynamicStrings_String subrule;
960 :
961 0 : if (dot > 0)
962 : {
963 : /* Check for optional libname. */
964 0 : subrule = DynamicStrings_Slice (rule, 0, dot);
965 0 : if (Debugging)
966 : {
967 : M2Printf_printf2 ((const char *) "checking for optional libname (subrule = %s, '.', dot = %d)\\n", 61, (const unsigned char *) &rule, (sizeof (rule)-1), (const unsigned char *) &dot, (sizeof (dot)-1));
968 : }
969 0 : if (TextCompareName (subrule, SymbolTable_GetLibName (SymbolTable_GetModuleScope (sym))))
970 : {
971 0 : subrule = DynamicStrings_KillString (subrule);
972 0 : if (Debugging)
973 : {
974 : M2Printf_printf0 ((const char *) "OptionalLibname TRUE\\n", 22);
975 : }
976 0 : return true;
977 : }
978 0 : subrule = DynamicStrings_KillString (subrule);
979 : }
980 0 : else if ((scope != SymbolTable_NulSym) && ((SymbolTable_IsModule (scope)) || (SymbolTable_IsDefImp (scope))))
981 : {
982 : /* avoid dangling else. */
983 0 : if (Debugging)
984 : {
985 : M2Printf_printf0 ((const char *) "OptionalLibname TRUE\\n", 22);
986 : }
987 0 : return true;
988 : }
989 : return false;
990 : /* static analysis guarentees a RETURN statement will be used before here. */
991 : __builtin_unreachable ();
992 : }
993 :
994 :
995 : /*
996 : MatchRuleIdent - return TRUE if ident sym matches rule.
997 : The ident must be in a module or defimp scope.
998 : */
999 :
1000 0 : static bool MatchRuleIdent (DynamicStrings_String rule, unsigned int sym)
1001 : {
1002 0 : unsigned int scope;
1003 :
1004 0 : if (TextCompareName (rule, SymbolTable_GetSymName (sym)))
1005 : {
1006 0 : scope = SymbolTable_GetScope (sym);
1007 0 : return (SymbolTable_IsModule (scope)) || (SymbolTable_IsDefImp (scope));
1008 : }
1009 : return false;
1010 : /* static analysis guarentees a RETURN statement will be used before here. */
1011 : __builtin_unreachable ();
1012 : }
1013 :
1014 :
1015 : /*
1016 : MatchRuleText - returns TRUE if rule matches sym.
1017 : */
1018 :
1019 0 : static bool MatchRuleText (DynamicStrings_String rule, unsigned int sym)
1020 : {
1021 0 : return TextCompareName (rule, M2AsmUtil_GetFullScopeAsmName (sym));
1022 : /* static analysis guarentees a RETURN statement will be used before here. */
1023 : __builtin_unreachable ();
1024 : }
1025 :
1026 :
1027 : /*
1028 : TextCompareName - return TRUE if rule matches name.
1029 : */
1030 :
1031 0 : static bool TextCompareName (DynamicStrings_String rule, NameKey_Name name)
1032 : {
1033 0 : bool result;
1034 0 : DynamicStrings_String text;
1035 :
1036 0 : text = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (name));
1037 0 : result = TextMatch (rule, text);
1038 0 : text = DynamicStrings_KillString (text);
1039 0 : return result;
1040 : /* static analysis guarentees a RETURN statement will be used before here. */
1041 : __builtin_unreachable ();
1042 : }
1043 :
1044 :
1045 : /*
1046 : TextMatch - returns TRUE if rule matches text. Currently this
1047 : is a simple string compare, but could be extended
1048 : to implement regexp (seen in the rule).
1049 : */
1050 :
1051 0 : static bool TextMatch (DynamicStrings_String rule, DynamicStrings_String text)
1052 : {
1053 0 : if (Debugging)
1054 : {
1055 : M2Printf_printf2 ((const char *) "TextMatch (%s, %s)\\n", 20, (const unsigned char *) &rule, (sizeof (rule)-1), (const unsigned char *) &text, (sizeof (text)-1));
1056 : }
1057 0 : return DynamicStrings_Equal (rule, text);
1058 : /* static analysis guarentees a RETURN statement will be used before here. */
1059 : __builtin_unreachable ();
1060 : }
1061 :
1062 :
1063 : /*
1064 : CreateTemplate - create and return a template filename with extension.
1065 : If the user has specified "-" then "-" is returned otherwise
1066 : a template is formed from "dumpdir + filename + .%03dl.extension".
1067 : */
1068 :
1069 0 : static DynamicStrings_String CreateTemplate (DynamicStrings_String filename, DynamicStrings_String extension)
1070 : {
1071 0 : if (filename == NULL)
1072 : {
1073 : /* User has not specified a file. */
1074 0 : if ((M2Options_GetDumpDir ()) == NULL)
1075 : {
1076 0 : filename = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (SymbolTable_GetMainModule ())));
1077 : }
1078 : else
1079 : {
1080 0 : filename = DynamicStrings_Dup (M2Options_GetDumpDir ());
1081 0 : filename = DynamicStrings_ConCat (filename, DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (SymbolTable_GetMainModule ())))));
1082 : }
1083 0 : filename = DynamicStrings_ConCat (filename, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".mod", 4)));
1084 : }
1085 : else
1086 : {
1087 : /* We need to duplicate the filename to create a new string before ConCat
1088 : is used later on. */
1089 0 : filename = DynamicStrings_Dup (filename);
1090 : }
1091 0 : if (! (DynamicStrings_EqualArray (filename, (const char *) "-", 1)))
1092 : {
1093 0 : filename = DynamicStrings_ConCat (DynamicStrings_ConCat (filename, DynamicStrings_InitString ((const char *) ".%03dl.", 7)), extension);
1094 : }
1095 0 : return filename;
1096 : /* static analysis guarentees a RETURN statement will be used before here. */
1097 : __builtin_unreachable ();
1098 : }
1099 :
1100 :
1101 : /*
1102 : MakeDeclTemplate - return a template for the decl dump file.
1103 : */
1104 :
1105 0 : static DynamicStrings_String MakeDeclTemplate (void)
1106 : {
1107 0 : return CreateTemplate (M2Options_GetDumpDeclFilename (), DynamicStrings_InitString ((const char *) "decl", 4));
1108 : /* static analysis guarentees a RETURN statement will be used before here. */
1109 : __builtin_unreachable ();
1110 : }
1111 :
1112 :
1113 : /*
1114 : Init - initialize the module global variables.
1115 : */
1116 :
1117 14952 : static void Init (void)
1118 : {
1119 14952 : NoOfQuadDumps = 0;
1120 14952 : NoOfDeclDumps = 0;
1121 14952 : declActive = false;
1122 14952 : quadActive = false;
1123 14952 : mustClose = false;
1124 14952 : outputFile = FIO_StdOut;
1125 0 : }
1126 :
1127 :
1128 : /*
1129 : IsDumpRequiredTree - return TRUE if the gcc tree should be dumped.
1130 : */
1131 :
1132 0 : extern "C" bool M2LangDump_IsDumpRequiredTree (tree gcctree, bool default_)
1133 : {
1134 0 : unsigned int sym;
1135 :
1136 0 : sym = SymbolConversion_Gcc2Mod (gcctree);
1137 0 : if (sym == SymbolTable_NulSym)
1138 : {
1139 : return default_;
1140 : }
1141 : else
1142 : {
1143 0 : return M2LangDump_IsDumpRequired (sym, default_);
1144 : }
1145 : /* static analysis guarentees a RETURN statement will be used before here. */
1146 : __builtin_unreachable ();
1147 : }
1148 :
1149 :
1150 : /*
1151 : IsDumpRequired - return TRUE if symbol sym should be dumped
1152 : according to the rules of the filter.
1153 : No filter specified will always return default.
1154 : The filter is a comma separated list. Each element
1155 : of the list can specify a symbol three ways.
1156 : Firstly by DECL name for example: m2pim_NumberIO_HexToStr
1157 : Secondly by qualified scope: [pathname.]NumberIO.HexToStr
1158 : Thirdly by filename and scope: NumberIO.mod:HexToStr
1159 : */
1160 :
1161 0 : extern "C" bool M2LangDump_IsDumpRequired (unsigned int sym, bool default_)
1162 : {
1163 0 : DynamicStrings_String filter;
1164 :
1165 0 : filter = static_cast<DynamicStrings_String> (M2Options_GetM2DumpFilter ());
1166 0 : if (filter == NULL)
1167 : {
1168 : return default_;
1169 : }
1170 : else
1171 : {
1172 0 : return Match (reinterpret_cast <void *> (filter), sym);
1173 : }
1174 : /* static analysis guarentees a RETURN statement will be used before here. */
1175 : __builtin_unreachable ();
1176 : }
1177 :
1178 :
1179 : /*
1180 : MakeQuadTemplate - return a template for the quad dump file.
1181 : */
1182 :
1183 0 : extern "C" DynamicStrings_String M2LangDump_MakeQuadTemplate (void)
1184 : {
1185 0 : return CreateTemplate (M2Options_GetDumpQuadFilename (), DynamicStrings_InitString ((const char *) "quad", 4));
1186 : /* static analysis guarentees a RETURN statement will be used before here. */
1187 : __builtin_unreachable ();
1188 : }
1189 :
1190 :
1191 : /*
1192 : MakeGimpleTemplate - return a template for the gimple dump file and assign
1193 : len to the max number of characters required to complete
1194 : a template (including a nul terminator).
1195 : */
1196 :
1197 0 : extern "C" DynamicStrings_String M2LangDump_MakeGimpleTemplate (unsigned int *len)
1198 : {
1199 0 : DynamicStrings_String filename;
1200 :
1201 0 : filename = CreateTemplate (M2Options_GetDumpGimpleFilename (), DynamicStrings_InitString ((const char *) "gimple", 6));
1202 0 : (*len) = DynamicStrings_Length (filename); /* This is a short cut based on '%03d' format
1203 : specifier used above. */
1204 0 : return filename; /* This is a short cut based on '%03d' format
1205 : specifier used above. */
1206 : /* static analysis guarentees a RETURN statement will be used before here. */
1207 : __builtin_unreachable ();
1208 : }
1209 :
1210 :
1211 : /*
1212 : GetDumpFile - return the dump output file.
1213 : */
1214 :
1215 0 : extern "C" FIO_File M2LangDump_GetDumpFile (void)
1216 : {
1217 0 : return outputFile;
1218 : /* static analysis guarentees a RETURN statement will be used before here. */
1219 : __builtin_unreachable ();
1220 : }
1221 :
1222 :
1223 : /*
1224 : CreateDumpQuad - create the dump file for a quad dump.
1225 : */
1226 :
1227 0 : extern "C" void M2LangDump_CreateDumpQuad (const char *title_, unsigned int _title_high)
1228 : {
1229 0 : char title[_title_high+1];
1230 :
1231 : /* make a local copy of each unbounded array. */
1232 0 : memcpy (title, title_, _title_high+1);
1233 :
1234 0 : Assert (! declActive);
1235 0 : Assert (! quadActive);
1236 0 : quadActive = true;
1237 0 : NoOfQuadDumps += 1;
1238 0 : OpenDump (M2LangDump_MakeQuadTemplate (), NoOfQuadDumps);
1239 0 : CreateDumpTitle ((const char *) title, _title_high);
1240 0 : }
1241 :
1242 :
1243 : /*
1244 : CloseDumpQuad - close the dump output file.
1245 : */
1246 :
1247 0 : extern "C" void M2LangDump_CloseDumpQuad (void)
1248 : {
1249 0 : CloseDump ();
1250 0 : quadActive = false;
1251 0 : }
1252 :
1253 :
1254 : /*
1255 : CreateDumpDecl - create the dump file for a decl dump.
1256 : */
1257 :
1258 0 : extern "C" void M2LangDump_CreateDumpDecl (const char *title_, unsigned int _title_high)
1259 : {
1260 0 : char title[_title_high+1];
1261 :
1262 : /* make a local copy of each unbounded array. */
1263 0 : memcpy (title, title_, _title_high+1);
1264 :
1265 0 : if ((M2Options_GetM2DumpFilter ()) != NULL)
1266 : {
1267 0 : Assert (! declActive);
1268 0 : Assert (! quadActive);
1269 0 : declActive = true;
1270 0 : NoOfDeclDumps += 1;
1271 0 : OpenDump (MakeDeclTemplate (), NoOfDeclDumps);
1272 0 : CreateDumpTitle ((const char *) title, _title_high);
1273 0 : AddFilterListToDumpWatch (M2Options_GetM2DumpFilter ());
1274 : }
1275 0 : }
1276 :
1277 :
1278 : /*
1279 : CloseDumpDecl - close the dump output file.
1280 : */
1281 :
1282 0 : extern "C" void M2LangDump_CloseDumpDecl (void)
1283 : {
1284 0 : if (declActive)
1285 : {
1286 0 : CloseDump ();
1287 0 : declActive = false;
1288 : }
1289 0 : }
1290 :
1291 14952 : extern "C" void _M2_M2LangDump_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
1292 : {
1293 14952 : Init ();
1294 14952 : }
1295 :
1296 0 : extern "C" void _M2_M2LangDump_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
1297 : {
1298 0 : }
|