xref: /freebsd/sys/contrib/dev/acpica/compiler/aslcompile.c (revision de7b456e596ff18032d2cbfdf244c66f36770da4)
1 /******************************************************************************
2  *
3  * Module Name: aslcompile - top level compile module
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include <contrib/dev/acpica/compiler/dtcompiler.h>
46 
47 #include <stdio.h>
48 #include <time.h>
49 #include <contrib/dev/acpica/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 FlConsumeAnsiComment (
71     FILE                    *Handle,
72     ASL_FILE_STATUS         *Status);
73 
74 static void
75 FlConsumeNewComment (
76     FILE                    *Handle,
77     ASL_FILE_STATUS         *Status);
78 
79 static void
80 CmDumpAllEvents (
81     void);
82 
83 
84 /*******************************************************************************
85  *
86  * FUNCTION:    AslCompilerSignon
87  *
88  * PARAMETERS:  FileId      - ID of the output file
89  *
90  * RETURN:      None
91  *
92  * DESCRIPTION: Display compiler signon
93  *
94  ******************************************************************************/
95 
96 void
97 AslCompilerSignon (
98     UINT32                  FileId)
99 {
100     char                    *Prefix = "";
101     char                    *UtilityName;
102 
103 
104     /* Set line prefix depending on the destination file type */
105 
106     switch (FileId)
107     {
108     case ASL_FILE_ASM_SOURCE_OUTPUT:
109     case ASL_FILE_ASM_INCLUDE_OUTPUT:
110 
111         Prefix = "; ";
112         break;
113 
114     case ASL_FILE_HEX_OUTPUT:
115 
116         if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM)
117         {
118             Prefix = "; ";
119         }
120         else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
121                  (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
122         {
123             FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
124             Prefix = " * ";
125         }
126         break;
127 
128     case ASL_FILE_C_SOURCE_OUTPUT:
129     case ASL_FILE_C_OFFSET_OUTPUT:
130     case ASL_FILE_C_INCLUDE_OUTPUT:
131 
132         Prefix = " * ";
133         break;
134 
135     default:
136 
137         /* No other output types supported */
138 
139         break;
140     }
141 
142     /* Running compiler or disassembler? */
143 
144     if (Gbl_DisasmFlag)
145     {
146         UtilityName = AML_DISASSEMBLER_NAME;
147     }
148     else
149     {
150         UtilityName = ASL_COMPILER_NAME;
151     }
152 
153     /* Compiler signon with copyright */
154 
155     FlPrintFile (FileId, "%s\n", Prefix);
156     FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
157 }
158 
159 
160 /*******************************************************************************
161  *
162  * FUNCTION:    AslCompilerFileHeader
163  *
164  * PARAMETERS:  FileId      - ID of the output file
165  *
166  * RETURN:      None
167  *
168  * DESCRIPTION: Header used at the beginning of output files
169  *
170  ******************************************************************************/
171 
172 void
173 AslCompilerFileHeader (
174     UINT32                  FileId)
175 {
176     struct tm               *NewTime;
177     time_t                  Aclock;
178     char                    *Prefix = "";
179 
180 
181     /* Set line prefix depending on the destination file type */
182 
183     switch (FileId)
184     {
185     case ASL_FILE_ASM_SOURCE_OUTPUT:
186     case ASL_FILE_ASM_INCLUDE_OUTPUT:
187 
188         Prefix = "; ";
189         break;
190 
191     case ASL_FILE_HEX_OUTPUT:
192 
193         if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM)
194         {
195             Prefix = "; ";
196         }
197         else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
198                  (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
199         {
200             Prefix = " * ";
201         }
202         break;
203 
204     case ASL_FILE_C_SOURCE_OUTPUT:
205     case ASL_FILE_C_OFFSET_OUTPUT:
206     case ASL_FILE_C_INCLUDE_OUTPUT:
207 
208         Prefix = " * ";
209         break;
210 
211     default:
212 
213         /* No other output types supported */
214 
215         break;
216     }
217 
218     /* Compilation header with timestamp */
219 
220     (void) time (&Aclock);
221     NewTime = localtime (&Aclock);
222 
223     FlPrintFile (FileId,
224         "%sCompilation of \"%s\" - %s%s\n",
225         Prefix, Gbl_Files[ASL_FILE_INPUT].Filename, asctime (NewTime),
226         Prefix);
227 
228     switch (FileId)
229     {
230     case ASL_FILE_C_SOURCE_OUTPUT:
231     case ASL_FILE_C_OFFSET_OUTPUT:
232     case ASL_FILE_C_INCLUDE_OUTPUT:
233 
234         FlPrintFile (FileId, " */\n");
235         break;
236 
237     default:
238 
239         /* Nothing to do for other output types */
240 
241         break;
242     }
243 }
244 
245 
246 /*******************************************************************************
247  *
248  * FUNCTION:    CmFlushSourceCode
249  *
250  * PARAMETERS:  None
251  *
252  * RETURN:      None
253  *
254  * DESCRIPTION: Read in any remaining source code after the parse tree
255  *              has been constructed.
256  *
257  ******************************************************************************/
258 
259 static void
260 CmFlushSourceCode (
261     void)
262 {
263     char                    Buffer;
264 
265 
266     while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
267     {
268         AslInsertLineBuffer ((int) Buffer);
269     }
270 
271     AslResetCurrentLineBuffer ();
272 }
273 
274 
275 /*******************************************************************************
276  *
277  * FUNCTION:    FlConsume*
278  *
279  * PARAMETERS:  Handle              - Open input file
280  *              Status              - File current status struct
281  *
282  * RETURN:      Number of lines consumed
283  *
284  * DESCRIPTION: Step over both types of comment during check for ascii chars
285  *
286  ******************************************************************************/
287 
288 static void
289 FlConsumeAnsiComment (
290     FILE                    *Handle,
291     ASL_FILE_STATUS         *Status)
292 {
293     UINT8                   Byte;
294     BOOLEAN                 ClosingComment = FALSE;
295 
296 
297     while (fread (&Byte, 1, 1, Handle) == 1)
298     {
299         /* Scan until comment close is found */
300 
301         if (ClosingComment)
302         {
303             if (Byte == '/')
304             {
305                 return;
306             }
307 
308             if (Byte != '*')
309             {
310                 /* Reset */
311 
312                 ClosingComment = FALSE;
313             }
314         }
315         else if (Byte == '*')
316         {
317             ClosingComment = TRUE;
318         }
319 
320         /* Maintain line count */
321 
322         if (Byte == 0x0A)
323         {
324             Status->Line++;
325         }
326 
327         Status->Offset++;
328     }
329 }
330 
331 
332 static void
333 FlConsumeNewComment (
334     FILE                    *Handle,
335     ASL_FILE_STATUS         *Status)
336 {
337     UINT8                   Byte;
338 
339 
340     while (fread (&Byte, 1, 1, Handle) == 1)
341     {
342         Status->Offset++;
343 
344         /* Comment ends at newline */
345 
346         if (Byte == 0x0A)
347         {
348             Status->Line++;
349             return;
350         }
351     }
352 }
353 
354 
355 /*******************************************************************************
356  *
357  * FUNCTION:    FlCheckForAcpiTable
358  *
359  * PARAMETERS:  Handle              - Open input file
360  *
361  * RETURN:      Status
362  *
363  * DESCRIPTION: Determine if a file seems to be a binary ACPI table, via the
364  *              following checks on what would be the table header:
365  *              0) File must be at least as long as an ACPI_TABLE_HEADER
366  *              1) The header length field must match the file size
367  *              2) Signature, OemId, OemTableId, AslCompilerId must be ASCII
368  *
369  ******************************************************************************/
370 
371 ACPI_STATUS
372 FlCheckForAcpiTable (
373     FILE                    *Handle)
374 {
375     ACPI_TABLE_HEADER       Table;
376     UINT32                  FileSize;
377     size_t                  Actual;
378     UINT32                  i;
379 
380 
381     /* Read a potential table header */
382 
383     Actual = fread (&Table, 1, sizeof (ACPI_TABLE_HEADER), Handle);
384     fseek (Handle, 0, SEEK_SET);
385 
386     if (Actual < sizeof (ACPI_TABLE_HEADER))
387     {
388         return (AE_ERROR);
389     }
390 
391     /* Header length field must match the file size */
392 
393     FileSize = DtGetFileSize (Handle);
394     if (Table.Length != FileSize)
395     {
396         return (AE_ERROR);
397     }
398 
399     /*
400      * These fields must be ASCII:
401      * Signature, OemId, OemTableId, AslCompilerId.
402      * We allow a NULL terminator in OemId and OemTableId.
403      */
404     for (i = 0; i < ACPI_NAME_SIZE; i++)
405     {
406         if (!ACPI_IS_ASCII ((UINT8) Table.Signature[i]))
407         {
408             return (AE_ERROR);
409         }
410 
411         if (!ACPI_IS_ASCII ((UINT8) Table.AslCompilerId[i]))
412         {
413             return (AE_ERROR);
414         }
415     }
416 
417     for (i = 0; (i < ACPI_OEM_ID_SIZE) && (Table.OemId[i]); i++)
418     {
419         if (!ACPI_IS_ASCII ((UINT8) Table.OemId[i]))
420         {
421             return (AE_ERROR);
422         }
423     }
424 
425     for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (Table.OemTableId[i]); i++)
426     {
427         if (!ACPI_IS_ASCII ((UINT8) Table.OemTableId[i]))
428         {
429             return (AE_ERROR);
430         }
431     }
432 
433     printf ("Binary file appears to be a valid ACPI table, disassembling\n");
434     return (AE_OK);
435 }
436 
437 
438 /*******************************************************************************
439  *
440  * FUNCTION:    FlCheckForAscii
441  *
442  * PARAMETERS:  Handle              - Open input file
443  *              Filename            - Input filename
444  *              DisplayErrors       - TRUE if error messages desired
445  *
446  * RETURN:      Status
447  *
448  * DESCRIPTION: Verify that the input file is entirely ASCII. Ignores characters
449  *              within comments. Note: does not handle nested comments and does
450  *              not handle comment delimiters within string literals. However,
451  *              on the rare chance this happens and an invalid character is
452  *              missed, the parser will catch the error by failing in some
453  *              spectactular manner.
454  *
455  ******************************************************************************/
456 
457 ACPI_STATUS
458 FlCheckForAscii (
459     FILE                    *Handle,
460     char                    *Filename,
461     BOOLEAN                 DisplayErrors)
462 {
463     UINT8                   Byte;
464     ACPI_SIZE               BadBytes = 0;
465     BOOLEAN                 OpeningComment = FALSE;
466     ASL_FILE_STATUS         Status;
467 
468 
469     Status.Line = 1;
470     Status.Offset = 0;
471 
472     /* Read the entire file */
473 
474     while (fread (&Byte, 1, 1, Handle) == 1)
475     {
476         /* Ignore comment fields (allow non-ascii within) */
477 
478         if (OpeningComment)
479         {
480             /* Check for second comment open delimiter */
481 
482             if (Byte == '*')
483             {
484                 FlConsumeAnsiComment (Handle, &Status);
485             }
486 
487             if (Byte == '/')
488             {
489                 FlConsumeNewComment (Handle, &Status);
490             }
491 
492             /* Reset */
493 
494             OpeningComment = FALSE;
495         }
496         else if (Byte == '/')
497         {
498             OpeningComment = TRUE;
499         }
500 
501         /* Check for an ASCII character */
502 
503         if (!ACPI_IS_ASCII (Byte))
504         {
505             if ((BadBytes < 10) && (DisplayErrors))
506             {
507                 AcpiOsPrintf (
508                     "Non-ASCII character [0x%2.2X] found in line %u, file offset 0x%.2X\n",
509                     Byte, Status.Line, Status.Offset);
510             }
511 
512             BadBytes++;
513         }
514 
515         /* Update line counter */
516 
517         else if (Byte == 0x0A)
518         {
519             Status.Line++;
520         }
521 
522         Status.Offset++;
523     }
524 
525     /* Seek back to the beginning of the source file */
526 
527     fseek (Handle, 0, SEEK_SET);
528 
529     /* Were there any non-ASCII characters in the file? */
530 
531     if (BadBytes)
532     {
533         if (DisplayErrors)
534         {
535             AcpiOsPrintf (
536                 "%u non-ASCII characters found in input source text, could be a binary file\n",
537                 BadBytes);
538             AslError (ASL_ERROR, ASL_MSG_NON_ASCII, NULL, Filename);
539         }
540 
541         return (AE_BAD_CHARACTER);
542     }
543 
544     /* File is OK (100% ASCII) */
545 
546     return (AE_OK);
547 }
548 
549 
550 /*******************************************************************************
551  *
552  * FUNCTION:    CmDoCompile
553  *
554  * PARAMETERS:  None
555  *
556  * RETURN:      Status (0 = OK)
557  *
558  * DESCRIPTION: This procedure performs the entire compile
559  *
560  ******************************************************************************/
561 
562 int
563 CmDoCompile (
564     void)
565 {
566     ACPI_STATUS             Status;
567     UINT8                   FullCompile;
568     UINT8                   Event;
569 
570 
571     FullCompile = UtBeginEvent ("*** Total Compile time ***");
572     Event = UtBeginEvent ("Open input and output files");
573     UtEndEvent (Event);
574 
575     Event = UtBeginEvent ("Preprocess input file");
576     if (Gbl_PreprocessFlag)
577     {
578         /* Preprocessor */
579 
580         PrDoPreprocess ();
581         if (Gbl_PreprocessOnly)
582         {
583             UtEndEvent (Event);
584             CmCleanupAndExit ();
585             return (0);
586         }
587     }
588     UtEndEvent (Event);
589 
590     /* Build the parse tree */
591 
592     Event = UtBeginEvent ("Parse source code and build parse tree");
593     AslCompilerparse();
594     UtEndEvent (Event);
595 
596     /* Check for parse errors */
597 
598     Status = AslCheckForErrorExit ();
599     if (ACPI_FAILURE (Status))
600     {
601         fprintf (stderr, "Compiler aborting due to parser-detected syntax error(s)\n");
602         LsDumpParseTree ();
603         goto ErrorExit;
604     }
605 
606     /* Did the parse tree get successfully constructed? */
607 
608     if (!RootNode)
609     {
610         /*
611          * If there are no errors, then we have some sort of
612          * internal problem.
613          */
614         AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
615             NULL, "- Could not resolve parse tree root node");
616 
617         goto ErrorExit;
618     }
619 
620 
621     /* Flush out any remaining source after parse tree is complete */
622 
623     Event = UtBeginEvent ("Flush source input");
624     CmFlushSourceCode ();
625 
626     /* Optional parse tree dump, compiler debug output only */
627 
628     LsDumpParseTree ();
629 
630     OpcGetIntegerWidth (RootNode);
631     UtEndEvent (Event);
632 
633     /* Pre-process parse tree for any operator transforms */
634 
635     Event = UtBeginEvent ("Parse tree transforms");
636     DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
637     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
638         TrAmlTransformWalk, NULL, NULL);
639     UtEndEvent (Event);
640 
641     /* Generate AML opcodes corresponding to the parse tokens */
642 
643     Event = UtBeginEvent ("Generate AML opcodes");
644     DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n");
645     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
646         OpcAmlOpcodeWalk, NULL);
647     UtEndEvent (Event);
648 
649     /*
650      * Now that the input is parsed, we can open the AML output file.
651      * Note: by default, the name of this file comes from the table descriptor
652      * within the input file.
653      */
654     Event = UtBeginEvent ("Open AML output file");
655     Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix);
656     UtEndEvent (Event);
657     if (ACPI_FAILURE (Status))
658     {
659         AePrintErrorLog (ASL_FILE_STDERR);
660         return (-1);
661     }
662 
663     /* Interpret and generate all compile-time constants */
664 
665     Event = UtBeginEvent ("Constant folding via AML interpreter");
666     DbgPrint (ASL_DEBUG_OUTPUT,
667         "\nInterpreting compile-time constant expressions\n\n");
668     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
669         OpcAmlConstantWalk, NULL, NULL);
670     UtEndEvent (Event);
671 
672     /* Update AML opcodes if necessary, after constant folding */
673 
674     Event = UtBeginEvent ("Updating AML opcodes after constant folding");
675     DbgPrint (ASL_DEBUG_OUTPUT,
676         "\nUpdating AML opcodes after constant folding\n\n");
677     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
678         NULL, OpcAmlOpcodeUpdateWalk, NULL);
679     UtEndEvent (Event);
680 
681     /* Calculate all AML package lengths */
682 
683     Event = UtBeginEvent ("Generate AML package lengths");
684     DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
685     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
686         LnPackageLengthWalk, NULL);
687     UtEndEvent (Event);
688 
689     if (Gbl_ParseOnlyFlag)
690     {
691         AePrintErrorLog (ASL_FILE_STDERR);
692         UtDisplaySummary (ASL_FILE_STDERR);
693         if (Gbl_DebugFlag)
694         {
695             /* Print error summary to the stdout also */
696 
697             AePrintErrorLog (ASL_FILE_STDOUT);
698             UtDisplaySummary (ASL_FILE_STDOUT);
699         }
700         UtEndEvent (FullCompile);
701         return (0);
702     }
703 
704     /*
705      * Create an internal namespace and use it as a symbol table
706      */
707 
708     /* Namespace loading */
709 
710     Event = UtBeginEvent ("Create ACPI Namespace");
711     Status = LdLoadNamespace (RootNode);
712     UtEndEvent (Event);
713     if (ACPI_FAILURE (Status))
714     {
715         goto ErrorExit;
716     }
717 
718     /* Namespace cross-reference */
719 
720     AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace");
721     Status = XfCrossReferenceNamespace ();
722     if (ACPI_FAILURE (Status))
723     {
724         goto ErrorExit;
725     }
726 
727     /* Namespace - Check for non-referenced objects */
728 
729     LkFindUnreferencedObjects ();
730     UtEndEvent (AslGbl_NamespaceEvent);
731 
732     /*
733      * Semantic analysis. This can happen only after the
734      * namespace has been loaded and cross-referenced.
735      *
736      * part one - check control methods
737      */
738     Event = UtBeginEvent ("Analyze control method return types");
739     AnalysisWalkInfo.MethodStack = NULL;
740 
741     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n");
742     TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE,
743         MtMethodAnalysisWalkBegin,
744         MtMethodAnalysisWalkEnd, &AnalysisWalkInfo);
745     UtEndEvent (Event);
746 
747     /* Semantic error checking part two - typing of method returns */
748 
749     Event = UtBeginEvent ("Determine object types returned by methods");
750     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n");
751     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
752         NULL, AnMethodTypingWalkEnd, NULL);
753     UtEndEvent (Event);
754 
755     /* Semantic error checking part three - operand type checking */
756 
757     Event = UtBeginEvent ("Analyze AML operand types");
758     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n");
759     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
760         NULL, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo);
761     UtEndEvent (Event);
762 
763     /* Semantic error checking part four - other miscellaneous checks */
764 
765     Event = UtBeginEvent ("Miscellaneous analysis");
766     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n");
767     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
768         AnOtherSemanticAnalysisWalkBegin,
769         NULL, &AnalysisWalkInfo);
770     UtEndEvent (Event);
771 
772     /* Calculate all AML package lengths */
773 
774     Event = UtBeginEvent ("Finish AML package length generation");
775     DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
776     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
777         LnInitLengthsWalk, NULL);
778     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
779         LnPackageLengthWalk, NULL);
780     UtEndEvent (Event);
781 
782     /* Code generation - emit the AML */
783 
784     Event = UtBeginEvent ("Generate AML code and write output files");
785     CgGenerateAmlOutput ();
786     UtEndEvent (Event);
787 
788     Event = UtBeginEvent ("Write optional output files");
789     CmDoOutputFiles ();
790     UtEndEvent (Event);
791 
792     UtEndEvent (FullCompile);
793     CmCleanupAndExit ();
794     return (0);
795 
796 ErrorExit:
797     UtEndEvent (FullCompile);
798     CmCleanupAndExit ();
799     return (-1);
800 }
801 
802 
803 /*******************************************************************************
804  *
805  * FUNCTION:    CmDoOutputFiles
806  *
807  * PARAMETERS:  None
808  *
809  * RETURN:      None.
810  *
811  * DESCRIPTION: Create all "listing" type files
812  *
813  ******************************************************************************/
814 
815 void
816 CmDoOutputFiles (
817     void)
818 {
819 
820     /* Create listings and hex files */
821 
822     LsDoListings ();
823     HxDoHexOutput ();
824 
825     /* Dump the namespace to the .nsp file if requested */
826 
827     (void) NsDisplayNamespace ();
828 }
829 
830 
831 /*******************************************************************************
832  *
833  * FUNCTION:    CmDumpAllEvents
834  *
835  * PARAMETERS:  None
836  *
837  * RETURN:      None.
838  *
839  * DESCRIPTION: Dump all compiler events
840  *
841  ******************************************************************************/
842 
843 static void
844 CmDumpAllEvents (
845     void)
846 {
847     ASL_EVENT_INFO          *Event;
848     UINT32                  Delta;
849     UINT32                  USec;
850     UINT32                  MSec;
851     UINT32                  i;
852 
853 
854     Event = AslGbl_Events;
855 
856     DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
857     if (Gbl_CompileTimesFlag)
858     {
859         printf ("\nElapsed time for major events\n\n");
860     }
861 
862     for (i = 0; i < AslGbl_NextEvent; i++)
863     {
864         if (Event->Valid)
865         {
866             /* Delta will be in 100-nanosecond units */
867 
868             Delta = (UINT32) (Event->EndTime - Event->StartTime);
869 
870             USec = Delta / ACPI_100NSEC_PER_USEC;
871             MSec = Delta / ACPI_100NSEC_PER_MSEC;
872 
873             /* Round milliseconds up */
874 
875             if ((USec - (MSec * ACPI_USEC_PER_MSEC)) >= 500)
876             {
877                 MSec++;
878             }
879 
880             DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
881                 USec, MSec, Event->EventName);
882 
883             if (Gbl_CompileTimesFlag)
884             {
885                 printf ("%8u usec %8u msec - %s\n",
886                     USec, MSec, Event->EventName);
887             }
888         }
889 
890         Event++;
891     }
892 }
893 
894 
895 /*******************************************************************************
896  *
897  * FUNCTION:    CmCleanupAndExit
898  *
899  * PARAMETERS:  None
900  *
901  * RETURN:      None.
902  *
903  * DESCRIPTION: Close all open files and exit the compiler
904  *
905  ******************************************************************************/
906 
907 void
908 CmCleanupAndExit (
909     void)
910 {
911     UINT32                  i;
912     BOOLEAN                 DeleteAmlFile = FALSE;
913 
914 
915     AePrintErrorLog (ASL_FILE_STDERR);
916     if (Gbl_DebugFlag)
917     {
918         /* Print error summary to stdout also */
919 
920         AePrintErrorLog (ASL_FILE_STDOUT);
921     }
922 
923     /* Emit compile times if enabled */
924 
925     CmDumpAllEvents ();
926 
927     if (Gbl_CompileTimesFlag)
928     {
929         printf ("\nMiscellaneous compile statistics\n\n");
930         printf ("%11u : %s\n", TotalParseNodes, "Parse nodes");
931         printf ("%11u : %s\n", Gbl_NsLookupCount, "Namespace searches");
932         printf ("%11u : %s\n", TotalNamedObjects, "Named objects");
933         printf ("%11u : %s\n", TotalMethods, "Control methods");
934         printf ("%11u : %s\n", TotalAllocations, "Memory Allocations");
935         printf ("%11u : %s\n", TotalAllocated, "Total allocated memory");
936         printf ("%11u : %s\n", TotalFolds, "Constant subtrees folded");
937         printf ("\n");
938     }
939 
940     if (Gbl_NsLookupCount)
941     {
942         DbgPrint (ASL_DEBUG_OUTPUT,
943             "\n\nMiscellaneous compile statistics\n\n");
944 
945         DbgPrint (ASL_DEBUG_OUTPUT,
946             "%32s : %u\n", "Total Namespace searches",
947             Gbl_NsLookupCount);
948 
949         DbgPrint (ASL_DEBUG_OUTPUT,
950             "%32s : %u usec\n", "Time per search", ((UINT32)
951             (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
952                 AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
953                 Gbl_NsLookupCount);
954     }
955 
956     if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
957     {
958         printf ("\nMaximum error count (%u) exceeded\n",
959             ASL_MAX_ERROR_COUNT);
960     }
961 
962     UtDisplaySummary (ASL_FILE_STDOUT);
963 
964     /*
965      * We will delete the AML file if there are errors and the
966      * force AML output option has not been used.
967      */
968     if ((Gbl_ExceptionCount[ASL_ERROR] > 0) && (!Gbl_IgnoreErrors) &&
969         Gbl_Files[ASL_FILE_AML_OUTPUT].Handle)
970     {
971         DeleteAmlFile = TRUE;
972     }
973 
974     /* Close all open files */
975 
976     /*
977      * Take care with the preprocessor file (.i), it might be the same
978      * as the "input" file, depending on where the compiler has terminated
979      * or aborted. Prevent attempt to close the same file twice in
980      * loop below.
981      */
982     if (Gbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
983         Gbl_Files[ASL_FILE_INPUT].Handle)
984     {
985         Gbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
986     }
987 
988     /* Close the standard I/O files */
989 
990     for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
991     {
992         FlCloseFile (i);
993     }
994 
995     /* Delete AML file if there are errors */
996 
997     if (DeleteAmlFile)
998     {
999         FlDeleteFile (ASL_FILE_AML_OUTPUT);
1000     }
1001 
1002     /* Delete the preprocessor output file (.i) unless -li flag is set */
1003 
1004     if (!Gbl_PreprocessorOutputFlag &&
1005         Gbl_PreprocessFlag)
1006     {
1007         FlDeleteFile (ASL_FILE_PREPROCESSOR);
1008     }
1009 
1010     /*
1011      * Delete intermediate ("combined") source file (if -ls flag not set)
1012      * This file is created during normal ASL/AML compiles. It is not
1013      * created by the data table compiler.
1014      *
1015      * If the -ls flag is set, then the .SRC file should not be deleted.
1016      * In this case, Gbl_SourceOutputFlag is set to TRUE.
1017      *
1018      * Note: Handles are cleared by FlCloseFile above, so we look at the
1019      * filename instead, to determine if the .SRC file was actually
1020      * created.
1021      *
1022      * TBD: SourceOutput should be .TMP, then rename if we want to keep it?
1023      */
1024     if (!Gbl_SourceOutputFlag)
1025     {
1026         FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
1027     }
1028 }
1029