xref: /freebsd/sys/contrib/dev/acpica/compiler/aslfold.c (revision 8ef24a0d4b28fe230e20637f56869cc4148cd2ca)
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 
56 static ACPI_STATUS
57 OpcAmlEvaluationWalk1 (
58     ACPI_PARSE_OBJECT       *Op,
59     UINT32                  Level,
60     void                    *Context);
61 
62 static ACPI_STATUS
63 OpcAmlEvaluationWalk2 (
64     ACPI_PARSE_OBJECT       *Op,
65     UINT32                  Level,
66     void                    *Context);
67 
68 static ACPI_STATUS
69 OpcAmlCheckForConstant (
70     ACPI_PARSE_OBJECT       *Op,
71     UINT32                  Level,
72     void                    *Context);
73 
74 static void
75 OpcUpdateIntegerNode (
76     ACPI_PARSE_OBJECT       *Op,
77     UINT64                  Value);
78 
79 static ACPI_STATUS
80 TrTransformToStoreOp (
81     ACPI_PARSE_OBJECT       *Op,
82     ACPI_WALK_STATE         *WalkState);
83 
84 static ACPI_STATUS
85 TrSimpleConstantReduction (
86     ACPI_PARSE_OBJECT       *Op,
87     ACPI_WALK_STATE         *WalkState);
88 
89 static void
90 TrInstallReducedConstant (
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 
108 ACPI_STATUS
109 OpcAmlConstantWalk (
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 
213 static ACPI_STATUS
214 OpcAmlCheckForConstant (
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 
396 CleanupAndExit:
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 
422 static ACPI_STATUS
423 TrSimpleConstantReduction (
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 
505 static ACPI_STATUS
506 TrTransformToStoreOp (
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 
619 EvalError:
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 
643 static void
644 TrInstallReducedConstant (
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 
742 static void
743 OpcUpdateIntegerNode (
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 
804 static ACPI_STATUS
805 OpcAmlEvaluationWalk1 (
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 
852 static ACPI_STATUS
853 OpcAmlEvaluationWalk2 (
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