Update ACPI build wrappers to use new ACPICA(20050309) code.
[dragonfly.git] / sys / contrib / dev / acpica-unix-20050211 / compiler / aslopt.c
1 /******************************************************************************
2  *
3  * Module Name: aslopt- Compiler optimizations
4  *              $Revision: 17 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117
118 #include "aslcompiler.h"
119 #include "aslcompiler.y.h"
120
121 #include "acparser.h"
122 #include "amlcode.h"
123 #include "acnamesp.h"
124
125
126 #define _COMPONENT          ACPI_COMPILER
127         ACPI_MODULE_NAME    ("aslopt")
128
129
130 UINT32 OptTotal = 0;
131
132
133 /*******************************************************************************
134  *
135  * FUNCTION:    OptSearchToRoot
136  *
137  * PARAMETERS:  Op                  - Current parser op
138  *              WalkState           - Current state
139  *              CurrentNode         - Where we are in the namespace
140  *              TargetNode          - Node to which we are referring
141  *              TargetPath          - External full path to the target node
142  *              NewPath             - Where the optimized path is returned
143  *
144  * RETURN:      Status
145  *
146  * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI
147  *              name utilizing the search-to-root name resolution algorithm
148  *              that is used by AML interpreters.
149  *
150  ******************************************************************************/
151
152 ACPI_STATUS
153 OptSearchToRoot (
154     ACPI_PARSE_OBJECT       *Op,
155     ACPI_WALK_STATE         *WalkState,
156     ACPI_NAMESPACE_NODE     *CurrentNode,
157     ACPI_NAMESPACE_NODE     *TargetNode,
158     ACPI_BUFFER             *TargetPath,
159     char                    **NewPath)
160 {
161     ACPI_NAMESPACE_NODE     *Node;
162     ACPI_GENERIC_STATE      ScopeInfo;
163     ACPI_STATUS             Status;
164     char                    *Path;
165
166
167     ACPI_FUNCTION_NAME ("OptSearchToRoot");
168
169
170     /*
171      * Check if search-to-root can be utilized.  Use the last NameSeg of
172      * the NamePath and 1) See if can be found and 2) If found, make
173      * sure that it is the same node that we want.  If there is another
174      * name in the search path before the one we want, the nodes will
175      * not match, and we cannot use this optimization.
176      */
177     Path = &(((char *) TargetPath->Pointer)[TargetPath->Length - ACPI_NAME_SIZE]),
178     ScopeInfo.Scope.Node = CurrentNode;
179
180     /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */
181
182     Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
183                     ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
184                     WalkState, &(Node));
185     if (ACPI_FAILURE (Status))
186     {
187         return (Status);
188     }
189
190     /*
191      * We found the name, but we must check to make sure that the node
192      * matches.  Otherwise, there is another identical name in the search
193      * path that precludes the use of this optimization.
194      */
195     if (Node != TargetNode)
196     {
197         /*
198          * This means that another object with the same name was found first,
199          * and we cannot use this optimization.
200          */
201         return (AE_NOT_FOUND);
202     }
203
204     /* Found the node, we can use this optimization */
205
206     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
207         "NAMESEG:   %-24s", Path));
208
209     /* We must allocate a new string for the name (TargetPath gets deleted) */
210
211     *NewPath = ACPI_MEM_CALLOCATE (ACPI_NAME_SIZE + 1);
212     ACPI_STRCPY (*NewPath, Path);
213
214     if (ACPI_STRNCMP (*NewPath, "_T_", 3))
215     {
216         AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op,
217                 *NewPath);
218     }
219
220     return (AE_OK);
221 }
222
223
224 /*******************************************************************************
225  *
226  * FUNCTION:    OptBuildShortestPath
227  *
228  * PARAMETERS:  Op                  - Current parser op
229  *              WalkState           - Current state
230  *              CurrentNode         - Where we are in the namespace
231  *              TargetNode          - Node to which we are referring
232  *              CurrentPath         - External full path to the current node
233  *              TargetPath          - External full path to the target node
234  *              AmlNameStringLength - Length of the original namepath
235  *              IsDeclaration       - TRUE for declaration, FALSE for reference
236  *              ReturnNewPath       - Where the optimized path is returned
237  *
238  * RETURN:      Status
239  *
240  * DESCRIPTION: Build an optimal NamePath using carats
241  *
242  ******************************************************************************/
243
244 ACPI_STATUS
245 OptBuildShortestPath (
246     ACPI_PARSE_OBJECT       *Op,
247     ACPI_WALK_STATE         *WalkState,
248     ACPI_NAMESPACE_NODE     *CurrentNode,
249     ACPI_NAMESPACE_NODE     *TargetNode,
250     ACPI_BUFFER             *CurrentPath,
251     ACPI_BUFFER             *TargetPath,
252     ACPI_SIZE               AmlNameStringLength,
253     UINT8                   IsDeclaration,
254     char                    **ReturnNewPath)
255 {
256     UINT32                  NumCommonSegments;
257     UINT32                  MaxCommonSegments;
258     ACPI_NATIVE_UINT        Index;
259     UINT32                  NumCarats;
260     ACPI_NATIVE_UINT        i;
261     char                    *NewPath;
262     char                    *NewPathExternal;
263     ACPI_NAMESPACE_NODE     *Node;
264     ACPI_GENERIC_STATE      ScopeInfo;
265     ACPI_STATUS             Status;
266     BOOLEAN                 SubPath = FALSE;
267
268
269     ACPI_FUNCTION_NAME ("OptBuildShortestPath");
270
271
272     ScopeInfo.Scope.Node = CurrentNode;
273
274     /*
275      * Determine the maximum number of NameSegs that the Target and Current paths
276      * can possibly have in common.  (To optimize, we have to have at least 1)
277      *
278      * Note: The external NamePath string lengths are always a multiple of 5
279      * (ACPI_NAME_SIZE + separator)
280      */
281     MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
282     if (CurrentPath->Length < TargetPath->Length)
283     {
284         MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
285     }
286
287     /*
288      * Determine how many NameSegs the two paths have in common.
289      * (Starting from the root)
290      */
291     for (NumCommonSegments = 0;
292          NumCommonSegments < MaxCommonSegments;
293          NumCommonSegments++)
294     {
295         /* Compare two single NameSegs */
296
297         if (ACPI_STRNCMP (
298             &((char *) TargetPath->Pointer)[(NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1],
299             &((char *) CurrentPath->Pointer)[(NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1],
300             ACPI_NAME_SIZE))
301         {
302             /* Mismatch */
303
304             break;
305         }
306     }
307
308     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %d", NumCommonSegments));
309
310     /* There must be at least 1 common NameSeg in order to optimize */
311
312     if (NumCommonSegments == 0)
313     {
314         return (AE_NOT_FOUND);
315     }
316
317     if (NumCommonSegments == MaxCommonSegments)
318     {
319         if (CurrentPath->Length == TargetPath->Length)
320         {
321             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
322             return (AE_NOT_FOUND);
323         }
324         else
325         {
326             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
327             SubPath = TRUE;
328         }
329     }
330
331     /* Determine how many prefix Carats are required */
332
333     NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) - NumCommonSegments;
334
335     /*
336      * Construct a new target string
337      */
338     NewPathExternal = ACPI_MEM_CALLOCATE (TargetPath->Length + NumCarats);
339
340     /* Insert the Carats into the Target string */
341
342     for (i = 0; i < NumCarats; i++)
343     {
344         NewPathExternal[i] = '^';
345     }
346
347     /* Copy only the necessary (optimal) segments from the original target string */
348
349     Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
350
351     /* Special handling for exact subpath in a name declaration */
352
353     if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length))
354     {
355         /*
356          * The current path is longer than the target, and the target is a subpath
357          * of the current path.  We must include one more NameSeg of the target path
358          */
359         Index -= ACPI_PATH_SEGMENT_LENGTH;
360
361         /* Special handling for Scope() operator */
362
363         if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
364         {
365             NewPathExternal[i] = '^';
366             i++;
367             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
368         }
369     }
370
371     ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]);
372     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
373
374     /*
375      * Internalize the new target string and check it against the original string
376      * to make sure that this is in fact an optimization.  If the original string
377      * is already optimal, there is no point in continuing.
378      */
379     Status = AcpiNsInternalizeName (NewPathExternal, &NewPath);
380
381     if (ACPI_FAILURE (Status))
382     {
383         AslCoreSubsystemError (Op, Status, "Internalizing new NamePath", ASL_NO_ABORT);
384         ACPI_MEM_FREE (NewPathExternal);
385         return (Status);
386     }
387
388     if (ACPI_STRLEN (NewPath) >= AmlNameStringLength)
389     {
390         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " NOT SHORTER (New %d old %d)",
391             ACPI_STRLEN (NewPath), AmlNameStringLength));
392         ACPI_MEM_FREE (NewPathExternal);
393         return (AE_NOT_FOUND);
394     }
395
396     /*
397      * Check to make sure that the optimization finds the node we are
398      * looking for.  This is simply a sanity check on the new
399      * path that has been created.
400      */
401     Status = AcpiNsLookup (&ScopeInfo,  NewPath,
402                     ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
403                     ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
404     if (ACPI_SUCCESS (Status))
405     {
406         /* Found the namepath, but make sure the node is correct */
407
408         if (Node == TargetNode)
409         {
410             /* The lookup matched the node, accept this optimization */
411
412             AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
413                 Op, NewPathExternal);
414             *ReturnNewPath = NewPath;
415         }
416         else
417         {
418             /* Node is not correct, do not use this optimization */
419
420             Status = AE_NOT_FOUND;
421             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
422             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
423                 "Not using optimized name - found wrong node");
424         }
425     }
426     else
427     {
428         /* The lookup failed, we obviously cannot use this optimization */
429
430         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
431         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
432             "Not using optimized name - did not find node");
433     }
434
435     ACPI_MEM_FREE (NewPathExternal);
436     return (Status);
437 }
438
439
440 /*******************************************************************************
441  *
442  * FUNCTION:    OptOptimizeNameDeclaration
443  *
444  * PARAMETERS:  Op                  - Current parser op
445  *              WalkState           - Current state
446  *              CurrentNode         - Where we are in the namespace
447  *              AmlNameString       - Unoptimized namepath
448  *              NewPath             - Where the optimized path is returned
449  *
450  * RETURN:      Status. AE_OK If path is optimized
451  *
452  * DESCRIPTION: Perform a simple optimization of removing an extraneous
453  *              backslash prefix if we are already at the root scope.
454  *
455  ******************************************************************************/
456
457 ACPI_STATUS
458 OptOptimizeNameDeclaration (
459     ACPI_PARSE_OBJECT       *Op,
460     ACPI_WALK_STATE         *WalkState,
461     ACPI_NAMESPACE_NODE     *CurrentNode,
462     ACPI_NAMESPACE_NODE     *TargetNode,
463     char                    *AmlNameString,
464     char                    **NewPath)
465 {
466     ACPI_STATUS             Status;
467     char                    *NewPathExternal;
468     ACPI_GENERIC_STATE      ScopeInfo;
469     ACPI_NAMESPACE_NODE     *Node;
470
471
472     ACPI_FUNCTION_TRACE ("OptOptimizeNameDeclaration");
473
474
475     if (((CurrentNode == AcpiGbl_RootNode) ||
476         (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
477             (AmlNameString[0] == '\\'))
478     {
479         /*
480          * The current scope is the root, and the namepath has a root prefix
481          * that is therefore extraneous.  Remove it.
482          */
483         *NewPath = &AmlNameString[1];
484
485         /* Debug output */
486
487         Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
488                     NULL, &NewPathExternal);
489         if (ACPI_FAILURE (Status))
490         {
491             AslCoreSubsystemError (Op, Status, "Externalizing NamePath", ASL_NO_ABORT);
492             return (Status);
493         }
494
495         /*
496          * Check to make sure that the optimization finds the node we are
497          * looking for.  This is simply a sanity check on the new
498          * path that has been created.
499          */
500         ScopeInfo.Scope.Node = CurrentNode;
501         Status = AcpiNsLookup (&ScopeInfo, *NewPath,
502                         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
503                         ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
504         if (ACPI_SUCCESS (Status))
505         {
506             /* Found the namepath, but make sure the node is correct */
507
508             if (Node == TargetNode)
509             {
510                 /* The lookup matched the node, accept this optimization */
511
512                 AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
513                     Op, NewPathExternal);
514
515                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
516                     "AT ROOT:   %-24s", NewPathExternal));
517             }
518             else
519             {
520                 /* Node is not correct, do not use this optimization */
521
522                 Status = AE_NOT_FOUND;
523                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
524                 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
525                     "Not using optimized name - found wrong node");
526             }
527         }
528         else
529         {
530             /* The lookup failed, we obviously cannot use this optimization */
531
532             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
533             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
534                 "Not using optimized name - did not find node");
535         }
536
537         ACPI_MEM_FREE (NewPathExternal);
538         return (Status);
539     }
540
541     /* Could not optimize */
542
543     return (AE_NOT_FOUND);
544 }
545
546
547 /*******************************************************************************
548  *
549  * FUNCTION:    OptOptimizeNamePath
550  *
551  * PARAMETERS:  Op                  - Current parser op
552  *              Flags               - Opcode info flags
553  *              WalkState           - Current state
554  *              AmlNameString       - Unoptimized namepath
555  *              TargetNode          - Node to which AmlNameString refers
556  *
557  * RETURN:      None.  If path is optimized, the Op is updated with new path
558  *
559  * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
560  *              Must take into account both the current location in the
561  *              namespace and the actual reference path.
562  *
563  ******************************************************************************/
564
565 void
566 OptOptimizeNamePath (
567     ACPI_PARSE_OBJECT       *Op,
568     UINT32                  Flags,
569     ACPI_WALK_STATE         *WalkState,
570     char                    *AmlNameString,
571     ACPI_NAMESPACE_NODE     *TargetNode)
572 {
573     ACPI_STATUS             Status;
574     ACPI_BUFFER             TargetPath;
575     ACPI_BUFFER             CurrentPath;
576     ACPI_SIZE               AmlNameStringLength;
577     ACPI_NAMESPACE_NODE     *CurrentNode;
578     char                    *ExternalNameString;
579     char                    *NewPath = NULL;
580     ACPI_SIZE               HowMuchShorter;
581     ACPI_PARSE_OBJECT       *NextOp;
582
583
584     ACPI_FUNCTION_TRACE ("OptOptimizeNamePath");
585
586
587     /* This is an optional optimization */
588
589     if (!Gbl_ReferenceOptimizationFlag)
590     {
591         return_VOID;
592     }
593
594     /* Various required items */
595
596     if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
597     {
598         return_VOID;
599     }
600
601     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "%5d [%12.12s] [%12.12s] ",
602         Op->Asl.LogicalLineNumber,
603         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
604         AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
605
606     if (!(Flags & (AML_NAMED | AML_CREATE)))
607     {
608         if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
609         {
610             /* We don't want to fuss with actual name declaration nodes here */
611
612             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
613                 "******* NAME DECLARATION\n"));
614             return_VOID;
615         }
616     }
617
618     /*
619      * The original path must be longer than one NameSeg (4 chars) for there
620      * to be any possibility that it can be optimized to a shorter string
621      */
622     AmlNameStringLength = ACPI_STRLEN (AmlNameString);
623     if (AmlNameStringLength <= ACPI_NAME_SIZE)
624     {
625         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
626             "NAMESEG %4.4s\n", AmlNameString));
627         return_VOID;
628     }
629
630     /*
631      * We need to obtain the node that represents the current scope -- where
632      * we are right now in the namespace.  We will compare this path
633      * against the Namepath, looking for commonality.
634      */
635     CurrentNode = AcpiGbl_RootNode;
636     if (WalkState->ScopeInfo)
637     {
638         CurrentNode = WalkState->ScopeInfo->Scope.Node;
639     }
640
641     if (Flags & (AML_NAMED | AML_CREATE))
642     {
643         /* This is the declaration of a new name */
644
645         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME"));
646
647         /* The node of interest is the parent of this node (the containing scope) */
648
649         CurrentNode = Op->Asl.Parent->Asl.Node;
650         if (!CurrentNode)
651         {
652             CurrentNode = AcpiGbl_RootNode;
653         }
654     }
655     else
656     {
657         /* This is a reference to an existing named object */
658
659         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REF "));
660     }
661
662     /*
663      * Obtain the full paths to the two nodes that we are interested in
664      * (Target and current namespace location) in external
665      * format -- something we can easily manipulate
666      */
667     TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
668     Status = AcpiNsHandleToPathname (TargetNode, &TargetPath);
669     if (ACPI_FAILURE (Status))
670     {
671         AslCoreSubsystemError (Op, Status, "Getting Target NamePath", ASL_NO_ABORT);
672         return_VOID;
673     }
674     TargetPath.Length--;    /* Subtract one for null terminator */
675
676     /* CurrentPath is the path to this scope (where we are in the namespace) */
677
678     CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
679     Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath);
680     if (ACPI_FAILURE (Status))
681     {
682         AslCoreSubsystemError (Op, Status, "Getting Current NamePath", ASL_NO_ABORT);
683         return_VOID;
684     }
685     CurrentPath.Length--;   /* Subtract one for null terminator */
686
687     /* Debug output only */
688
689     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
690                 NULL, &ExternalNameString);
691     if (ACPI_FAILURE (Status))
692     {
693         AslCoreSubsystemError (Op, Status, "Externalizing NamePath", ASL_NO_ABORT);
694         return_VOID;
695     }
696
697     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
698         "%37s (%2d) ==> %-32s(%2d) %-32s",
699         (char *) CurrentPath.Pointer, CurrentPath.Length,
700         (char *) TargetPath.Pointer, TargetPath.Length, ExternalNameString));
701
702     ACPI_MEM_FREE (ExternalNameString);
703
704     /*
705      * Attempt an optmization depending on the type of namepath
706      */
707     if (Flags & (AML_NAMED | AML_CREATE))
708     {
709         /*
710          * This is a named opcode and the namepath is a name declaration, not
711          * a reference.
712          */
713         Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
714                     TargetNode, AmlNameString, &NewPath);
715         if (ACPI_FAILURE (Status))
716         {
717             /*
718              * 2) now attempt to
719              *    optimize the namestring with carats (up-arrow)
720              */
721             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
722                             TargetNode, &CurrentPath, &TargetPath,
723                             AmlNameStringLength, 1, &NewPath);
724         }
725     }
726     else
727     {
728         /*
729          * This is a reference to an existing named object
730          *
731          * 1) Check if search-to-root can be utilized using the last
732          *    NameSeg of the NamePath
733          */
734         Status = OptSearchToRoot (Op, WalkState, CurrentNode,
735                         TargetNode, &TargetPath, &NewPath);
736         if (ACPI_FAILURE (Status))
737         {
738             /*
739              * 2) Search-to-root could not be used, now attempt to
740              *    optimize the namestring with carats (up-arrow)
741              */
742             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
743                             TargetNode, &CurrentPath, &TargetPath,
744                             AmlNameStringLength, 0, &NewPath);
745         }
746     }
747
748     /*
749      * Success from above indicates that the NamePath was successfully
750      * optimized.  We need to update the parse op with the new name
751      */
752     if (ACPI_SUCCESS (Status))
753     {
754         HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath));
755         OptTotal += HowMuchShorter;
756
757         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " REDUCED %2d (%d)",
758             HowMuchShorter, OptTotal));
759
760         if (Flags & AML_NAMED)
761         {
762             if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
763             {
764                 /*
765                  * ALIAS is the only oddball opcode, the name declaration
766                  * (alias name) is the second operand
767                  */
768                 Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
769                 Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath);
770             }
771             else
772             {
773                 Op->Asl.Child->Asl.Value.String = NewPath;
774                 Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath);
775             }
776         }
777         else if (Flags & AML_CREATE)
778         {
779             /* Name must appear as the last parameter */
780
781             NextOp = Op->Asl.Child;
782             while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
783             {
784                 NextOp = NextOp->Asl.Next;
785             }
786             /* Update the parse node with the new NamePath */
787
788             NextOp->Asl.Value.String = NewPath;
789             NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath);
790         }
791         else
792         {
793             /* Update the parse node with the new NamePath */
794
795             Op->Asl.Value.String = NewPath;
796             Op->Asl.AmlLength = ACPI_STRLEN (NewPath);
797         }
798     }
799     else
800     {
801         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
802     }
803
804     /* Cleanup path buffers */
805
806     ACPI_MEM_FREE (TargetPath.Pointer);
807     ACPI_MEM_FREE (CurrentPath.Pointer);
808
809     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
810     return_VOID;
811 }
812