1 /******************************************************************************
   2  *
   3  * Module Name: aslcompile - top level compile module
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 "aslcompiler.h"
  45 #include "dtcompiler.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 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 }