Home | History | Annotate | Line # | Download | only in compiler
aslcompile.c revision 1.22
      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
     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     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
    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
    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
    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
    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
    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