1 /******************************************************************************
2  *
3  * Module Name: aslcompile - top level compile module
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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
CmDoCompile(void)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
CmDoAslMiddleAndBackEnd(void)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
AslCompilerSignon(UINT32 FileId)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
AslCompilerFileHeader(UINT32 FileId)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     Aclock = time (NULL);
595     NewTime = ctime (&Aclock);
596 
597     FlPrintFile (FileId,
598         "%sCompilation of \"%s\" -",
599         Prefix, AslGbl_Files[ASL_FILE_INPUT].Filename);
600 
601     if (NewTime)
602     {
603         FlPrintFile (FileId, " %s%s\n", NewTime, Prefix);
604     }
605 
606     switch (FileId)
607     {
608     case ASL_FILE_C_SOURCE_OUTPUT:
609     case ASL_FILE_C_OFFSET_OUTPUT:
610     case ASL_FILE_C_INCLUDE_OUTPUT:
611 
612         FlPrintFile (FileId, " */\n");
613         break;
614 
615     default:
616 
617         /* Nothing to do for other output types */
618 
619         break;
620     }
621 }
622 
623 
624 /*******************************************************************************
625  *
626  * FUNCTION:    CmFlushSourceCode
627  *
628  * PARAMETERS:  None
629  *
630  * RETURN:      None
631  *
632  * DESCRIPTION: Read in any remaining source code after the parse tree
633  *              has been constructed.
634  *
635  ******************************************************************************/
636 
637 static void
CmFlushSourceCode(void)638 CmFlushSourceCode (
639     void)
640 {
641     char                    Buffer;
642 
643 
644     while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
645     {
646         AslInsertLineBuffer ((int) Buffer);
647     }
648 
649     AslResetCurrentLineBuffer ();
650 }
651 
652 
653 /*******************************************************************************
654  *
655  * FUNCTION:    CmDoOutputFiles
656  *
657  * PARAMETERS:  None
658  *
659  * RETURN:      None.
660  *
661  * DESCRIPTION: Create all "listing" type files
662  *
663  ******************************************************************************/
664 
665 void
CmDoOutputFiles(void)666 CmDoOutputFiles (
667     void)
668 {
669 
670     /* Create listings and hex files */
671 
672     LsDoListings ();
673     HxDoHexOutput ();
674 
675     /* Dump the namespace to the .nsp file if requested */
676 
677     (void) NsDisplayNamespace ();
678 
679     /* Dump the device mapping file */
680 
681     MpEmitMappingInfo ();
682 }
683 
684 
685 /*******************************************************************************
686  *
687  * FUNCTION:    CmDumpAllEvents
688  *
689  * PARAMETERS:  None
690  *
691  * RETURN:      None.
692  *
693  * DESCRIPTION: Dump all compiler events
694  *
695  ******************************************************************************/
696 
697 static void
CmDumpAllEvents(void)698 CmDumpAllEvents (
699     void)
700 {
701     ASL_EVENT_INFO          *Event;
702     UINT32                  Delta;
703     UINT32                  MicroSeconds;
704     UINT32                  MilliSeconds;
705     UINT32                  i;
706 
707 
708     Event = AslGbl_Events;
709 
710     DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
711     if (AslGbl_CompileTimesFlag)
712     {
713         printf ("\nElapsed time for major events\n\n");
714     }
715 
716     for (i = 0; i < AslGbl_NextEvent; i++)
717     {
718         if (Event->Valid)
719         {
720             /* Delta will be in 100-nanosecond units */
721 
722             Delta = (UINT32) (Event->EndTime - Event->StartTime);
723 
724             MicroSeconds = Delta / ACPI_100NSEC_PER_USEC;
725             MilliSeconds = Delta / ACPI_100NSEC_PER_MSEC;
726 
727             /* Round milliseconds up */
728 
729             if ((MicroSeconds - (MilliSeconds * ACPI_USEC_PER_MSEC)) >= 500)
730             {
731                 MilliSeconds++;
732             }
733 
734             DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
735                 MicroSeconds, MilliSeconds, Event->EventName);
736 
737             if (AslGbl_CompileTimesFlag)
738             {
739                 printf ("%8u usec %8u msec - %s\n",
740                     MicroSeconds, MilliSeconds, Event->EventName);
741             }
742         }
743 
744         Event++;
745     }
746 }
747 
748 
749 /*******************************************************************************
750  *
751  * FUNCTION:    CmCleanupAndExit
752  *
753  * PARAMETERS:  None
754  *
755  * RETURN:      None.
756  *
757  * DESCRIPTION: Close all open files and exit the compiler
758  *
759  ******************************************************************************/
760 
761 int
CmCleanupAndExit(void)762 CmCleanupAndExit (
763     void)
764 {
765     int                     Status = 0;
766     BOOLEAN                 DeleteAmlFile = FALSE;
767     ASL_GLOBAL_FILE_NODE    *CurrentFileNode = AslGbl_FilesList;
768 
769 
770     /* Check if any errors occurred during compile */
771 
772     (void) AslCheckForErrorExit ();
773 
774     AePrintErrorLog (ASL_FILE_STDERR);
775     if (AslGbl_DebugFlag)
776     {
777         /* Print error summary to stdout also */
778 
779         AePrintErrorLog (ASL_FILE_STDOUT);
780     }
781 
782     /* Emit compile times if enabled */
783 
784     CmDumpAllEvents ();
785 
786     if (AslGbl_CompileTimesFlag)
787     {
788         printf ("\nMiscellaneous compile statistics\n\n");
789         printf ("%11u : %s\n", AslGbl_TotalParseNodes, "Parse nodes");
790         printf ("%11u : %s\n", AslGbl_NsLookupCount, "Namespace searches");
791         printf ("%11u : %s\n", AslGbl_TotalNamedObjects, "Named objects");
792         printf ("%11u : %s\n", AslGbl_TotalMethods, "Control methods");
793         printf ("%11u : %s\n", AslGbl_TotalAllocations, "Memory Allocations");
794         printf ("%11u : %s\n", AslGbl_TotalAllocated, "Total allocated memory");
795         printf ("%11u : %s\n", AslGbl_TotalFolds, "Constant subtrees folded");
796         printf ("\n");
797     }
798 
799     if (AslGbl_NsLookupCount)
800     {
801         DbgPrint (ASL_DEBUG_OUTPUT,
802             "\n\nMiscellaneous compile statistics\n\n");
803 
804         DbgPrint (ASL_DEBUG_OUTPUT,
805             "%32s : %u\n", "Total Namespace searches",
806             AslGbl_NsLookupCount);
807 
808         DbgPrint (ASL_DEBUG_OUTPUT,
809             "%32s : %u usec\n", "Time per search", ((UINT32)
810             (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
811                 AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
812                 AslGbl_NsLookupCount);
813     }
814 
815     if (AslGbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
816     {
817         printf ("\nMaximum error count (%d) exceeded (aslcompile.c)\n",
818             ASL_MAX_ERROR_COUNT);
819     }
820 
821     UtDisplaySummary (ASL_FILE_STDOUT);
822 
823     /*
824      * Delete the AML file if there are errors and the force AML output option
825      * (-f) has not been used.
826      *
827      * Return -1 as a status of the compiler if no AML files are generated. If
828      * the AML file is generated in the presence of errors, return 0. In the
829      * latter case, the errors were ignored by the user so the compilation is
830      * considered successful.
831      */
832     if (AslGbl_ParserErrorDetected || AslGbl_PreprocessOnly ||
833         ((AslGbl_ExceptionCount[ASL_ERROR] > 0) &&
834         (!AslGbl_IgnoreErrors) &&
835         AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle))
836     {
837         DeleteAmlFile = TRUE;
838         Status = -1;
839     }
840 
841     /* Close all open files */
842 
843     while (CurrentFileNode)
844     {
845         /*
846          * Set the program return status based on file errors. If there are any
847          * errors and during compilation, the command is not considered
848          * successful.
849          */
850         if (Status != -1 && !AslGbl_IgnoreErrors &&
851             CurrentFileNode->ParserErrorDetected)
852         {
853             Status = -1;
854         }
855 
856         switch  (FlSwitchFileSet (CurrentFileNode->Files[ASL_FILE_INPUT].Filename))
857         {
858             case SWITCH_TO_SAME_FILE:
859             case SWITCH_TO_DIFFERENT_FILE:
860 
861                 CmFinishFiles (DeleteAmlFile);
862                 CurrentFileNode = CurrentFileNode->Next;
863                 break;
864 
865             case FILE_NOT_FOUND:
866             default:
867 
868                 CurrentFileNode = NULL;
869                 break;
870         }
871     }
872 
873     /* Final cleanup after compiling one file */
874 
875     if (!AslGbl_DoAslConversion)
876     {
877         UtDeleteLocalCaches ();
878     }
879 
880     return (Status);
881 }
882 
883 
884 /*******************************************************************************
885  *
886  * FUNCTION:    CmFinishFiles
887  *
888  * PARAMETERS:  DeleteAmlFile
889  *
890  * RETURN:      None.
891  *
892  * DESCRIPTION: Close all open files, delete AML files depending on the
893  *              function parameter is true.
894  *
895  ******************************************************************************/
896 
897 static void
CmFinishFiles(BOOLEAN DeleteAmlFile)898 CmFinishFiles(
899     BOOLEAN                 DeleteAmlFile)
900 {
901     UINT32                  i;
902 
903 
904     /*
905      * Take care with the preprocessor file (.pre), it might be the same
906      * as the "input" file, depending on where the compiler has terminated
907      * or aborted. Prevent attempt to close the same file twice in
908      * loop below.
909      */
910     if (AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
911         AslGbl_Files[ASL_FILE_INPUT].Handle)
912     {
913         AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
914     }
915 
916     /* Close the standard I/O files */
917 
918     for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
919     {
920         /*
921          * Some files such as debug output files could be pointing to
922          * stderr or stdout. Leave these alone.
923          */
924         if (AslGbl_Files[i].Handle != stderr &&
925             AslGbl_Files[i].Handle != stdout)
926         {
927             FlCloseFile (i);
928         }
929     }
930 
931     /* Delete AML file if there are errors */
932 
933     if (DeleteAmlFile)
934     {
935         FlDeleteFile (ASL_FILE_AML_OUTPUT);
936     }
937 
938     /* Delete the preprocessor temp file unless full debug was specified */
939 
940     if (AslGbl_PreprocessFlag && !AslGbl_KeepPreprocessorTempFile)
941     {
942         FlDeleteFile (ASL_FILE_PREPROCESSOR);
943     }
944 
945     /*
946      * Delete intermediate ("combined") source file (if -ls flag not set)
947      * This file is created during normal ASL/AML compiles. It is not
948      * created by the data table compiler.
949      *
950      * If the -ls flag is set, then the .SRC file should not be deleted.
951      * In this case, Gbl_SourceOutputFlag is set to TRUE.
952      *
953      * Note: Handles are cleared by FlCloseFile above, so we look at the
954      * filename instead, to determine if the .SRC file was actually
955      * created.
956      */
957     if (!AslGbl_SourceOutputFlag)
958     {
959         FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
960     }
961 }
962