aslfold.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: aslfold - Constant folding
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/include/amlcode.h>
47
48#include <contrib/dev/acpica/include/acdispat.h>
49#include <contrib/dev/acpica/include/acparser.h>
50
51#define _COMPONENT          ACPI_COMPILER
52        ACPI_MODULE_NAME    ("aslfold")
53
54/* Local prototypes */
55
56static ACPI_STATUS
57OpcAmlEvaluationWalk1 (
58    ACPI_PARSE_OBJECT       *Op,
59    UINT32                  Level,
60    void                    *Context);
61
62static ACPI_STATUS
63OpcAmlEvaluationWalk2 (
64    ACPI_PARSE_OBJECT       *Op,
65    UINT32                  Level,
66    void                    *Context);
67
68static ACPI_STATUS
69OpcAmlCheckForConstant (
70    ACPI_PARSE_OBJECT       *Op,
71    UINT32                  Level,
72    void                    *Context);
73
74static void
75OpcUpdateIntegerNode (
76    ACPI_PARSE_OBJECT       *Op,
77    UINT64                  Value);
78
79static ACPI_STATUS
80TrTransformToStoreOp (
81    ACPI_PARSE_OBJECT       *Op,
82    ACPI_WALK_STATE         *WalkState);
83
84static ACPI_STATUS
85TrSimpleConstantReduction (
86    ACPI_PARSE_OBJECT       *Op,
87    ACPI_WALK_STATE         *WalkState);
88
89static void
90TrInstallReducedConstant (
91    ACPI_PARSE_OBJECT       *Op,
92    ACPI_OPERAND_OBJECT     *ObjDesc);
93
94
95/*******************************************************************************
96 *
97 * FUNCTION:    OpcAmlConstantWalk
98 *
99 * PARAMETERS:  ASL_WALK_CALLBACK
100 *
101 * RETURN:      Status
102 *
103 * DESCRIPTION: Reduce an Op and its subtree to a constant if possible.
104 *              Called during ascent of the parse tree.
105 *
106 ******************************************************************************/
107
108ACPI_STATUS
109OpcAmlConstantWalk (
110    ACPI_PARSE_OBJECT       *Op,
111    UINT32                  Level,
112    void                    *Context)
113{
114    ACPI_WALK_STATE         *WalkState;
115    ACPI_STATUS             Status = AE_OK;
116
117
118    if (Op->Asl.CompileFlags == 0)
119    {
120        return (AE_OK);
121    }
122
123    /*
124     * Only interested in subtrees that could possibly contain
125     * expressions that can be evaluated at this time
126     */
127    if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
128          (Op->Asl.CompileFlags & NODE_IS_TARGET))
129    {
130        return (AE_OK);
131    }
132
133    /* Create a new walk state */
134
135    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
136    if (!WalkState)
137    {
138        return (AE_NO_MEMORY);
139    }
140
141    WalkState->NextOp = NULL;
142    WalkState->Params = NULL;
143
144    /*
145     * Examine the entire subtree -- all nodes must be constants
146     * or type 3/4/5 opcodes
147     */
148    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
149        OpcAmlCheckForConstant, NULL, WalkState);
150
151    /*
152     * Did we find an entire subtree that contains all constants
153     * and type 3/4/5 opcodes?
154     */
155    switch (Status)
156    {
157    case AE_OK:
158
159        /* Simple case, like Add(3,4) -> 7 */
160
161        Status = TrSimpleConstantReduction (Op, WalkState);
162        break;
163
164    case AE_CTRL_RETURN_VALUE:
165
166        /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */
167
168        Status = TrTransformToStoreOp (Op, WalkState);
169        break;
170
171    case AE_TYPE:
172
173        AcpiDsDeleteWalkState (WalkState);
174        return (AE_OK);
175
176    default:
177        AcpiDsDeleteWalkState (WalkState);
178        break;
179    }
180
181    if (ACPI_FAILURE (Status))
182    {
183        DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n",
184            AcpiFormatException (Status));
185
186        /* We could not resolve the subtree for some reason */
187
188        AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
189            (char *) AcpiFormatException (Status));
190
191        /* Set the subtree value to ZERO anyway. Eliminates further errors */
192
193        OpcUpdateIntegerNode (Op, 0);
194    }
195
196    return (AE_OK);
197}
198
199
200/*******************************************************************************
201 *
202 * FUNCTION:    OpcAmlCheckForConstant
203 *
204 * PARAMETERS:  ASL_WALK_CALLBACK
205 *
206 * RETURN:      Status
207 *
208 * DESCRIPTION: Check one Op for a reducible type 3/4/5 AML opcode.
209 *              This is performed via an upward walk of the parse subtree.
210 *
211 ******************************************************************************/
212
213static ACPI_STATUS
214OpcAmlCheckForConstant (
215    ACPI_PARSE_OBJECT       *Op,
216    UINT32                  Level,
217    void                    *Context)
218{
219    ACPI_WALK_STATE         *WalkState = Context;
220    ACPI_STATUS             Status = AE_OK;
221    ACPI_PARSE_OBJECT       *NextOp;
222    const ACPI_OPCODE_INFO  *OpInfo;
223
224
225    WalkState->Op = Op;
226    WalkState->Opcode = Op->Common.AmlOpcode;
227    WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
228
229    DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
230        Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);
231
232    /*
233     * These opcodes do not appear in the OpcodeInfo table, but
234     * they represent constants, so abort the constant walk now.
235     */
236    if ((WalkState->Opcode == AML_RAW_DATA_BYTE) ||
237        (WalkState->Opcode == AML_RAW_DATA_WORD) ||
238        (WalkState->Opcode == AML_RAW_DATA_DWORD) ||
239        (WalkState->Opcode == AML_RAW_DATA_QWORD))
240    {
241        DbgPrint (ASL_PARSE_OUTPUT, "RAW DATA");
242        Status = AE_TYPE;
243        goto CleanupAndExit;
244    }
245
246    /*
247     * Search upwards for a possible Name() operator. This is done
248     * because a type 3/4/5 opcode within a Name() expression
249     * MUST be reduced to a simple constant.
250     */
251    NextOp = Op->Asl.Parent;
252    while (NextOp)
253    {
254        /* Finished if we find a Name() opcode */
255
256        if (NextOp->Asl.AmlOpcode == AML_NAME_OP)
257        {
258            break;
259        }
260
261        /*
262         * Any "deferred" opcodes contain one or more TermArg parameters,
263         * and thus are not required to be folded to constants at compile
264         * time. This affects things like Buffer() and Package() objects.
265         * We just ignore them here. However, any sub-expressions can and
266         * will still be typechecked. Note: These are called the
267         * "deferred" opcodes in the AML interpreter.
268         */
269        OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
270        if (OpInfo->Flags & AML_DEFER)
271        {
272            NextOp = NULL;
273            break;
274        }
275
276        NextOp = NextOp->Asl.Parent;
277    }
278
279    /* Type 3/4/5 opcodes have the AML_CONSTANT flag set */
280
281    if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
282    {
283        /*
284         * From the ACPI specification:
285         *
286         * "The Type 3/4/5 opcodes return a value and can be used in an
287         * expression that evaluates to a constant. These opcodes may be
288         * evaluated at ASL compile-time. To ensure that these opcodes
289         * will evaluate to a constant, the following rules apply: The
290         * term cannot have a destination (target) operand, and must have
291         * either a Type3Opcode, Type4Opcode, Type5Opcode, ConstExprTerm,
292         * Integer, BufferTerm, Package, or String for all arguments."
293         */
294
295        /*
296         * The value (second) operand for the Name() operator MUST
297         * reduce to a single constant, as per the ACPI specification
298         * (the operand is a DataObject). This also implies that there
299         * can be no target operand. Name() is the only ASL operator
300         * with a "DataObject" as an operand and is thus special-
301         * cased here.
302         */
303        if (NextOp) /* Inspect a Name() operator */
304        {
305            /* Error if there is a target operand */
306
307            if (Op->Asl.CompileFlags & NODE_IS_TARGET)
308            {
309                AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, NULL);
310                Status = AE_TYPE;
311            }
312
313            /* Error if expression cannot be reduced (folded) */
314
315            if (!(NextOp->Asl.CompileFlags & NODE_COULD_NOT_REDUCE))
316            {
317                /* Ensure only one error message per statement */
318
319                NextOp->Asl.CompileFlags |= NODE_COULD_NOT_REDUCE;
320                DbgPrint (ASL_PARSE_OUTPUT,
321                    "**** Could not reduce operands for NAME opcode ****\n");
322
323                AslError (ASL_ERROR, ASL_MSG_CONSTANT_REQUIRED, Op,
324                    "Constant is required for Name operator");
325                Status = AE_TYPE;
326            }
327        }
328
329        if (ACPI_FAILURE (Status))
330        {
331            goto CleanupAndExit;
332        }
333
334        /* This is not a 3/4/5 opcode, but maybe can convert to STORE */
335
336        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
337        {
338            DbgPrint (ASL_PARSE_OUTPUT,
339                "**** Valid Target, transform to Store ****\n");
340            return (AE_CTRL_RETURN_VALUE);
341        }
342
343        /* Expression cannot be reduced */
344
345        DbgPrint (ASL_PARSE_OUTPUT,
346            "**** Not a Type 3/4/5 opcode or cannot reduce/fold (%s) ****\n",
347             Op->Asl.ParseOpName);
348
349        Status = AE_TYPE;
350        goto CleanupAndExit;
351    }
352
353    /*
354     * TBD: Ignore buffer constants for now. The problem is that these
355     * constants have been transformed into RAW_DATA at this point, from
356     * the parse tree transform process which currently happens before
357     * the constant folding process. We may need to defer this transform
358     * for buffer until after the constant folding.
359     */
360    if (WalkState->Opcode == AML_BUFFER_OP)
361    {
362        DbgPrint (ASL_PARSE_OUTPUT,
363            "\nBuffer constant reduction is not supported yet\n");
364
365        if (NextOp) /* Found a Name() operator, error */
366        {
367            AslError (ASL_ERROR, ASL_MSG_UNSUPPORTED, Op,
368                "Buffer expression cannot be reduced");
369        }
370
371        Status = AE_TYPE;
372        goto CleanupAndExit;
373    }
374
375    /* Debug output */
376
377    DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");
378
379    if (Op->Asl.CompileFlags & NODE_IS_TARGET)
380    {
381        if (Op->Asl.ParseOpcode == PARSEOP_ZERO)
382        {
383            DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " NULL TARGET");
384        }
385        else
386        {
387            DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " VALID TARGET");
388        }
389    }
390
391    if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
392    {
393        DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " TERMARG");
394    }
395
396CleanupAndExit:
397
398    /* Dump the node compile flags also */
399
400    TrPrintNodeCompileFlags (Op->Asl.CompileFlags);
401    DbgPrint (ASL_PARSE_OUTPUT, "\n");
402    return (Status);
403}
404
405
406/*******************************************************************************
407 *
408 * FUNCTION:    TrSimpleConstantReduction
409 *
410 * PARAMETERS:  Op                  - Parent operator to be transformed
411 *              WalkState           - Current walk state
412 *
413 * RETURN:      Status
414 *
415 * DESCRIPTION: Reduce an entire AML operation to a single constant. The
416 *              operation must not have a target operand.
417 *
418 *              Add (32,64) --> 96
419 *
420 ******************************************************************************/
421
422static ACPI_STATUS
423TrSimpleConstantReduction (
424    ACPI_PARSE_OBJECT       *Op,
425    ACPI_WALK_STATE         *WalkState)
426{
427    ACPI_PARSE_OBJECT       *RootOp;
428    ACPI_PARSE_OBJECT       *OriginalParentOp;
429    ACPI_OPERAND_OBJECT     *ObjDesc;
430    ACPI_STATUS             Status;
431
432
433    DbgPrint (ASL_PARSE_OUTPUT,
434        "Simple subtree constant reduction, operator to constant\n");
435
436    /* Allocate a new temporary root for this subtree */
437
438    RootOp = TrAllocateNode (PARSEOP_INTEGER);
439    if (!RootOp)
440    {
441        return (AE_NO_MEMORY);
442    }
443
444    RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
445
446    OriginalParentOp = Op->Common.Parent;
447    Op->Common.Parent = RootOp;
448
449    /* Hand off the subtree to the AML interpreter */
450
451    WalkState->CallerReturnDesc = &ObjDesc;
452
453    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
454        OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
455
456    /* Restore original parse tree */
457
458    Op->Common.Parent = OriginalParentOp;
459
460    if (ACPI_FAILURE (Status))
461    {
462        DbgPrint (ASL_PARSE_OUTPUT,
463            "Constant Subtree evaluation(1), %s\n",
464            AcpiFormatException (Status));
465        return (Status);
466    }
467
468    /* Get the final result */
469
470    Status = AcpiDsResultPop (&ObjDesc, WalkState);
471    if (ACPI_FAILURE (Status))
472    {
473        DbgPrint (ASL_PARSE_OUTPUT,
474            "Constant Subtree evaluation(2), %s\n",
475            AcpiFormatException (Status));
476        return (Status);
477    }
478
479    /* Disconnect any existing children, install new constant */
480
481    Op->Asl.Child = NULL;
482    TrInstallReducedConstant (Op, ObjDesc);
483
484    UtSetParseOpName (Op);
485    return (AE_OK);
486}
487
488
489/*******************************************************************************
490 *
491 * FUNCTION:    TrTransformToStoreOp
492 *
493 * PARAMETERS:  Op                  - Parent operator to be transformed
494 *              WalkState           - Current walk state
495 *
496 * RETURN:      Status
497 *
498 * DESCRIPTION: Transforms a single AML operation with a constant and target
499 *              to a simple store operation:
500 *
501 *              Add (32,64,DATA) --> Store (96,DATA)
502 *
503 ******************************************************************************/
504
505static ACPI_STATUS
506TrTransformToStoreOp (
507    ACPI_PARSE_OBJECT       *Op,
508    ACPI_WALK_STATE         *WalkState)
509{
510    ACPI_PARSE_OBJECT       *OriginalTarget;
511    ACPI_PARSE_OBJECT       *NewTarget;
512    ACPI_PARSE_OBJECT       *Child1;
513    ACPI_PARSE_OBJECT       *Child2;
514    ACPI_OPERAND_OBJECT     *ObjDesc;
515    ACPI_PARSE_OBJECT       *NewParent;
516    ACPI_PARSE_OBJECT       *OriginalParent;
517    ACPI_STATUS             Status;
518
519
520    /* Extract the operands */
521
522    Child1 = Op->Asl.Child;
523    Child2 = Child1->Asl.Next;
524
525    /*
526     * Special case for DIVIDE -- it has two targets. The first
527     * is for the remainder and if present, we will not attempt
528     * to reduce the expression.
529     */
530    if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
531    {
532        Child2 = Child2->Asl.Next;
533        if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
534        {
535            DbgPrint (ASL_PARSE_OUTPUT,
536                "Cannot reduce DIVIDE - has two targets\n\n");
537            return (AE_OK);
538        }
539    }
540
541    DbgPrint (ASL_PARSE_OUTPUT,
542        "Reduction/Transform to StoreOp: Store(%s, %s)\n",
543        Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
544
545    /*
546     * Create a NULL (zero) target so that we can use the
547     * interpreter to evaluate the expression.
548     */
549    NewTarget = TrCreateNullTarget ();
550    NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
551
552    /* Handle one-operand cases (NOT, TOBCD, etc.) */
553
554    if (!Child2->Asl.Next)
555    {
556        Child2 = Child1;
557    }
558
559    /* Link in new NULL target as the last operand */
560
561    OriginalTarget = Child2->Asl.Next;
562    Child2->Asl.Next = NewTarget;
563    NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;
564
565    NewParent = TrAllocateNode (PARSEOP_INTEGER);
566    NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
567
568    OriginalParent = Op->Common.Parent;
569    Op->Common.Parent = NewParent;
570
571    /* Hand off the subtree to the AML interpreter */
572
573    WalkState->CallerReturnDesc = &ObjDesc;
574
575    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
576        OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
577    if (ACPI_FAILURE (Status))
578    {
579        DbgPrint (ASL_PARSE_OUTPUT,
580            "Constant Subtree evaluation(3), %s\n",
581            AcpiFormatException (Status));
582        goto EvalError;
583    }
584
585    /* Get the final result */
586
587    Status = AcpiDsResultPop (&ObjDesc, WalkState);
588    if (ACPI_FAILURE (Status))
589    {
590        DbgPrint (ASL_PARSE_OUTPUT,
591            "Constant Subtree evaluation(4), %s\n",
592            AcpiFormatException (Status));
593        goto EvalError;
594    }
595
596    /* Truncate any subtree expressions, they have been evaluated */
597
598    Child1->Asl.Child = NULL;
599
600    /* Folded constant is in ObjDesc, store into Child1 */
601
602    TrInstallReducedConstant (Child1, ObjDesc);
603
604    /* Convert operator to STORE */
605
606    Op->Asl.ParseOpcode = PARSEOP_STORE;
607    Op->Asl.AmlOpcode = AML_STORE_OP;
608    UtSetParseOpName (Op);
609    Op->Common.Parent = OriginalParent;
610
611    /* First child is the folded constant */
612
613    /* Second child will be the target */
614
615    Child1->Asl.Next = OriginalTarget;
616    return (AE_OK);
617
618
619EvalError:
620
621    /* Restore original links */
622
623    Op->Common.Parent = OriginalParent;
624    Child2->Asl.Next = OriginalTarget;
625    return (Status);
626}
627
628
629/*******************************************************************************
630 *
631 * FUNCTION:    TrInstallReducedConstant
632 *
633 * PARAMETERS:  Op                  - Parent operator to be transformed
634 *              ObjDesc             - Reduced constant to be installed
635 *
636 * RETURN:      None
637 *
638 * DESCRIPTION: Transform the original operator to a simple constant.
639 *              Handles Integers, Strings, and Buffers.
640 *
641 ******************************************************************************/
642
643static void
644TrInstallReducedConstant (
645    ACPI_PARSE_OBJECT       *Op,
646    ACPI_OPERAND_OBJECT     *ObjDesc)
647{
648    ACPI_PARSE_OBJECT       *LengthOp;
649    ACPI_PARSE_OBJECT       *DataOp;
650
651
652    TotalFolds++;
653    AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
654        Op->Asl.ParseOpName);
655
656    /*
657     * Because we know we executed type 3/4/5 opcodes above, we know that
658     * the result must be either an Integer, String, or Buffer.
659     */
660    switch (ObjDesc->Common.Type)
661    {
662    case ACPI_TYPE_INTEGER:
663
664        OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
665
666        DbgPrint (ASL_PARSE_OUTPUT,
667            "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
668            Op->Asl.ParseOpName,
669            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
670        break;
671
672    case ACPI_TYPE_STRING:
673
674        Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
675        Op->Common.AmlOpcode = AML_STRING_OP;
676        Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
677        Op->Common.Value.String = ObjDesc->String.Pointer;
678
679        DbgPrint (ASL_PARSE_OUTPUT,
680            "Constant expression reduced to (STRING) %s\n\n",
681            Op->Common.Value.String);
682        break;
683
684    case ACPI_TYPE_BUFFER:
685        /*
686         * Create a new parse subtree of the form:
687         *
688         * BUFFER (Buffer AML opcode)
689         *    INTEGER (Buffer length in bytes)
690         *    RAW_DATA (Buffer byte data)
691         */
692        Op->Asl.ParseOpcode = PARSEOP_BUFFER;
693        Op->Common.AmlOpcode = AML_BUFFER_OP;
694        Op->Asl.CompileFlags = NODE_AML_PACKAGE;
695        UtSetParseOpName (Op);
696
697        /* Child node is the buffer length */
698
699        LengthOp = TrAllocateNode (PARSEOP_INTEGER);
700
701        LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
702        LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
703        LengthOp->Asl.Parent = Op;
704        (void) OpcSetOptimalIntegerSize (LengthOp);
705
706        Op->Asl.Child = LengthOp;
707
708        /* Next child is the raw buffer data */
709
710        DataOp = TrAllocateNode (PARSEOP_RAW_DATA);
711        DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
712        DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
713        DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
714        DataOp->Asl.Parent = Op;
715
716        LengthOp->Asl.Next = DataOp;
717
718        DbgPrint (ASL_PARSE_OUTPUT,
719            "Constant expression reduced to (BUFFER) length %X\n\n",
720            ObjDesc->Buffer.Length);
721        break;
722
723    default:
724        break;
725    }
726}
727
728
729/*******************************************************************************
730 *
731 * FUNCTION:    OpcUpdateIntegerNode
732 *
733 * PARAMETERS:  Op                  - Current parse object
734 *              Value               - Value for the integer op
735 *
736 * RETURN:      None
737 *
738 * DESCRIPTION: Update node to the correct Integer type and value
739 *
740 ******************************************************************************/
741
742static void
743OpcUpdateIntegerNode (
744    ACPI_PARSE_OBJECT       *Op,
745    UINT64                  Value)
746{
747
748    Op->Common.Value.Integer = Value;
749
750    /*
751     * The AmlLength is used by the parser to indicate a constant,
752     * (if non-zero). Length is either (1/2/4/8)
753     */
754    switch (Op->Asl.AmlLength)
755    {
756    case 1:
757
758        TrUpdateNode (PARSEOP_BYTECONST, Op);
759        Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
760        break;
761
762    case 2:
763
764        TrUpdateNode (PARSEOP_WORDCONST, Op);
765        Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
766        break;
767
768    case 4:
769
770        TrUpdateNode (PARSEOP_DWORDCONST, Op);
771        Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
772        break;
773
774    case 8:
775
776        TrUpdateNode (PARSEOP_QWORDCONST, Op);
777        Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
778        break;
779
780    case 0:
781    default:
782
783        OpcSetOptimalIntegerSize (Op);
784        TrUpdateNode (PARSEOP_INTEGER, Op);
785        break;
786    }
787
788    Op->Asl.AmlLength = 0;
789}
790
791
792/*******************************************************************************
793 *
794 * FUNCTION:    OpcAmlEvaluationWalk1
795 *
796 * PARAMETERS:  ASL_WALK_CALLBACK
797 *
798 * RETURN:      Status
799 *
800 * DESCRIPTION: Descending callback for AML execution of constant subtrees
801 *
802 ******************************************************************************/
803
804static ACPI_STATUS
805OpcAmlEvaluationWalk1 (
806    ACPI_PARSE_OBJECT       *Op,
807    UINT32                  Level,
808    void                    *Context)
809{
810    ACPI_WALK_STATE         *WalkState = Context;
811    ACPI_STATUS             Status;
812    ACPI_PARSE_OBJECT       *OutOp;
813
814
815    WalkState->Op = Op;
816    WalkState->Opcode = Op->Common.AmlOpcode;
817    WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
818
819    /* Copy child pointer to Arg for compatibility with Interpreter */
820
821    if (Op->Asl.Child)
822    {
823        Op->Common.Value.Arg = Op->Asl.Child;
824    }
825
826    /* Call AML dispatcher */
827
828    Status = AcpiDsExecBeginOp (WalkState, &OutOp);
829    if (ACPI_FAILURE (Status))
830    {
831        DbgPrint (ASL_PARSE_OUTPUT,
832            "%s Constant interpretation failed (1) - %s\n",
833            Op->Asl.ParseOpName, AcpiFormatException (Status));
834    }
835
836    return (Status);
837}
838
839
840/*******************************************************************************
841 *
842 * FUNCTION:    OpcAmlEvaluationWalk2
843 *
844 * PARAMETERS:  ASL_WALK_CALLBACK
845 *
846 * RETURN:      Status
847 *
848 * DESCRIPTION: Ascending callback for AML execution of constant subtrees
849 *
850 ******************************************************************************/
851
852static ACPI_STATUS
853OpcAmlEvaluationWalk2 (
854    ACPI_PARSE_OBJECT       *Op,
855    UINT32                  Level,
856    void                    *Context)
857{
858    ACPI_WALK_STATE         *WalkState = Context;
859    ACPI_STATUS             Status;
860
861
862    WalkState->Op = Op;
863    WalkState->Opcode = Op->Common.AmlOpcode;
864    WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
865
866    /* Copy child pointer to Arg for compatibility with Interpreter */
867
868    if (Op->Asl.Child)
869    {
870        Op->Common.Value.Arg = Op->Asl.Child;
871    }
872
873    /* Call AML dispatcher */
874
875    Status = AcpiDsExecEndOp (WalkState);
876    if (ACPI_FAILURE (Status))
877    {
878        DbgPrint (ASL_PARSE_OUTPUT,
879            "%s: Constant interpretation failed (2) - %s\n",
880            Op->Asl.ParseOpName, AcpiFormatException (Status));
881    }
882
883    return (Status);
884}
885