xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslcompile.c (revision f3cfa6f6ce31685c6c4a758bc430e69eb99f50a4)
1 /******************************************************************************
2  *
3  * Module Name: aslcompile - top level compile module
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2019, 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 MERCHANTIBILITY 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 
116         if (AslGbl_PreprocessOnly)
117         {
118             UtEndEvent (Event);
119             CmCleanupAndExit ();
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     OpcGetIntegerWidth (AslGbl_ParseTreeRoot->Asl.Child);
179     UtEndEvent (Event);
180 
181     /* Pre-process parse tree for any operator transforms */
182 
183     Event = UtBeginEvent ("Parse tree transforms");
184     DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
185     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
186         TrAmlTransformWalkBegin, TrAmlTransformWalkEnd, NULL);
187     UtEndEvent (Event);
188 
189     /* Generate AML opcodes corresponding to the parse tokens */
190 
191     Event = UtBeginEvent ("Generate AML opcodes");
192     DbgPrint (ASL_DEBUG_OUTPUT, "Generating AML opcodes\n\n");
193     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
194         OpcAmlOpcodeWalk, NULL);
195     UtEndEvent (Event);
196 
197     UtEndEvent (FullCompile);
198     return (AE_OK);
199 
200 ErrorExit:
201     UtEndEvent (FullCompile);
202     return (AE_ERROR);
203 }
204 
205 
206 /*******************************************************************************
207  *
208  * FUNCTION:    CmDoAslMiddleAndBackEnd
209  *
210  * PARAMETERS:  None
211  *
212  * RETURN:      Status of middle-end and back-end
213  *
214  * DESCRIPTION: Perform compiler middle-end (type checking and semantic
215  *              analysis) and back-end (code generation)
216  *
217  ******************************************************************************/
218 
219 int
220 CmDoAslMiddleAndBackEnd (
221     void)
222 {
223     UINT8                   Event;
224     ACPI_STATUS             Status;
225 
226 
227     /* Interpret and generate all compile-time constants */
228 
229     Event = UtBeginEvent ("Constant folding via AML interpreter");
230     DbgPrint (ASL_DEBUG_OUTPUT,
231         "Interpreting compile-time constant expressions\n\n");
232 
233     if (AslGbl_FoldConstants)
234     {
235         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
236             NULL, OpcAmlConstantWalk, NULL);
237     }
238     else
239     {
240         DbgPrint (ASL_PARSE_OUTPUT, "    Optional folding disabled\n");
241     }
242     UtEndEvent (Event);
243 
244     /* Update AML opcodes if necessary, after constant folding */
245 
246     Event = UtBeginEvent ("Updating AML opcodes after constant folding");
247     DbgPrint (ASL_DEBUG_OUTPUT,
248         "Updating AML opcodes after constant folding\n\n");
249     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
250         NULL, OpcAmlOpcodeUpdateWalk, NULL);
251     UtEndEvent (Event);
252 
253     /* Calculate all AML package lengths */
254 
255     Event = UtBeginEvent ("Generate AML package lengths");
256     DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n");
257     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
258         LnPackageLengthWalk, NULL);
259     UtEndEvent (Event);
260 
261     if (AslGbl_ParseOnlyFlag)
262     {
263         AePrintErrorLog (ASL_FILE_STDERR);
264         UtDisplaySummary (ASL_FILE_STDERR);
265         if (AslGbl_DebugFlag)
266         {
267             /* Print error summary to the stdout also */
268 
269             AePrintErrorLog (ASL_FILE_STDOUT);
270             UtDisplaySummary (ASL_FILE_STDOUT);
271         }
272         return (0);
273     }
274 
275     /*
276      * Create an internal namespace and use it as a symbol table
277      */
278 
279     /* Namespace loading */
280 
281     Event = UtBeginEvent ("Create ACPI Namespace");
282     DbgPrint (ASL_DEBUG_OUTPUT, "Creating ACPI Namespace\n\n");
283     Status = LdLoadNamespace (AslGbl_ParseTreeRoot);
284     UtEndEvent (Event);
285     if (ACPI_FAILURE (Status))
286     {
287         return (-1);
288     }
289 
290     /* Namespace cross-reference */
291 
292     AslGbl_NamespaceEvent = UtBeginEvent (
293         "Cross reference parse tree and Namespace");
294     DbgPrint (ASL_DEBUG_OUTPUT, "Cross referencing namespace\n\n");
295     Status = XfCrossReferenceNamespace ();
296     if (ACPI_FAILURE (Status))
297     {
298         return (-1);
299     }
300 
301     /* Namespace - Check for non-referenced objects */
302 
303     LkFindUnreferencedObjects ();
304     UtEndEvent (AslGbl_NamespaceEvent);
305 
306     /* Resolve External Declarations */
307 
308     Event = UtBeginEvent ("Resolve all Externals");
309     DbgPrint (ASL_DEBUG_OUTPUT, "\nResolve Externals\n\n");
310 
311     if (AslGbl_DoExternalsInPlace)
312     {
313         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
314             ExAmlExternalWalkBegin, NULL, NULL);
315     }
316     else
317     {
318         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
319             ExAmlExternalWalkBegin, ExAmlExternalWalkEnd, NULL);
320     }
321     UtEndEvent (Event);
322 
323     /*
324      * Semantic analysis. This can happen only after the
325      * namespace has been loaded and cross-referenced.
326      *
327      * part one - check control methods
328      */
329     Event = UtBeginEvent ("Analyze control method return types");
330     AslGbl_AnalysisWalkInfo.MethodStack = NULL;
331 
332     DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method analysis\n\n");
333 
334     if (AslGbl_CrossReferenceOutput)
335     {
336         OtPrintHeaders ("Part 1: Object Reference Map "
337             "(Object references from within each control method)");
338     }
339 
340     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
341         MtMethodAnalysisWalkBegin,
342         MtMethodAnalysisWalkEnd, &AslGbl_AnalysisWalkInfo);
343     UtEndEvent (Event);
344 
345     /* Generate the object cross-reference file if requested */
346 
347     Event = UtBeginEvent ("Generate cross-reference file");
348     OtCreateXrefFile ();
349     UtEndEvent (Event);
350 
351     /* Semantic error checking part two - typing of method returns */
352 
353     Event = UtBeginEvent ("Determine object types returned by methods");
354     DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method typing\n\n");
355     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
356         NULL, AnMethodTypingWalkEnd, NULL);
357     UtEndEvent (Event);
358 
359     /* Semantic error checking part three - operand type checking */
360 
361     Event = UtBeginEvent ("Analyze AML operand types");
362     DbgPrint (ASL_DEBUG_OUTPUT,
363         "Semantic analysis - Operand type checking\n\n");
364     if (AslGbl_DoTypechecking)
365     {
366         TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
367             NULL, AnOperandTypecheckWalkEnd, &AslGbl_AnalysisWalkInfo);
368     }
369     UtEndEvent (Event);
370 
371     /* Semantic error checking part four - other miscellaneous checks */
372 
373     Event = UtBeginEvent ("Miscellaneous analysis");
374     DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - miscellaneous\n\n");
375     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
376         AnOtherSemanticAnalysisWalkBegin,
377         NULL, &AslGbl_AnalysisWalkInfo);
378     UtEndEvent (Event);
379 
380     /*
381      * ASL-/ASL+ converter: Gbl_ParseTreeRoot->CommentList contains the
382      * very last comment of a given ASL file because it's the last constructed
383      * node during compilation. We take the very last comment and save it in a
384      * global for it to be used by the disassembler.
385      */
386     if (AcpiGbl_CaptureComments)
387     {
388         AcpiGbl_LastListHead = AslGbl_ParseTreeRoot->Asl.CommentList;
389         AslGbl_ParseTreeRoot->Asl.CommentList = NULL;
390     }
391 
392     /* Calculate all AML package lengths */
393 
394     Event = UtBeginEvent ("Finish AML package length generation");
395     DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n");
396     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
397         LnInitLengthsWalk, NULL);
398     TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
399         LnPackageLengthWalk, NULL);
400     UtEndEvent (Event);
401 
402     /* Code generation - emit the AML */
403 
404     Event = UtBeginEvent ("Generate AML code and write output files");
405     DbgPrint (ASL_DEBUG_OUTPUT, "Writing AML byte code\n\n");
406 
407     AslGbl_CurrentDB = AslGbl_ParseTreeRoot->Asl.Child;
408 
409     while (AslGbl_CurrentDB)
410     {
411         switch  (FlSwitchFileSet(AslGbl_CurrentDB->Asl.Filename))
412         {
413             case SWITCH_TO_DIFFERENT_FILE:
414                 /*
415                  * Reset these parameters when definition blocks belong in
416                  * different files. If they belong in the same file, there is
417                  * no need to reset these parameters
418                  */
419                 FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
420                 AslGbl_SourceLine = 0;
421                 AslGbl_NextError = AslGbl_ErrorLog;
422 
423                 /* fall-through */
424 
425             case SWITCH_TO_SAME_FILE:
426 
427                 CgGenerateAmlOutput ();
428                 CmDoOutputFiles ();
429                 AslGbl_CurrentDB = AslGbl_CurrentDB->Asl.Next;
430 
431                 break;
432 
433             default: /* FILE_NOT_FOUND */
434 
435                 /* The requested file could not be found. Get out of here */
436 
437                 AslGbl_CurrentDB = NULL;
438                 break;
439         }
440     }
441     UtEndEvent (Event);
442 
443     Event = UtBeginEvent ("Write optional output files");
444     UtEndEvent (Event);
445 
446     return (0);
447 }
448 
449 
450 /*******************************************************************************
451  *
452  * FUNCTION:    AslCompilerSignon
453  *
454  * PARAMETERS:  FileId      - ID of the output file
455  *
456  * RETURN:      None
457  *
458  * DESCRIPTION: Display compiler signon
459  *
460  ******************************************************************************/
461 
462 void
463 AslCompilerSignon (
464     UINT32                  FileId)
465 {
466     char                    *Prefix = "";
467     char                    *UtilityName;
468 
469 
470     /* Set line prefix depending on the destination file type */
471 
472     switch (FileId)
473     {
474     case ASL_FILE_ASM_SOURCE_OUTPUT:
475     case ASL_FILE_ASM_INCLUDE_OUTPUT:
476 
477         Prefix = "; ";
478         break;
479 
480     case ASL_FILE_HEX_OUTPUT:
481 
482         if (AslGbl_HexOutputFlag == HEX_OUTPUT_ASM)
483         {
484             Prefix = "; ";
485         }
486         else if ((AslGbl_HexOutputFlag == HEX_OUTPUT_C) ||
487                  (AslGbl_HexOutputFlag == HEX_OUTPUT_ASL))
488         {
489             FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
490             Prefix = " * ";
491         }
492         break;
493 
494     case ASL_FILE_C_SOURCE_OUTPUT:
495     case ASL_FILE_C_OFFSET_OUTPUT:
496     case ASL_FILE_C_INCLUDE_OUTPUT:
497 
498         Prefix = " * ";
499         break;
500 
501     default:
502 
503         /* No other output types supported */
504 
505         break;
506     }
507 
508     /* Running compiler or disassembler? */
509 
510     if (AcpiGbl_DisasmFlag)
511     {
512         UtilityName = AML_DISASSEMBLER_NAME;
513     }
514     else
515     {
516         UtilityName = ASL_COMPILER_NAME;
517     }
518 
519     /* Compiler signon with copyright */
520 
521     FlPrintFile (FileId, "%s\n", Prefix);
522     FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
523 }
524 
525 
526 /*******************************************************************************
527  *
528  * FUNCTION:    AslCompilerFileHeader
529  *
530  * PARAMETERS:  FileId      - ID of the output file
531  *
532  * RETURN:      None
533  *
534  * DESCRIPTION: Header used at the beginning of output files
535  *
536  ******************************************************************************/
537 
538 void
539 AslCompilerFileHeader (
540     UINT32                  FileId)
541 {
542     struct tm               *NewTime;
543     time_t                  Aclock;
544     char                    *Prefix = "";
545 
546 
547     /* Set line prefix depending on the destination file type */
548 
549     switch (FileId)
550     {
551     case ASL_FILE_ASM_SOURCE_OUTPUT:
552     case ASL_FILE_ASM_INCLUDE_OUTPUT:
553 
554         Prefix = "; ";
555         break;
556 
557     case ASL_FILE_HEX_OUTPUT:
558 
559         if (AslGbl_HexOutputFlag == HEX_OUTPUT_ASM)
560         {
561             Prefix = "; ";
562         }
563         else if ((AslGbl_HexOutputFlag == HEX_OUTPUT_C) ||
564                  (AslGbl_HexOutputFlag == HEX_OUTPUT_ASL))
565         {
566             Prefix = " * ";
567         }
568         break;
569 
570     case ASL_FILE_C_SOURCE_OUTPUT:
571     case ASL_FILE_C_OFFSET_OUTPUT:
572     case ASL_FILE_C_INCLUDE_OUTPUT:
573 
574         Prefix = " * ";
575         break;
576 
577     default:
578 
579         /* No other output types supported */
580 
581         break;
582     }
583 
584     /* Compilation header with timestamp */
585 
586     (void) time (&Aclock);
587     NewTime = localtime (&Aclock);
588 
589     FlPrintFile (FileId,
590         "%sCompilation of \"%s\" - %s%s\n",
591         Prefix, AslGbl_Files[ASL_FILE_INPUT].Filename, asctime (NewTime),
592         Prefix);
593 
594     switch (FileId)
595     {
596     case ASL_FILE_C_SOURCE_OUTPUT:
597     case ASL_FILE_C_OFFSET_OUTPUT:
598     case ASL_FILE_C_INCLUDE_OUTPUT:
599 
600         FlPrintFile (FileId, " */\n");
601         break;
602 
603     default:
604 
605         /* Nothing to do for other output types */
606 
607         break;
608     }
609 }
610 
611 
612 /*******************************************************************************
613  *
614  * FUNCTION:    CmFlushSourceCode
615  *
616  * PARAMETERS:  None
617  *
618  * RETURN:      None
619  *
620  * DESCRIPTION: Read in any remaining source code after the parse tree
621  *              has been constructed.
622  *
623  ******************************************************************************/
624 
625 static void
626 CmFlushSourceCode (
627     void)
628 {
629     char                    Buffer;
630 
631 
632     while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
633     {
634         AslInsertLineBuffer ((int) Buffer);
635     }
636 
637     AslResetCurrentLineBuffer ();
638 }
639 
640 
641 /*******************************************************************************
642  *
643  * FUNCTION:    CmDoOutputFiles
644  *
645  * PARAMETERS:  None
646  *
647  * RETURN:      None.
648  *
649  * DESCRIPTION: Create all "listing" type files
650  *
651  ******************************************************************************/
652 
653 void
654 CmDoOutputFiles (
655     void)
656 {
657 
658     /* Create listings and hex files */
659 
660     LsDoListings ();
661     HxDoHexOutput ();
662 
663     /* Dump the namespace to the .nsp file if requested */
664 
665     (void) NsDisplayNamespace ();
666 
667     /* Dump the device mapping file */
668 
669     MpEmitMappingInfo ();
670 }
671 
672 
673 /*******************************************************************************
674  *
675  * FUNCTION:    CmDumpAllEvents
676  *
677  * PARAMETERS:  None
678  *
679  * RETURN:      None.
680  *
681  * DESCRIPTION: Dump all compiler events
682  *
683  ******************************************************************************/
684 
685 static void
686 CmDumpAllEvents (
687     void)
688 {
689     ASL_EVENT_INFO          *Event;
690     UINT32                  Delta;
691     UINT32                  MicroSeconds;
692     UINT32                  MilliSeconds;
693     UINT32                  i;
694 
695 
696     Event = AslGbl_Events;
697 
698     DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
699     if (AslGbl_CompileTimesFlag)
700     {
701         printf ("\nElapsed time for major events\n\n");
702     }
703 
704     for (i = 0; i < AslGbl_NextEvent; i++)
705     {
706         if (Event->Valid)
707         {
708             /* Delta will be in 100-nanosecond units */
709 
710             Delta = (UINT32) (Event->EndTime - Event->StartTime);
711 
712             MicroSeconds = Delta / ACPI_100NSEC_PER_USEC;
713             MilliSeconds = Delta / ACPI_100NSEC_PER_MSEC;
714 
715             /* Round milliseconds up */
716 
717             if ((MicroSeconds - (MilliSeconds * ACPI_USEC_PER_MSEC)) >= 500)
718             {
719                 MilliSeconds++;
720             }
721 
722             DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
723                 MicroSeconds, MilliSeconds, Event->EventName);
724 
725             if (AslGbl_CompileTimesFlag)
726             {
727                 printf ("%8u usec %8u msec - %s\n",
728                     MicroSeconds, MilliSeconds, Event->EventName);
729             }
730         }
731 
732         Event++;
733     }
734 }
735 
736 
737 /*******************************************************************************
738  *
739  * FUNCTION:    CmCleanupAndExit
740  *
741  * PARAMETERS:  None
742  *
743  * RETURN:      None.
744  *
745  * DESCRIPTION: Close all open files and exit the compiler
746  *
747  ******************************************************************************/
748 
749 void
750 CmCleanupAndExit (
751     void)
752 {
753     BOOLEAN                 DeleteAmlFile = FALSE;
754     ASL_GLOBAL_FILE_NODE    *CurrentFileNode = AslGbl_FilesList;
755 
756 
757     /* Check if any errors occurred during compile */
758 
759     (void) AslCheckForErrorExit ();
760 
761     AePrintErrorLog (ASL_FILE_STDERR);
762     if (AslGbl_DebugFlag)
763     {
764         /* Print error summary to stdout also */
765 
766         AePrintErrorLog (ASL_FILE_STDOUT);
767     }
768 
769     /* Emit compile times if enabled */
770 
771     CmDumpAllEvents ();
772 
773     if (AslGbl_CompileTimesFlag)
774     {
775         printf ("\nMiscellaneous compile statistics\n\n");
776         printf ("%11u : %s\n", AslGbl_TotalParseNodes, "Parse nodes");
777         printf ("%11u : %s\n", AslGbl_NsLookupCount, "Namespace searches");
778         printf ("%11u : %s\n", AslGbl_TotalNamedObjects, "Named objects");
779         printf ("%11u : %s\n", AslGbl_TotalMethods, "Control methods");
780         printf ("%11u : %s\n", AslGbl_TotalAllocations, "Memory Allocations");
781         printf ("%11u : %s\n", AslGbl_TotalAllocated, "Total allocated memory");
782         printf ("%11u : %s\n", AslGbl_TotalFolds, "Constant subtrees folded");
783         printf ("\n");
784     }
785 
786     if (AslGbl_NsLookupCount)
787     {
788         DbgPrint (ASL_DEBUG_OUTPUT,
789             "\n\nMiscellaneous compile statistics\n\n");
790 
791         DbgPrint (ASL_DEBUG_OUTPUT,
792             "%32s : %u\n", "Total Namespace searches",
793             AslGbl_NsLookupCount);
794 
795         DbgPrint (ASL_DEBUG_OUTPUT,
796             "%32s : %u usec\n", "Time per search", ((UINT32)
797             (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
798                 AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
799                 AslGbl_NsLookupCount);
800     }
801 
802     if (AslGbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
803     {
804         printf ("\nMaximum error count (%d) exceeded\n",
805             ASL_MAX_ERROR_COUNT);
806     }
807 
808     UtDisplaySummary (ASL_FILE_STDOUT);
809 
810     /*
811      * We will delete the AML file if there are errors and the
812      * force AML output option has not been used.
813      */
814     if (AslGbl_ParserErrorDetected || ((AslGbl_ExceptionCount[ASL_ERROR] > 0) &&
815         (!AslGbl_IgnoreErrors) &&
816         AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle))
817     {
818         DeleteAmlFile = TRUE;
819     }
820 
821     /* Close all open files */
822 
823     while (CurrentFileNode)
824     {
825         switch  (FlSwitchFileSet (CurrentFileNode->Files[ASL_FILE_INPUT].Filename))
826         {
827             case SWITCH_TO_SAME_FILE:
828             case SWITCH_TO_DIFFERENT_FILE:
829 
830                 CmFinishFiles (DeleteAmlFile);
831                 CurrentFileNode = CurrentFileNode->Next;
832                 break;
833 
834             case FILE_NOT_FOUND:
835             default:
836 
837                 CurrentFileNode = NULL;
838                 break;
839         }
840     }
841 
842     /* Final cleanup after compiling one file */
843 
844     if (!AslGbl_DoAslConversion)
845     {
846         UtDeleteLocalCaches ();
847     }
848 }
849 
850 
851 /*******************************************************************************
852  *
853  * FUNCTION:    CmFinishFiles
854  *
855  * PARAMETERS:  DeleteAmlFile
856  *
857  * RETURN:      None.
858  *
859  * DESCRIPTION: Close all open files, delete AML files depending on the
860  *              function parameter is true.
861  *
862  ******************************************************************************/
863 
864 static void
865 CmFinishFiles(
866     BOOLEAN                 DeleteAmlFile)
867 {
868     UINT32                  i;
869 
870 
871     /*
872      * Take care with the preprocessor file (.pre), it might be the same
873      * as the "input" file, depending on where the compiler has terminated
874      * or aborted. Prevent attempt to close the same file twice in
875      * loop below.
876      */
877     if (AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
878         AslGbl_Files[ASL_FILE_INPUT].Handle)
879     {
880         AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
881     }
882 
883     /* Close the standard I/O files */
884 
885     for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
886     {
887         /*
888          * Some files such as debug output files could be pointing to
889          * stderr or stdout. Leave these alone.
890          */
891         if (AslGbl_Files[i].Handle != stderr &&
892             AslGbl_Files[i].Handle != stdout)
893         {
894             FlCloseFile (i);
895         }
896     }
897 
898     /* Delete AML file if there are errors */
899 
900     if (DeleteAmlFile)
901     {
902         FlDeleteFile (ASL_FILE_AML_OUTPUT);
903     }
904 
905     /* Delete the preprocessor temp file unless full debug was specified */
906 
907     if (AslGbl_PreprocessFlag && !AslGbl_KeepPreprocessorTempFile)
908     {
909         FlDeleteFile (ASL_FILE_PREPROCESSOR);
910     }
911 
912     /*
913      * Delete intermediate ("combined") source file (if -ls flag not set)
914      * This file is created during normal ASL/AML compiles. It is not
915      * created by the data table compiler.
916      *
917      * If the -ls flag is set, then the .SRC file should not be deleted.
918      * In this case, Gbl_SourceOutputFlag is set to TRUE.
919      *
920      * Note: Handles are cleared by FlCloseFile above, so we look at the
921      * filename instead, to determine if the .SRC file was actually
922      * created.
923      */
924     if (!AslGbl_SourceOutputFlag)
925     {
926         FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
927     }
928 }
929