1 /******************************************************************************
2 *
3 * Module Name: aslfold - Constant folding
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47
48 #include "acdispat.h"
49 #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
OpcAmlConstantWalk(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)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 & OP_COMPILE_TIME_CONST)) ||
128 (Op->Asl.CompileFlags & OP_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
OpcAmlCheckForConstant(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)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 & OP_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 & OP_COULD_NOT_REDUCE))
316 {
317 /* Ensure only one error message per statement */
318
319 NextOp->Asl.CompileFlags |= OP_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 & OP_IS_TARGET)
337 {
338 DbgPrint (ASL_PARSE_OUTPUT,
339 "**** Valid Target, transform to Store or CopyObject ****\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 currently not supported\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 & OP_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 & OP_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 TrPrintOpFlags (Op->Asl.CompileFlags, ASL_PARSE_OUTPUT);
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
TrSimpleConstantReduction(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)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 = TrAllocateOp (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
TrTransformToStoreOp(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)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 UINT16 NewParseOpcode;
519 UINT16 NewAmlOpcode;
520
521
522 /* Extract the operands */
523
524 Child1 = Op->Asl.Child;
525 Child2 = Child1->Asl.Next;
526
527 /*
528 * Special case for DIVIDE -- it has two targets. The first
529 * is for the remainder and if present, we will not attempt
530 * to reduce the expression.
531 */
532 if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
533 {
534 Child2 = Child2->Asl.Next;
535 if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
536 {
537 DbgPrint (ASL_PARSE_OUTPUT,
538 "Cannot reduce DIVIDE - has two targets\n\n");
539 return (AE_OK);
540 }
541 }
542
543 switch (Op->Asl.ParseOpcode)
544 {
545 /*
546 * Folding of the explicit conversion opcodes must use CopyObject
547 * instead of Store. This can change the object type of the target
548 * operand, as per the ACPI specification:
549 *
550 * "If the ASL operator is one of the explicit conversion operators
551 * (ToString, ToInteger, etc., and the CopyObject operator), no
552 * [implicit] conversion is performed. (In other words, the result
553 * object is stored directly to the target and completely overwrites
554 * any existing object already stored at the target)"
555 */
556 case PARSEOP_TOINTEGER:
557 case PARSEOP_TOSTRING:
558 case PARSEOP_TOBUFFER:
559 case PARSEOP_TODECIMALSTRING:
560 case PARSEOP_TOHEXSTRING:
561 case PARSEOP_TOBCD:
562 case PARSEOP_FROMBCD:
563
564 NewParseOpcode = PARSEOP_COPYOBJECT;
565 NewAmlOpcode = AML_COPY_OBJECT_OP;
566
567 DbgPrint (ASL_PARSE_OUTPUT,
568 "Reduction/Transform to CopyObjectOp: CopyObject(%s, %s)\n",
569 Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
570 break;
571
572 default:
573
574 NewParseOpcode = PARSEOP_STORE;
575 NewAmlOpcode = AML_STORE_OP;
576
577 DbgPrint (ASL_PARSE_OUTPUT,
578 "Reduction/Transform to StoreOp: Store(%s, %s)\n",
579 Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
580 break;
581 }
582
583 /*
584 * Create a NULL (zero) target so that we can use the
585 * interpreter to evaluate the expression.
586 */
587 NewTarget = TrCreateNullTargetOp ();
588 NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
589
590 /* Handle one-operand cases (NOT, TOBCD, etc.) */
591
592 if (!Child2->Asl.Next)
593 {
594 Child2 = Child1;
595 }
596
597 /* Link in new NULL target as the last operand */
598
599 OriginalTarget = Child2->Asl.Next;
600 Child2->Asl.Next = NewTarget;
601 NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;
602
603 NewParent = TrAllocateOp (PARSEOP_INTEGER);
604 NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
605
606 OriginalParent = Op->Common.Parent;
607 Op->Common.Parent = NewParent;
608
609 /* Hand off the subtree to the AML interpreter */
610
611 WalkState->CallerReturnDesc = &ObjDesc;
612
613 Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
614 OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
615 if (ACPI_FAILURE (Status))
616 {
617 DbgPrint (ASL_PARSE_OUTPUT,
618 "Constant Subtree evaluation(3), %s\n",
619 AcpiFormatException (Status));
620 goto EvalError;
621 }
622
623 /* Get the final result */
624
625 Status = AcpiDsResultPop (&ObjDesc, WalkState);
626 if (ACPI_FAILURE (Status))
627 {
628 DbgPrint (ASL_PARSE_OUTPUT,
629 "Constant Subtree evaluation(4), %s\n",
630 AcpiFormatException (Status));
631 goto EvalError;
632 }
633
634 /* Truncate any subtree expressions, they have been evaluated */
635
636 Child1->Asl.Child = NULL;
637
638 /* Folded constant is in ObjDesc, store into Child1 */
639
640 TrInstallReducedConstant (Child1, ObjDesc);
641
642 /* Convert operator to STORE or COPYOBJECT */
643
644 Op->Asl.ParseOpcode = NewParseOpcode;
645 Op->Asl.AmlOpcode = NewAmlOpcode;
646 UtSetParseOpName (Op);
647 Op->Common.Parent = OriginalParent;
648
649 /* First child is the folded constant */
650
651 /* Second child will be the target */
652
653 Child1->Asl.Next = OriginalTarget;
654 return (AE_OK);
655
656
657 EvalError:
658
659 /* Restore original links */
660
661 Op->Common.Parent = OriginalParent;
662 Child2->Asl.Next = OriginalTarget;
663 return (Status);
664 }
665
666
667 /*******************************************************************************
668 *
669 * FUNCTION: TrInstallReducedConstant
670 *
671 * PARAMETERS: Op - Parent operator to be transformed
672 * ObjDesc - Reduced constant to be installed
673 *
674 * RETURN: None
675 *
676 * DESCRIPTION: Transform the original operator to a simple constant.
677 * Handles Integers, Strings, and Buffers.
678 *
679 ******************************************************************************/
680
681 static void
TrInstallReducedConstant(ACPI_PARSE_OBJECT * Op,ACPI_OPERAND_OBJECT * ObjDesc)682 TrInstallReducedConstant (
683 ACPI_PARSE_OBJECT *Op,
684 ACPI_OPERAND_OBJECT *ObjDesc)
685 {
686 ACPI_PARSE_OBJECT *LengthOp;
687 ACPI_PARSE_OBJECT *DataOp;
688
689
690 AslGbl_TotalFolds++;
691 AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
692 Op->Asl.ParseOpName);
693
694 /*
695 * Because we know we executed type 3/4/5 opcodes above, we know that
696 * the result must be either an Integer, String, or Buffer.
697 */
698 switch (ObjDesc->Common.Type)
699 {
700 case ACPI_TYPE_INTEGER:
701
702 OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
703
704 DbgPrint (ASL_PARSE_OUTPUT,
705 "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
706 Op->Asl.ParseOpName,
707 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
708 break;
709
710 case ACPI_TYPE_STRING:
711
712 Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
713 Op->Common.AmlOpcode = AML_STRING_OP;
714 Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
715 Op->Common.Value.String = ObjDesc->String.Pointer;
716
717 DbgPrint (ASL_PARSE_OUTPUT,
718 "Constant expression reduced to (STRING) %s\n\n",
719 Op->Common.Value.String);
720 break;
721
722 case ACPI_TYPE_BUFFER:
723 /*
724 * Create a new parse subtree of the form:
725 *
726 * BUFFER (Buffer AML opcode)
727 * INTEGER (Buffer length in bytes)
728 * RAW_DATA (Buffer byte data)
729 */
730 Op->Asl.ParseOpcode = PARSEOP_BUFFER;
731 Op->Common.AmlOpcode = AML_BUFFER_OP;
732 Op->Asl.CompileFlags = OP_AML_PACKAGE;
733 UtSetParseOpName (Op);
734
735 /* Child node is the buffer length */
736
737 LengthOp = TrAllocateOp (PARSEOP_INTEGER);
738
739 LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
740 LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
741 LengthOp->Asl.Parent = Op;
742 (void) OpcSetOptimalIntegerSize (LengthOp);
743
744 Op->Asl.Child = LengthOp;
745
746 /* Next child is the raw buffer data */
747
748 DataOp = TrAllocateOp (PARSEOP_RAW_DATA);
749 DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
750 DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
751 DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
752 DataOp->Asl.Parent = Op;
753
754 LengthOp->Asl.Next = DataOp;
755
756 DbgPrint (ASL_PARSE_OUTPUT,
757 "Constant expression reduced to (BUFFER) length %X\n\n",
758 ObjDesc->Buffer.Length);
759 break;
760
761 default:
762 break;
763 }
764 }
765
766
767 /*******************************************************************************
768 *
769 * FUNCTION: OpcUpdateIntegerNode
770 *
771 * PARAMETERS: Op - Current parse object
772 * Value - Value for the integer op
773 *
774 * RETURN: None
775 *
776 * DESCRIPTION: Update node to the correct Integer type and value
777 *
778 ******************************************************************************/
779
780 static void
OpcUpdateIntegerNode(ACPI_PARSE_OBJECT * Op,UINT64 Value)781 OpcUpdateIntegerNode (
782 ACPI_PARSE_OBJECT *Op,
783 UINT64 Value)
784 {
785
786 Op->Common.Value.Integer = Value;
787
788 /*
789 * The AmlLength is used by the parser to indicate a constant,
790 * (if non-zero). Length is either (1/2/4/8)
791 */
792 switch (Op->Asl.AmlLength)
793 {
794 case 1:
795
796 TrSetOpIntegerValue (PARSEOP_BYTECONST, Op);
797 Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
798 break;
799
800 case 2:
801
802 TrSetOpIntegerValue (PARSEOP_WORDCONST, Op);
803 Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
804 break;
805
806 case 4:
807
808 TrSetOpIntegerValue (PARSEOP_DWORDCONST, Op);
809 Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
810 break;
811
812 case 8:
813
814 TrSetOpIntegerValue (PARSEOP_QWORDCONST, Op);
815 Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
816 break;
817
818 case 0:
819 default:
820
821 OpcSetOptimalIntegerSize (Op);
822 TrSetOpIntegerValue (PARSEOP_INTEGER, Op);
823 break;
824 }
825
826 Op->Asl.AmlLength = 0;
827 }
828
829
830 /*******************************************************************************
831 *
832 * FUNCTION: OpcAmlEvaluationWalk1
833 *
834 * PARAMETERS: ASL_WALK_CALLBACK
835 *
836 * RETURN: Status
837 *
838 * DESCRIPTION: Descending callback for AML execution of constant subtrees
839 *
840 ******************************************************************************/
841
842 static ACPI_STATUS
OpcAmlEvaluationWalk1(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)843 OpcAmlEvaluationWalk1 (
844 ACPI_PARSE_OBJECT *Op,
845 UINT32 Level,
846 void *Context)
847 {
848 ACPI_WALK_STATE *WalkState = Context;
849 ACPI_STATUS Status;
850 ACPI_PARSE_OBJECT *OutOp;
851
852
853 WalkState->Op = Op;
854 WalkState->Opcode = Op->Common.AmlOpcode;
855 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
856
857 /* Copy child pointer to Arg for compatibility with Interpreter */
858
859 if (Op->Asl.Child)
860 {
861 Op->Common.Value.Arg = Op->Asl.Child;
862 }
863
864 /* Call AML dispatcher */
865
866 Status = AcpiDsExecBeginOp (WalkState, &OutOp);
867 if (ACPI_FAILURE (Status))
868 {
869 DbgPrint (ASL_PARSE_OUTPUT,
870 "%s Constant interpretation failed (1) - %s\n",
871 Op->Asl.ParseOpName, AcpiFormatException (Status));
872 }
873
874 return (Status);
875 }
876
877
878 /*******************************************************************************
879 *
880 * FUNCTION: OpcAmlEvaluationWalk2
881 *
882 * PARAMETERS: ASL_WALK_CALLBACK
883 *
884 * RETURN: Status
885 *
886 * DESCRIPTION: Ascending callback for AML execution of constant subtrees
887 *
888 ******************************************************************************/
889
890 static ACPI_STATUS
OpcAmlEvaluationWalk2(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)891 OpcAmlEvaluationWalk2 (
892 ACPI_PARSE_OBJECT *Op,
893 UINT32 Level,
894 void *Context)
895 {
896 ACPI_WALK_STATE *WalkState = Context;
897 ACPI_STATUS Status;
898
899
900 WalkState->Op = Op;
901 WalkState->Opcode = Op->Common.AmlOpcode;
902 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
903
904 /* Copy child pointer to Arg for compatibility with Interpreter */
905
906 if (Op->Asl.Child)
907 {
908 Op->Common.Value.Arg = Op->Asl.Child;
909 }
910
911 /* Call AML dispatcher */
912
913 Status = AcpiDsExecEndOp (WalkState);
914 if (ACPI_FAILURE (Status))
915 {
916 DbgPrint (ASL_PARSE_OUTPUT,
917 "%s: Constant interpretation failed (2) - %s\n",
918 Op->Asl.ParseOpName, AcpiFormatException (Status));
919 }
920
921 return (Status);
922 }
923