xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslcompile.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /******************************************************************************
2  *
3  * Module Name: aslcompile - top level compile module
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2021, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "acnamesp.h"
46 
47 #include <stdio.h>
48 #include <time.h>
49 #include <acapps.h>
50 
51 #define _COMPONENT          ACPI_COMPILER
52         ACPI_MODULE_NAME    ("aslcompile")
53 
54 /*
55  * Main parser entry
56  * External is here in case the parser emits the same external in the
57  * generated header. (Newer versions of Bison)
58  */
59 int
60 AslCompilerparse(
61     void);
62 
63 /* Local prototypes */
64 
65 static void
66 CmFlushSourceCode (
67     void);
68 
69 static void
70 CmDumpAllEvents (
71     void);
72 
73 static void
74 CmFinishFiles(
75     BOOLEAN                 DeleteAmlFile);
76 
77 
78 /*******************************************************************************
79  *
80  * FUNCTION:    CmDoCompile
81  *
82  * PARAMETERS:  None
83  *
84  * RETURN:      Status (0 = OK)
85  *
86  * DESCRIPTION: This procedure performs the entire compile
87  *
88  ******************************************************************************/
89 
90 ACPI_STATUS
91 CmDoCompile (
92     void)
93 {
94     UINT8                   FullCompile;
95     UINT8                   Event;
96     ASL_GLOBAL_FILE_NODE    *FileNode;
97 
98 
99     FullCompile = UtBeginEvent ("*** Total Compile time ***");
100     Event = UtBeginEvent ("Open input and output files");
101     UtEndEvent (Event);
102 
103     Event = UtBeginEvent ("Preprocess input file");
104     if (AslGbl_PreprocessFlag)
105     {
106         /* Enter compiler name as a #define */
107 
108         PrAddDefine (ASL_DEFINE, "", FALSE);
109 
110         /* Preprocessor */
111 
112         PrDoPreprocess ();
113         AslGbl_CurrentLineNumber = 1;
114         AslGbl_LogicalLineNumber = 1;
115         AslGbl_CurrentLineOffset = 0;
116 
117         if (AslGbl_PreprocessOnly)
118         {
119             UtEndEvent (Event);
120             return (AE_OK);
121         }
122     }
123     UtEndEvent (Event);
124 
125 
126     /* Build the parse tree */
127 
128     Event = UtBeginEvent ("Parse source code and build parse tree");
129     AslCompilerparse();
130     UtEndEvent (Event);
131 
132     /* Check for parser-detected syntax errors */
133 
134     if (AslGbl_SyntaxError)
135     {
136         fprintf (stderr,
137             "Compiler aborting due to parser-detected syntax error(s)\n");
138 
139         /* Flag this error in the FileNode for compilation summary */
140 
141         FileNode = FlGetCurrentFileNode ();
142         FileNode->ParserErrorDetected = TRUE;
143         AslGbl_ParserErrorDetected = TRUE;
144         LsDumpParseTree ();
145         goto ErrorExit;
146     }
147 
148     /* Did the parse tree get successfully constructed? */
149 
150     if (!AslGbl_ParseTreeRoot)
151     {
152         /*
153          * If there are no errors, then we have some sort of
154          * internal problem.
155          */
156         AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
157             NULL, "- Could not resolve parse tree root node");
158 
159         goto ErrorExit;
160     }
161 
162     /* Flush out any remaining source after parse tree is complete */
163 
164     Event = UtBeginEvent ("Flush source input");
165     CmFlushSourceCode ();
166 
167     /* Prune the parse tree if requested (debug purposes only) */
168 
169     if (AslGbl_PruneParseTree)
170     {
171         AslPruneParseTree (AslGbl_PruneDepth, AslGbl_PruneType);
172     }
173 
174     /* Optional parse tree dump, compiler debug output only */
175 
176     LsDumpParseTree ();
177 
178     UtEndEvent (Event);
179     UtEndEvent (FullCompile);
180     return (AE_OK);
181 
182 ErrorExit:
183     UtEndEvent (FullCompile);
184     return (AE_ERROR);
185 }
186 
187 
188 /*******************************************************************************
189  *
190  * FUNCTION:    CmDoAslMiddleAndBackEnd
191  *
192  * PARAMETERS:  None
193  *
194  * RETURN:      Status of middle-end and back-end
195  *
196  * DESCRIPTION: Perform compiler middle-end (type checking and semantic
197  *              analysis) and back-end (code generation)
198  *
199  ******************************************************************************/
200 
201 int
202 CmDoAslMiddleAndBackEnd (
203     void)
204 {
205     UINT8                   Event;
206     ACPI_STATUS             Status;
207 
208 
209     OpcGetIntegerWidth (AslGbl_ParseTreeRoot->Asl.Child);
210 
211     /* Pre-process parse tree for any operator transforms */
212 
213     Event = UtBeginEvent ("Parse tree transforms");
214     DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
215     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
216         TrAmlTransformWalkBegin, TrAmlTransformWalkEnd, NULL);
217     UtEndEvent (Event);
218 
219     /* Generate AML opcodes corresponding to the parse tokens */
220 
221     Event = UtBeginEvent ("Generate AML opcodes");
222     DbgPrint (ASL_DEBUG_OUTPUT, "Generating AML opcodes\n\n");
223     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
224         NULL, OpcAmlOpcodeWalk, NULL);
225     UtEndEvent (Event);
226 
227 
228     /* Interpret and generate all compile-time constants */
229 
230     Event = UtBeginEvent ("Constant folding via AML interpreter");
231     DbgPrint (ASL_DEBUG_OUTPUT,
232         "Interpreting compile-time constant expressions\n\n");
233 
234     if (AslGbl_FoldConstants)
235     {
236         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
237             NULL, OpcAmlConstantWalk, NULL);
238     }
239     else
240     {
241         DbgPrint (ASL_PARSE_OUTPUT, "    Optional folding disabled\n");
242     }
243     UtEndEvent (Event);
244 
245     /* Update AML opcodes if necessary, after constant folding */
246 
247     Event = UtBeginEvent ("Updating AML opcodes after constant folding");
248     DbgPrint (ASL_DEBUG_OUTPUT,
249         "Updating AML opcodes after constant folding\n\n");
250     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
251         NULL, OpcAmlOpcodeUpdateWalk, NULL);
252     UtEndEvent (Event);
253 
254     /* Calculate all AML package lengths */
255 
256     Event = UtBeginEvent ("Generate AML package lengths");
257     DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n");
258     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
259         LnPackageLengthWalk, NULL);
260     UtEndEvent (Event);
261 
262     if (AslGbl_ParseOnlyFlag)
263     {
264         AePrintErrorLog (ASL_FILE_STDERR);
265         UtDisplaySummary (ASL_FILE_STDERR);
266         if (AslGbl_DebugFlag)
267         {
268             /* Print error summary to the stdout also */
269 
270             AePrintErrorLog (ASL_FILE_STDOUT);
271             UtDisplaySummary (ASL_FILE_STDOUT);
272         }
273         return (0);
274     }
275 
276     /*
277      * Create an internal namespace and use it as a symbol table
278      */
279 
280     /* Namespace loading */
281 
282     Event = UtBeginEvent ("Create ACPI Namespace");
283     DbgPrint (ASL_DEBUG_OUTPUT, "Creating ACPI Namespace\n\n");
284     Status = LdLoadNamespace (AslGbl_ParseTreeRoot);
285     UtEndEvent (Event);
286     if (ACPI_FAILURE (Status))
287     {
288         return (-1);
289     }
290 
291     /* Namespace cross-reference */
292 
293     AslGbl_NamespaceEvent = UtBeginEvent (
294         "Cross reference parse tree and Namespace");
295     DbgPrint (ASL_DEBUG_OUTPUT, "Cross referencing namespace\n\n");
296     Status = XfCrossReferenceNamespace ();
297     if (ACPI_FAILURE (Status))
298     {
299         return (-1);
300     }
301 
302     /* Namespace - Check for non-referenced objects */
303 
304     LkFindUnreferencedObjects ();
305     UtEndEvent (AslGbl_NamespaceEvent);
306 
307     /* Resolve External Declarations */
308 
309     Event = UtBeginEvent ("Resolve all Externals");
310     DbgPrint (ASL_DEBUG_OUTPUT, "\nResolve Externals\n\n");
311 
312     if (AslGbl_DoExternalsInPlace)
313     {
314         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
315             ExAmlExternalWalkBegin, NULL, NULL);
316     }
317     else
318     {
319         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
320             ExAmlExternalWalkBegin, ExAmlExternalWalkEnd, NULL);
321     }
322     UtEndEvent (Event);
323 
324     /*
325      * Semantic analysis. This can happen only after the
326      * namespace has been loaded and cross-referenced.
327      *
328      * part one - check control methods
329      */
330     Event = UtBeginEvent ("Analyze control method return types");
331     AslGbl_AnalysisWalkInfo.MethodStack = NULL;
332 
333     DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method analysis\n\n");
334 
335     if (AslGbl_CrossReferenceOutput)
336     {
337         OtPrintHeaders ("Part 1: Object Reference Map "
338             "(Object references from within each control method)");
339     }
340 
341     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
342         MtMethodAnalysisWalkBegin,
343         MtMethodAnalysisWalkEnd, &AslGbl_AnalysisWalkInfo);
344     UtEndEvent (Event);
345 
346     /* Generate the object cross-reference file if requested */
347 
348     Event = UtBeginEvent ("Generate cross-reference file");
349     OtCreateXrefFile ();
350     UtEndEvent (Event);
351 
352     /* Semantic error checking part two - typing of method returns */
353 
354     Event = UtBeginEvent ("Determine object types returned by methods");
355     DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method typing\n\n");
356     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
357         NULL, AnMethodTypingWalkEnd, NULL);
358     UtEndEvent (Event);
359 
360     /* Semantic error checking part three - operand type checking */
361 
362     Event = UtBeginEvent ("Analyze AML operand types");
363     DbgPrint (ASL_DEBUG_OUTPUT,
364         "Semantic analysis - Operand type checking\n\n");
365     if (AslGbl_DoTypechecking)
366     {
367         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
368             NULL, AnOperandTypecheckWalkEnd, &AslGbl_AnalysisWalkInfo);
369     }
370     UtEndEvent (Event);
371 
372     /* Semantic error checking part four - other miscellaneous checks */
373 
374     Event = UtBeginEvent ("Miscellaneous analysis");
375     DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - miscellaneous\n\n");
376     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
377         AnOtherSemanticAnalysisWalkBegin,
378         NULL, &AslGbl_AnalysisWalkInfo);
379     UtEndEvent (Event);
380 
381     /*
382      * ASL-/ASL+ converter: Gbl_ParseTreeRoot->CommentList contains the
383      * very last comment of a given ASL file because it's the last constructed
384      * node during compilation. We take the very last comment and save it in a
385      * global for it to be used by the disassembler.
386      */
387     if (AcpiGbl_CaptureComments)
388     {
389         AcpiGbl_LastListHead = AslGbl_ParseTreeRoot->Asl.CommentList;
390         AslGbl_ParseTreeRoot->Asl.CommentList = NULL;
391     }
392 
393     /* Calculate all AML package lengths */
394 
395     Event = UtBeginEvent ("Finish AML package length generation");
396     DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n");
397     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
398         LnInitLengthsWalk, NULL);
399     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
400         LnPackageLengthWalk, NULL);
401     UtEndEvent (Event);
402 
403     /* Code generation - emit the AML */
404 
405     Event = UtBeginEvent ("Generate AML code and write output files");
406     DbgPrint (ASL_DEBUG_OUTPUT, "Writing AML byte code\n\n");
407 
408     AslGbl_CurrentDB = AslGbl_ParseTreeRoot->Asl.Child;
409 
410     while (AslGbl_CurrentDB)
411     {
412         switch  (FlSwitchFileSet(AslGbl_CurrentDB->Asl.Filename))
413         {
414             case SWITCH_TO_DIFFERENT_FILE:
415                 /*
416                  * Reset these parameters when definition blocks belong in
417                  * different files. If they belong in the same file, there is
418                  * no need to reset these parameters
419                  */
420                 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
421                 AslGbl_SourceLine = 0;
422                 AslGbl_NextError = AslGbl_ErrorLog;
423 
424                 /* fall-through */
425 
426             case SWITCH_TO_SAME_FILE:
427 
428                 CgGenerateAmlOutput ();
429                 CmDoOutputFiles ();
430                 AslGbl_CurrentDB = AslGbl_CurrentDB->Asl.Next;
431 
432                 break;
433 
434             default: /* FILE_NOT_FOUND */
435 
436                 /* The requested file could not be found. Get out of here */
437 
438                 AslGbl_CurrentDB = NULL;
439                 break;
440         }
441     }
442     UtEndEvent (Event);
443 
444     Event = UtBeginEvent ("Write optional output files");
445     UtEndEvent (Event);
446 
447     return (0);
448 }
449 
450 
451 /*******************************************************************************
452  *
453  * FUNCTION:    AslCompilerSignon
454  *
455  * PARAMETERS:  FileId      - ID of the output file
456  *
457  * RETURN:      None
458  *
459  * DESCRIPTION: Display compiler signon
460  *
461  ******************************************************************************/
462 
463 void
464 AslCompilerSignon (
465     UINT32                  FileId)
466 {
467     char                    *Prefix = "";
468     char                    *UtilityName;
469 
470 
471     /* Set line prefix depending on the destination file type */
472 
473     switch (FileId)
474     {
475     case ASL_FILE_ASM_SOURCE_OUTPUT:
476     case ASL_FILE_ASM_INCLUDE_OUTPUT:
477 
478         Prefix = "; ";
479         break;
480 
481     case ASL_FILE_HEX_OUTPUT:
482 
483         if (AslGbl_HexOutputFlag == HEX_OUTPUT_ASM)
484         {
485             Prefix = "; ";
486         }
487         else if ((AslGbl_HexOutputFlag == HEX_OUTPUT_C) ||
488                  (AslGbl_HexOutputFlag == HEX_OUTPUT_ASL))
489         {
490             FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
491             Prefix = " * ";
492         }
493         break;
494 
495     case ASL_FILE_C_SOURCE_OUTPUT:
496     case ASL_FILE_C_OFFSET_OUTPUT:
497     case ASL_FILE_C_INCLUDE_OUTPUT:
498 
499         Prefix = " * ";
500         break;
501 
502     default:
503 
504         /* No other output types supported */
505 
506         break;
507     }
508 
509     /* Running compiler or disassembler? */
510 
511     if (AcpiGbl_DisasmFlag)
512     {
513         UtilityName = AML_DISASSEMBLER_NAME;
514     }
515     else
516     {
517         UtilityName = ASL_COMPILER_NAME;
518     }
519 
520     /* Compiler signon with copyright */
521 
522     FlPrintFile (FileId, "%s\n", Prefix);
523     FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
524 }
525 
526 
527 /*******************************************************************************
528  *
529  * FUNCTION:    AslCompilerFileHeader
530  *
531  * PARAMETERS:  FileId      - ID of the output file
532  *
533  * RETURN:      None
534  *
535  * DESCRIPTION: Header used at the beginning of output files
536  *
537  ******************************************************************************/
538 
539 void
540 AslCompilerFileHeader (
541     UINT32                  FileId)
542 {
543     char                    *NewTime;
544     time_t                  Aclock;
545     char                    *Prefix = "";
546 
547 
548     /* Set line prefix depending on the destination file type */
549 
550     switch (FileId)
551     {
552     case ASL_FILE_ASM_SOURCE_OUTPUT:
553     case ASL_FILE_ASM_INCLUDE_OUTPUT:
554 
555         Prefix = "; ";
556         break;
557 
558     case ASL_FILE_HEX_OUTPUT:
559 
560         if (AslGbl_HexOutputFlag == HEX_OUTPUT_ASM)
561         {
562             Prefix = "; ";
563         }
564         else if ((AslGbl_HexOutputFlag == HEX_OUTPUT_C) ||
565                  (AslGbl_HexOutputFlag == HEX_OUTPUT_ASL))
566         {
567             Prefix = " * ";
568         }
569         break;
570 
571     case ASL_FILE_C_SOURCE_OUTPUT:
572     case ASL_FILE_C_OFFSET_OUTPUT:
573     case ASL_FILE_C_INCLUDE_OUTPUT:
574 
575         Prefix = " * ";
576         break;
577 
578     default:
579 
580         /* No other output types supported */
581 
582         break;
583     }
584 
585     /* Compilation header with timestamp */
586 
587     Aclock = time (NULL);
588     NewTime = ctime (&Aclock);
589 
590     FlPrintFile (FileId,
591         "%sCompilation of \"%s\" -",
592         Prefix, AslGbl_Files[ASL_FILE_INPUT].Filename);
593 
594     if (NewTime)
595     {
596         FlPrintFile (FileId, " %s%s\n", NewTime, Prefix);
597     }
598 
599     switch (FileId)
600     {
601     case ASL_FILE_C_SOURCE_OUTPUT:
602     case ASL_FILE_C_OFFSET_OUTPUT:
603     case ASL_FILE_C_INCLUDE_OUTPUT:
604 
605         FlPrintFile (FileId, " */\n");
606         break;
607 
608     default:
609 
610         /* Nothing to do for other output types */
611 
612         break;
613     }
614 }
615 
616 
617 /*******************************************************************************
618  *
619  * FUNCTION:    CmFlushSourceCode
620  *
621  * PARAMETERS:  None
622  *
623  * RETURN:      None
624  *
625  * DESCRIPTION: Read in any remaining source code after the parse tree
626  *              has been constructed.
627  *
628  ******************************************************************************/
629 
630 static void
631 CmFlushSourceCode (
632     void)
633 {
634     char                    Buffer;
635 
636 
637     while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
638     {
639         AslInsertLineBuffer ((int) Buffer);
640     }
641 
642     AslResetCurrentLineBuffer ();
643 }
644 
645 
646 /*******************************************************************************
647  *
648  * FUNCTION:    CmDoOutputFiles
649  *
650  * PARAMETERS:  None
651  *
652  * RETURN:      None.
653  *
654  * DESCRIPTION: Create all "listing" type files
655  *
656  ******************************************************************************/
657 
658 void
659 CmDoOutputFiles (
660     void)
661 {
662 
663     /* Create listings and hex files */
664 
665     LsDoListings ();
666     HxDoHexOutput ();
667 
668     /* Dump the namespace to the .nsp file if requested */
669 
670     (void) NsDisplayNamespace ();
671 
672     /* Dump the device mapping file */
673 
674     MpEmitMappingInfo ();
675 }
676 
677 
678 /*******************************************************************************
679  *
680  * FUNCTION:    CmDumpAllEvents
681  *
682  * PARAMETERS:  None
683  *
684  * RETURN:      None.
685  *
686  * DESCRIPTION: Dump all compiler events
687  *
688  ******************************************************************************/
689 
690 static void
691 CmDumpAllEvents (
692     void)
693 {
694     ASL_EVENT_INFO          *Event;
695     UINT32                  Delta;
696     UINT32                  MicroSeconds;
697     UINT32                  MilliSeconds;
698     UINT32                  i;
699 
700 
701     Event = AslGbl_Events;
702 
703     DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
704     if (AslGbl_CompileTimesFlag)
705     {
706         printf ("\nElapsed time for major events\n\n");
707     }
708 
709     for (i = 0; i < AslGbl_NextEvent; i++)
710     {
711         if (Event->Valid)
712         {
713             /* Delta will be in 100-nanosecond units */
714 
715             Delta = (UINT32) (Event->EndTime - Event->StartTime);
716 
717             MicroSeconds = Delta / ACPI_100NSEC_PER_USEC;
718             MilliSeconds = Delta / ACPI_100NSEC_PER_MSEC;
719 
720             /* Round milliseconds up */
721 
722             if ((MicroSeconds - (MilliSeconds * ACPI_USEC_PER_MSEC)) >= 500)
723             {
724                 MilliSeconds++;
725             }
726 
727             DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
728                 MicroSeconds, MilliSeconds, Event->EventName);
729 
730             if (AslGbl_CompileTimesFlag)
731             {
732                 printf ("%8u usec %8u msec - %s\n",
733                     MicroSeconds, MilliSeconds, Event->EventName);
734             }
735         }
736 
737         Event++;
738     }
739 }
740 
741 
742 /*******************************************************************************
743  *
744  * FUNCTION:    CmCleanupAndExit
745  *
746  * PARAMETERS:  None
747  *
748  * RETURN:      None.
749  *
750  * DESCRIPTION: Close all open files and exit the compiler
751  *
752  ******************************************************************************/
753 
754 int
755 CmCleanupAndExit (
756     void)
757 {
758     int                     Status = 0;
759     BOOLEAN                 DeleteAmlFile = FALSE;
760     ASL_GLOBAL_FILE_NODE    *CurrentFileNode = AslGbl_FilesList;
761 
762 
763     /* Check if any errors occurred during compile */
764 
765     (void) AslCheckForErrorExit ();
766 
767     AePrintErrorLog (ASL_FILE_STDERR);
768     if (AslGbl_DebugFlag)
769     {
770         /* Print error summary to stdout also */
771 
772         AePrintErrorLog (ASL_FILE_STDOUT);
773     }
774 
775     /* Emit compile times if enabled */
776 
777     CmDumpAllEvents ();
778 
779     if (AslGbl_CompileTimesFlag)
780     {
781         printf ("\nMiscellaneous compile statistics\n\n");
782         printf ("%11u : %s\n", AslGbl_TotalParseNodes, "Parse nodes");
783         printf ("%11u : %s\n", AslGbl_NsLookupCount, "Namespace searches");
784         printf ("%11u : %s\n", AslGbl_TotalNamedObjects, "Named objects");
785         printf ("%11u : %s\n", AslGbl_TotalMethods, "Control methods");
786         printf ("%11u : %s\n", AslGbl_TotalAllocations, "Memory Allocations");
787         printf ("%11u : %s\n", AslGbl_TotalAllocated, "Total allocated memory");
788         printf ("%11u : %s\n", AslGbl_TotalFolds, "Constant subtrees folded");
789         printf ("\n");
790     }
791 
792     if (AslGbl_NsLookupCount)
793     {
794         DbgPrint (ASL_DEBUG_OUTPUT,
795             "\n\nMiscellaneous compile statistics\n\n");
796 
797         DbgPrint (ASL_DEBUG_OUTPUT,
798             "%32s : %u\n", "Total Namespace searches",
799             AslGbl_NsLookupCount);
800 
801         DbgPrint (ASL_DEBUG_OUTPUT,
802             "%32s : %u usec\n", "Time per search", ((UINT32)
803             (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
804                 AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
805                 AslGbl_NsLookupCount);
806     }
807 
808     if (AslGbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
809     {
810         printf ("\nMaximum error count (%d) exceeded\n",
811             ASL_MAX_ERROR_COUNT);
812     }
813 
814     UtDisplaySummary (ASL_FILE_STDOUT);
815 
816     /*
817      * Delete the AML file if there are errors and the force AML output option
818      * (-f) has not been used.
819      *
820      * Return -1 as a status of the compiler if no AML files are generated. If
821      * the AML file is generated in the presence of errors, return 0. In the
822      * latter case, the errors were ignored by the user so the compilation is
823      * considered successful.
824      */
825     if (AslGbl_ParserErrorDetected || AslGbl_PreprocessOnly ||
826         ((AslGbl_ExceptionCount[ASL_ERROR] > 0) &&
827         (!AslGbl_IgnoreErrors) &&
828         AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle))
829     {
830         DeleteAmlFile = TRUE;
831         Status = -1;
832     }
833 
834     /* Close all open files */
835 
836     while (CurrentFileNode)
837     {
838         /*
839          * Set the program return status based on file errors. If there are any
840          * errors and during compilation, the command is not considered
841          * successful.
842          */
843         if (Status != -1 && !AslGbl_IgnoreErrors &&
844             CurrentFileNode->ParserErrorDetected)
845         {
846             Status = -1;
847         }
848 
849         switch  (FlSwitchFileSet (CurrentFileNode->Files[ASL_FILE_INPUT].Filename))
850         {
851             case SWITCH_TO_SAME_FILE:
852             case SWITCH_TO_DIFFERENT_FILE:
853 
854                 CmFinishFiles (DeleteAmlFile);
855                 CurrentFileNode = CurrentFileNode->Next;
856                 break;
857 
858             case FILE_NOT_FOUND:
859             default:
860 
861                 CurrentFileNode = NULL;
862                 break;
863         }
864     }
865 
866     /* Final cleanup after compiling one file */
867 
868     if (!AslGbl_DoAslConversion)
869     {
870         UtDeleteLocalCaches ();
871     }
872 
873     return (Status);
874 }
875 
876 
877 /*******************************************************************************
878  *
879  * FUNCTION:    CmFinishFiles
880  *
881  * PARAMETERS:  DeleteAmlFile
882  *
883  * RETURN:      None.
884  *
885  * DESCRIPTION: Close all open files, delete AML files depending on the
886  *              function parameter is true.
887  *
888  ******************************************************************************/
889 
890 static void
891 CmFinishFiles(
892     BOOLEAN                 DeleteAmlFile)
893 {
894     UINT32                  i;
895 
896 
897     /*
898      * Take care with the preprocessor file (.pre), it might be the same
899      * as the "input" file, depending on where the compiler has terminated
900      * or aborted. Prevent attempt to close the same file twice in
901      * loop below.
902      */
903     if (AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
904         AslGbl_Files[ASL_FILE_INPUT].Handle)
905     {
906         AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
907     }
908 
909     /* Close the standard I/O files */
910 
911     for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
912     {
913         /*
914          * Some files such as debug output files could be pointing to
915          * stderr or stdout. Leave these alone.
916          */
917         if (AslGbl_Files[i].Handle != stderr &&
918             AslGbl_Files[i].Handle != stdout)
919         {
920             FlCloseFile (i);
921         }
922     }
923 
924     /* Delete AML file if there are errors */
925 
926     if (DeleteAmlFile)
927     {
928         FlDeleteFile (ASL_FILE_AML_OUTPUT);
929     }
930 
931     /* Delete the preprocessor temp file unless full debug was specified */
932 
933     if (AslGbl_PreprocessFlag && !AslGbl_KeepPreprocessorTempFile)
934     {
935         FlDeleteFile (ASL_FILE_PREPROCESSOR);
936     }
937 
938     /*
939      * Delete intermediate ("combined") source file (if -ls flag not set)
940      * This file is created during normal ASL/AML compiles. It is not
941      * created by the data table compiler.
942      *
943      * If the -ls flag is set, then the .SRC file should not be deleted.
944      * In this case, Gbl_SourceOutputFlag is set to TRUE.
945      *
946      * Note: Handles are cleared by FlCloseFile above, so we look at the
947      * filename instead, to determine if the .SRC file was actually
948      * created.
949      */
950     if (!AslGbl_SourceOutputFlag)
951     {
952         FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
953     }
954 }
955