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