Home | History | Annotate | Line # | Download | only in compiler
aslparseop.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: aslparseop - Parse op create/allocate/cache interfaces
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 "aslcompiler.y.h"
     46 #include "acapps.h"
     47 #include "acconvert.h"
     48 
     49 #define _COMPONENT          ACPI_COMPILER
     50         ACPI_MODULE_NAME    ("aslparseop")
     51 
     52 
     53 /* Local prototypes */
     54 
     55 static ACPI_PARSE_OBJECT *
     56 TrGetOpFromCache (
     57     void);
     58 
     59 
     60 /*******************************************************************************
     61  *
     62  * FUNCTION:    TrCreateOp
     63  *
     64  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the op
     65  *              NumChildren         - Number of children to follow
     66  *              ...                 - A list of child ops to link to the new
     67  *                                    op. NumChildren long.
     68  *
     69  * RETURN:      Pointer to the new op. Aborts on allocation failure
     70  *
     71  * DESCRIPTION: Create a new parse op and link together a list of child
     72  *              ops underneath the new op.
     73  *
     74  ******************************************************************************/
     75 
     76 ACPI_PARSE_OBJECT *
     77 TrCreateOp (
     78     UINT32                  ParseOpcode,
     79     UINT32                  NumChildren,
     80     ...)
     81 {
     82     ACPI_PARSE_OBJECT       *Op;
     83     ACPI_PARSE_OBJECT       *Child;
     84     ACPI_PARSE_OBJECT       *PrevChild;
     85     va_list                 ap;
     86     UINT32                  i;
     87     BOOLEAN                 FirstChild;
     88 
     89 
     90     va_start (ap, NumChildren);
     91 
     92     /* Allocate one new op */
     93 
     94     Op = TrAllocateOp (ParseOpcode);
     95 
     96     DbgPrint (ASL_PARSE_OUTPUT,
     97         "\nCreateOp  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
     98         Op->Asl.LineNumber, Op->Asl.Column, Op,
     99         NumChildren, UtGetOpName(ParseOpcode));
    100 
    101     /* Some extra debug output based on the parse opcode */
    102 
    103     switch (ParseOpcode)
    104     {
    105     case PARSEOP_ASL_CODE:
    106 
    107         Gbl_ParseTreeRoot = Op;
    108         Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    109         DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
    110         break;
    111 
    112     case PARSEOP_DEFINITION_BLOCK:
    113 
    114         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
    115         break;
    116 
    117     case PARSEOP_OPERATIONREGION:
    118 
    119         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
    120         break;
    121 
    122     case PARSEOP_OR:
    123 
    124         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
    125         break;
    126 
    127     default:
    128 
    129         /* Nothing to do for other opcodes */
    130 
    131         break;
    132     }
    133 
    134     /* Link the new op to its children */
    135 
    136     PrevChild = NULL;
    137     FirstChild = TRUE;
    138     for (i = 0; i < NumChildren; i++)
    139     {
    140         /* Get the next child */
    141 
    142         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
    143         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
    144 
    145         /*
    146          * If child is NULL, this means that an optional argument
    147          * was omitted. We must create a placeholder with a special
    148          * opcode (DEFAULT_ARG) so that the code generator will know
    149          * that it must emit the correct default for this argument
    150          */
    151         if (!Child)
    152         {
    153             Child = TrAllocateOp (PARSEOP_DEFAULT_ARG);
    154         }
    155 
    156         /* Link first child to parent */
    157 
    158         if (FirstChild)
    159         {
    160             FirstChild = FALSE;
    161             Op->Asl.Child = Child;
    162 
    163             /*
    164              * For the ASL-/ASL+ converter: if the ParseOp is a Connection,
    165              * External, Offset or AccessAs, it means that the comments in the
    166              * FirstChild belongs to their parent due to the parsing order in
    167              * the .y files. To correct this, take the comments in the
    168              * FirstChild place it in the parent. This also means that
    169              * legitimate comments for the child gets put to the parent.
    170              */
    171             if (Gbl_CaptureComments &&
    172                 ((ParseOpcode == PARSEOP_CONNECTION) ||
    173                  (ParseOpcode == PARSEOP_EXTERNAL) ||
    174                  (ParseOpcode == PARSEOP_OFFSET) ||
    175                  (ParseOpcode == PARSEOP_ACCESSAS)))
    176             {
    177                 Op->Asl.CommentList      = Child->Asl.CommentList;
    178                 Op->Asl.EndBlkComment    = Child->Asl.EndBlkComment;
    179                 Op->Asl.InlineComment    = Child->Asl.InlineComment;
    180                 Op->Asl.FileChanged      = Child->Asl.FileChanged;
    181 
    182                 Child->Asl.CommentList   = NULL;
    183                 Child->Asl.EndBlkComment = NULL;
    184                 Child->Asl.InlineComment = NULL;
    185                 Child->Asl.FileChanged   = FALSE;
    186 
    187                 /*
    188                  * These do not need to be "passed off". They can be copied
    189                  * because the code for these opcodes should be printed in the
    190                  * same file.
    191                  */
    192                 Op->Asl.Filename         = Child->Asl.Filename;
    193                 Op->Asl.ParentFilename   = Child->Asl.ParentFilename;
    194             }
    195         }
    196 
    197         /* Point all children to parent */
    198 
    199         Child->Asl.Parent = Op;
    200 
    201         /* Link children in a peer list */
    202 
    203         if (PrevChild)
    204         {
    205             PrevChild->Asl.Next = Child;
    206         };
    207 
    208         /* Get the comment from last child in the resource template call */
    209 
    210         if (Gbl_CaptureComments &&
    211             (Op->Asl.ParseOpcode == PARSEOP_RESOURCETEMPLATE))
    212         {
    213             CvDbgPrint ("Transferred current comment list to this op.\n");
    214             Op->Asl.CommentList = Child->Asl.CommentList;
    215             Child->Asl.CommentList = NULL;
    216 
    217             Op->Asl.InlineComment = Child->Asl.InlineComment;
    218             Child->Asl.InlineComment = NULL;
    219         }
    220 
    221         /*
    222          * This child might be a list, point all ops in the list
    223          * to the same parent
    224          */
    225         while (Child->Asl.Next)
    226         {
    227             Child = Child->Asl.Next;
    228             Child->Asl.Parent = Op;
    229         }
    230 
    231         PrevChild = Child;
    232     }
    233 
    234     va_end(ap);
    235     DbgPrint (ASL_PARSE_OUTPUT, "\n");
    236     return (Op);
    237 }
    238 
    239 
    240 /*******************************************************************************
    241  *
    242  * FUNCTION:    TrCreateLeafOp
    243  *
    244  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the op
    245  *
    246  * RETURN:      Pointer to the new op. Aborts on allocation failure
    247  *
    248  * DESCRIPTION: Create a simple leaf op (no children or peers, and no value
    249  *              assigned to the op)
    250  *
    251  ******************************************************************************/
    252 
    253 ACPI_PARSE_OBJECT *
    254 TrCreateLeafOp (
    255     UINT32                  ParseOpcode)
    256 {
    257     ACPI_PARSE_OBJECT       *Op;
    258 
    259 
    260     Op = TrAllocateOp (ParseOpcode);
    261 
    262     DbgPrint (ASL_PARSE_OUTPUT,
    263         "\nCreateLeafOp  Ln/Col %u/%u NewOp %p  Op %s\n\n",
    264         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
    265 
    266     return (Op);
    267 }
    268 
    269 
    270 /*******************************************************************************
    271  *
    272  * FUNCTION:    TrCreateValuedLeafOp
    273  *
    274  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the op
    275  *              Value               - Value to be assigned to the op
    276  *
    277  * RETURN:      Pointer to the new op. Aborts on allocation failure
    278  *
    279  * DESCRIPTION: Create a leaf op (no children or peers) with a value
    280  *              assigned to it
    281  *
    282  ******************************************************************************/
    283 
    284 ACPI_PARSE_OBJECT *
    285 TrCreateValuedLeafOp (
    286     UINT32                  ParseOpcode,
    287     UINT64                  Value)
    288 {
    289     ACPI_PARSE_OBJECT       *Op;
    290 
    291 
    292     Op = TrAllocateOp (ParseOpcode);
    293     Op->Asl.Value.Integer = Value;
    294 
    295     DbgPrint (ASL_PARSE_OUTPUT,
    296         "\nCreateValuedLeafOp  Ln/Col %u/%u NewOp %p  "
    297         "Op %s  Value %8.8X%8.8X  ",
    298         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
    299         ACPI_FORMAT_UINT64 (Value));
    300 
    301     switch (ParseOpcode)
    302     {
    303     case PARSEOP_STRING_LITERAL:
    304 
    305         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
    306         break;
    307 
    308     case PARSEOP_NAMESEG:
    309 
    310         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
    311         break;
    312 
    313     case PARSEOP_NAMESTRING:
    314 
    315         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
    316         break;
    317 
    318     case PARSEOP_EISAID:
    319 
    320         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
    321         break;
    322 
    323     case PARSEOP_METHOD:
    324 
    325         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
    326         break;
    327 
    328     case PARSEOP_INTEGER:
    329 
    330         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
    331             ACPI_FORMAT_UINT64 (Value));
    332         break;
    333 
    334     default:
    335         break;
    336     }
    337 
    338     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    339     return (Op);
    340 }
    341 
    342 
    343 /*******************************************************************************
    344  *
    345  * FUNCTION:    TrCreateTargetOp
    346  *
    347  * PARAMETERS:  OriginalOp          - Op to be copied
    348  *
    349  * RETURN:      Pointer to the new op. Aborts on allocation failure
    350  *
    351  * DESCRIPTION: Copy an existing op (and subtree). Used in ASL+ (C-style)
    352  *              expressions where the target is the same as one of the
    353  *              operands. A new op and subtree must be created from the
    354  *              original so that the parse tree can be linked properly.
    355  *
    356  * NOTE:        This code is specific to target operands that are the last
    357  *              operand in an ASL/AML operator. Meaning that the top-level
    358  *              parse Op in a possible subtree has a NULL Next pointer.
    359  *              This simplifies the recursion.
    360  *
    361  *              Subtree example:
    362  *                  DeRefOf (Local1) += 32
    363  *
    364  *              This gets converted to:
    365  *                  Add (DeRefOf (Local1), 32, DeRefOf (Local1))
    366  *
    367  *              Each DeRefOf has a single child, Local1. Even more complex
    368  *              subtrees can be created via the Index and DeRefOf operators.
    369  *
    370  ******************************************************************************/
    371 
    372 ACPI_PARSE_OBJECT *
    373 TrCreateTargetOp (
    374     ACPI_PARSE_OBJECT       *OriginalOp,
    375     ACPI_PARSE_OBJECT       *ParentOp)
    376 {
    377     ACPI_PARSE_OBJECT       *Op;
    378 
    379 
    380     if (!OriginalOp)
    381     {
    382         return (NULL);
    383     }
    384 
    385     Op = TrGetOpFromCache ();
    386 
    387     /* Copy the pertinent values (omit link pointer fields) */
    388 
    389     Op->Asl.Value               = OriginalOp->Asl.Value;
    390     Op->Asl.Filename            = OriginalOp->Asl.Filename;
    391     Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
    392     Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
    393     Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
    394     Op->Asl.Column              = OriginalOp->Asl.Column;
    395     Op->Asl.Flags               = OriginalOp->Asl.Flags;
    396     Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
    397     Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
    398     Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
    399     Op->Asl.Parent              = ParentOp;
    400 
    401     UtSetParseOpName (Op);
    402 
    403     /* Copy a possible subtree below this op */
    404 
    405     if (OriginalOp->Asl.Child)
    406     {
    407         Op->Asl.Child = TrCreateTargetOp (OriginalOp->Asl.Child, Op);
    408     }
    409 
    410     if (OriginalOp->Asl.Next) /* Null for top-level op */
    411     {
    412         Op->Asl.Next = TrCreateTargetOp (OriginalOp->Asl.Next, ParentOp);
    413     }
    414 
    415     return (Op);
    416 }
    417 
    418 
    419 /*******************************************************************************
    420  *
    421  * FUNCTION:    TrCreateAssignmentOp
    422  *
    423  * PARAMETERS:  Target              - Assignment target
    424  *              Source              - Assignment source
    425  *
    426  * RETURN:      Pointer to the new op. Aborts on allocation failure
    427  *
    428  * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
    429  *              tree if possible to utilize the last argument of the math
    430  *              operators which is a target operand -- thus saving invocation
    431  *              of and additional Store() operator. An optimization.
    432  *
    433  ******************************************************************************/
    434 
    435 ACPI_PARSE_OBJECT *
    436 TrCreateAssignmentOp (
    437     ACPI_PARSE_OBJECT       *Target,
    438     ACPI_PARSE_OBJECT       *Source)
    439 {
    440     ACPI_PARSE_OBJECT       *TargetOp;
    441     ACPI_PARSE_OBJECT       *SourceOp1;
    442     ACPI_PARSE_OBJECT       *SourceOp2;
    443     ACPI_PARSE_OBJECT       *Operator;
    444 
    445 
    446     DbgPrint (ASL_PARSE_OUTPUT,
    447         "\nTrCreateAssignmentOp  Line [%u to %u] Source %s Target %s\n",
    448         Source->Asl.LineNumber, Source->Asl.EndLine,
    449         UtGetOpName (Source->Asl.ParseOpcode),
    450         UtGetOpName (Target->Asl.ParseOpcode));
    451 
    452     TrSetOpFlags (Target, OP_IS_TARGET);
    453 
    454     switch (Source->Asl.ParseOpcode)
    455     {
    456     /*
    457      * Only these operators can be optimized because they have
    458      * a target operand
    459      */
    460     case PARSEOP_ADD:
    461     case PARSEOP_AND:
    462     case PARSEOP_DIVIDE:
    463     case PARSEOP_INDEX:
    464     case PARSEOP_MOD:
    465     case PARSEOP_MULTIPLY:
    466     case PARSEOP_NOT:
    467     case PARSEOP_OR:
    468     case PARSEOP_SHIFTLEFT:
    469     case PARSEOP_SHIFTRIGHT:
    470     case PARSEOP_SUBTRACT:
    471     case PARSEOP_XOR:
    472 
    473         break;
    474 
    475     /* Otherwise, just create a normal Store operator */
    476 
    477     default:
    478         goto CannotOptimize;
    479     }
    480 
    481     /*
    482      * Transform the parse tree such that the target is moved to the
    483      * last operand of the operator
    484      */
    485     SourceOp1 = Source->Asl.Child;
    486     SourceOp2 = SourceOp1->Asl.Next;
    487 
    488     /* NOT only has one operand, but has a target */
    489 
    490     if (Source->Asl.ParseOpcode == PARSEOP_NOT)
    491     {
    492         SourceOp2 = SourceOp1;
    493     }
    494 
    495     /* DIVIDE has an extra target operand (remainder) */
    496 
    497     if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
    498     {
    499         SourceOp2 = SourceOp2->Asl.Next;
    500     }
    501 
    502     TargetOp = SourceOp2->Asl.Next;
    503 
    504     /*
    505      * Can't perform this optimization if there already is a target
    506      * for the operator (ZERO is a "no target" placeholder).
    507      */
    508     if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
    509     {
    510         goto CannotOptimize;
    511     }
    512 
    513     /* Link in the target as the final operand */
    514 
    515     SourceOp2->Asl.Next = Target;
    516     Target->Asl.Parent = Source;
    517     return (Source);
    518 
    519 
    520 CannotOptimize:
    521 
    522     Operator = TrAllocateOp (PARSEOP_STORE);
    523     TrLinkOpChildren (Operator, 2, Source, Target);
    524 
    525     /* Set the appropriate line numbers for the new op */
    526 
    527     Operator->Asl.LineNumber        = Target->Asl.LineNumber;
    528     Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
    529     Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
    530     Operator->Asl.Column            = Target->Asl.Column;
    531 
    532     return (Operator);
    533 }
    534 
    535 
    536 /*******************************************************************************
    537  *
    538  * FUNCTION:    TrCreateNullTargetOp
    539  *
    540  * PARAMETERS:  None
    541  *
    542  * RETURN:      Pointer to the new op. Aborts on allocation failure
    543  *
    544  * DESCRIPTION: Create a "null" target op. This is defined by the ACPI
    545  *              specification to be a zero AML opcode, and indicates that
    546  *              no target has been specified for the parent operation
    547  *
    548  ******************************************************************************/
    549 
    550 ACPI_PARSE_OBJECT *
    551 TrCreateNullTargetOp (
    552     void)
    553 {
    554     ACPI_PARSE_OBJECT       *Op;
    555 
    556 
    557     Op = TrAllocateOp (PARSEOP_ZERO);
    558     Op->Asl.CompileFlags |= (OP_IS_TARGET | OP_COMPILE_TIME_CONST);
    559 
    560     DbgPrint (ASL_PARSE_OUTPUT,
    561         "\nCreateNullTargetOp  Ln/Col %u/%u NewOp %p  Op %s\n",
    562         Op->Asl.LineNumber, Op->Asl.Column, Op,
    563         UtGetOpName (Op->Asl.ParseOpcode));
    564 
    565     return (Op);
    566 }
    567 
    568 
    569 /*******************************************************************************
    570  *
    571  * FUNCTION:    TrCreateConstantLeafOp
    572  *
    573  * PARAMETERS:  ParseOpcode         - The constant opcode
    574  *
    575  * RETURN:      Pointer to the new op. Aborts on allocation failure
    576  *
    577  * DESCRIPTION: Create a leaf op (no children or peers) for one of the
    578  *              special constants - __LINE__, __FILE__, and __DATE__.
    579  *
    580  * Note: The fullimplemenation of __METHOD__ cannot happen here because we
    581  * don't have a full parse tree at this time and cannot find the parent
    582  * control method. __METHOD__ must be implemented later, after the parse
    583  * tree has been fully constructed.
    584  *
    585  ******************************************************************************/
    586 
    587 ACPI_PARSE_OBJECT *
    588 TrCreateConstantLeafOp (
    589     UINT32                  ParseOpcode)
    590 {
    591     ACPI_PARSE_OBJECT       *Op = NULL;
    592     time_t                  CurrentTime;
    593     char                    *StaticTimeString;
    594     char                    *TimeString;
    595     char                    *Filename;
    596 
    597 
    598     switch (ParseOpcode)
    599     {
    600     case PARSEOP___LINE__:
    601 
    602         Op = TrAllocateOp (PARSEOP_INTEGER);
    603         Op->Asl.Value.Integer = Op->Asl.LineNumber;
    604         break;
    605 
    606     case PARSEOP___METHOD__:
    607 
    608         /* Will become a string literal later */
    609 
    610         Op = TrAllocateOp (PARSEOP___METHOD__);
    611         Op->Asl.Value.String = NULL;
    612         break;
    613 
    614     case PARSEOP___PATH__:
    615 
    616         Op = TrAllocateOp (PARSEOP_STRING_LITERAL);
    617 
    618         /* Op.Asl.Filename contains the full pathname to the file */
    619 
    620         Op->Asl.Value.String = Op->Asl.Filename;
    621         break;
    622 
    623     case PARSEOP___FILE__:
    624 
    625         Op = TrAllocateOp (PARSEOP_STRING_LITERAL);
    626 
    627         /* Get the simple filename from the full path */
    628 
    629         FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
    630         Op->Asl.Value.String = Filename;
    631         break;
    632 
    633     case PARSEOP___DATE__:
    634 
    635         Op = TrAllocateOp (PARSEOP_STRING_LITERAL);
    636 
    637         /* Get a copy of the current time */
    638 
    639         CurrentTime = time (NULL);
    640         StaticTimeString = ctime (&CurrentTime);
    641         TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
    642         strcpy (TimeString, StaticTimeString);
    643 
    644         TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
    645         Op->Asl.Value.String = TimeString;
    646         break;
    647 
    648     default: /* This would be an internal error */
    649 
    650         return (NULL);
    651     }
    652 
    653     DbgPrint (ASL_PARSE_OUTPUT,
    654         "\nCreateConstantLeafOp  Ln/Col %u/%u NewOp %p  "
    655         "Op %s  Value %8.8X%8.8X  \n",
    656         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
    657         ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
    658 
    659     return (Op);
    660 }
    661 
    662 
    663 /*******************************************************************************
    664  *
    665  * FUNCTION:    TrAllocateOp
    666  *
    667  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the op
    668  *
    669  * RETURN:      New parse op. Aborts on allocation failure
    670  *
    671  * DESCRIPTION: Allocate and initialize a new parse op for the parse tree
    672  *
    673  ******************************************************************************/
    674 
    675 ACPI_PARSE_OBJECT *
    676 TrAllocateOp (
    677     UINT32                  ParseOpcode)
    678 {
    679     ACPI_PARSE_OBJECT       *Op;
    680     ACPI_PARSE_OBJECT       *LatestOp;
    681 
    682 
    683     Op = TrGetOpFromCache ();
    684 
    685     Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
    686     Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
    687     Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
    688     Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
    689     Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
    690     Op->Asl.Column            = Gbl_CurrentColumn;
    691 
    692     UtSetParseOpName (Op);
    693 
    694     /* The following is for capturing comments */
    695 
    696     if(Gbl_CaptureComments)
    697     {
    698         LatestOp = Gbl_CommentState.LatestParseOp;
    699         Op->Asl.InlineComment     = NULL;
    700         Op->Asl.EndNodeComment    = NULL;
    701         Op->Asl.CommentList       = NULL;
    702         Op->Asl.FileChanged       = FALSE;
    703 
    704         /*
    705          * Check to see if the file name has changed before resetting the
    706          * latest parse op.
    707          */
    708         if (LatestOp &&
    709             (ParseOpcode != PARSEOP_INCLUDE) &&
    710             (ParseOpcode != PARSEOP_INCLUDE_END) &&
    711             strcmp (LatestOp->Asl.Filename, Op->Asl.Filename))
    712         {
    713             CvDbgPrint ("latest op: %s\n", LatestOp->Asl.ParseOpName);
    714             Op->Asl.FileChanged = TRUE;
    715             if (Gbl_IncludeFileStack)
    716             {
    717                 Op->Asl.ParentFilename = Gbl_IncludeFileStack->Filename;
    718             }
    719             else
    720             {
    721                 Op->Asl.ParentFilename = NULL;
    722             }
    723         }
    724 
    725         Gbl_CommentState.LatestParseOp = Op;
    726         CvDbgPrint ("TrAllocateOp=Set latest parse op to this op.\n");
    727         CvDbgPrint ("           Op->Asl.ParseOpName = %s\n",
    728             Gbl_CommentState.LatestParseOp->Asl.ParseOpName);
    729         CvDbgPrint ("           Op->Asl.ParseOpcode = 0x%x\n", ParseOpcode);
    730 
    731         if (Op->Asl.FileChanged)
    732         {
    733             CvDbgPrint("    file has been changed!\n");
    734         }
    735 
    736         /*
    737          * if this parse op's syntax uses () and {} (i.e. Package(1){0x00}) then
    738          * set a flag in the comment state. This facilitates paring comments for
    739          * these types of opcodes.
    740          */
    741         if ((CvParseOpBlockType(Op) == (BLOCK_PAREN | BLOCK_BRACE)) &&
    742             (ParseOpcode != PARSEOP_DEFINITION_BLOCK))
    743         {
    744             CvDbgPrint ("Parsing paren/Brace op now!\n");
    745             Gbl_CommentState.ParsingParenBraceNode = Op;
    746         }
    747 
    748         if (Gbl_CommentListHead)
    749         {
    750             CvDbgPrint ("Transferring...\n");
    751             Op->Asl.CommentList = Gbl_CommentListHead;
    752             Gbl_CommentListHead = NULL;
    753             Gbl_CommentListTail = NULL;
    754             CvDbgPrint ("    Transferred current comment list to this op.\n");
    755             CvDbgPrint ("    %s\n", Op->Asl.CommentList->Comment);
    756         }
    757 
    758         if (Gbl_InlineCommentBuffer)
    759         {
    760             Op->Asl.InlineComment = Gbl_InlineCommentBuffer;
    761             Gbl_InlineCommentBuffer = NULL;
    762             CvDbgPrint ("Transferred current inline comment list to this op.\n");
    763         }
    764     }
    765 
    766     return (Op);
    767 }
    768 
    769 
    770 /*******************************************************************************
    771  *
    772  * FUNCTION:    TrGetOpFromCache
    773  *
    774  * PARAMETERS:  None
    775  *
    776  * RETURN:      New parse op. Aborts on allocation failure
    777  *
    778  * DESCRIPTION: Allocate a new parse op for the parse tree. Bypass the local
    779  *              dynamic memory manager for performance reasons (This has a
    780  *              major impact on the speed of the compiler.)
    781  *
    782  ******************************************************************************/
    783 
    784 static ACPI_PARSE_OBJECT *
    785 TrGetOpFromCache (
    786     void)
    787 {
    788     ASL_CACHE_INFO          *Cache;
    789 
    790 
    791     if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
    792     {
    793         /* Allocate a new buffer */
    794 
    795         Cache = UtLocalCalloc (sizeof (Cache->Next) +
    796             (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
    797 
    798         /* Link new cache buffer to head of list */
    799 
    800         Cache->Next = Gbl_ParseOpCacheList;
    801         Gbl_ParseOpCacheList = Cache;
    802 
    803         /* Setup cache management pointers */
    804 
    805         Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
    806         Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
    807     }
    808 
    809     Gbl_ParseOpCount++;
    810     return (Gbl_ParseOpCacheNext++);
    811 }
    812 
    813 
    814 /*******************************************************************************
    815  *
    816  * FUNCTION:    TrPrintOpFlags
    817  *
    818  * PARAMETERS:  Flags               - Flags word to be decoded
    819  *              OutputLevel         - Debug output level: ASL_TREE_OUTPUT etc.
    820  *
    821  * RETURN:      None
    822  *
    823  * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
    824  *
    825  ******************************************************************************/
    826 
    827 void
    828 TrPrintOpFlags (
    829     UINT32                  Flags,
    830     UINT32                  OutputLevel)
    831 {
    832     UINT32                  FlagBit = 1;
    833     UINT32                  i;
    834 
    835 
    836     for (i = 0; i < ACPI_NUM_OP_FLAGS; i++)
    837     {
    838         if (Flags & FlagBit)
    839         {
    840             DbgPrint (OutputLevel, " %s", Gbl_OpFlagNames[i]);
    841         }
    842 
    843         FlagBit <<= 1;
    844     }
    845 }
    846