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