aslopt.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: aslopt- Compiler optimizations
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
47#include <contrib/dev/acpica/include/acparser.h>
48#include <contrib/dev/acpica/include/amlcode.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50
51
52#define _COMPONENT          ACPI_COMPILER
53        ACPI_MODULE_NAME    ("aslopt")
54
55
56static UINT32               OptTotal = 0;
57
58/* Local prototypes */
59
60static ACPI_STATUS
61OptSearchToRoot (
62    ACPI_PARSE_OBJECT       *Op,
63    ACPI_WALK_STATE         *WalkState,
64    ACPI_NAMESPACE_NODE     *CurrentNode,
65    ACPI_NAMESPACE_NODE     *TargetNode,
66    ACPI_BUFFER             *TargetPath,
67    char                    **NewPath);
68
69static ACPI_STATUS
70OptBuildShortestPath (
71    ACPI_PARSE_OBJECT       *Op,
72    ACPI_WALK_STATE         *WalkState,
73    ACPI_NAMESPACE_NODE     *CurrentNode,
74    ACPI_NAMESPACE_NODE     *TargetNode,
75    ACPI_BUFFER             *CurrentPath,
76    ACPI_BUFFER             *TargetPath,
77    ACPI_SIZE               AmlNameStringLength,
78    UINT8                   IsDeclaration,
79    char                    **ReturnNewPath);
80
81static ACPI_STATUS
82OptOptimizeNameDeclaration (
83    ACPI_PARSE_OBJECT       *Op,
84    ACPI_WALK_STATE         *WalkState,
85    ACPI_NAMESPACE_NODE     *CurrentNode,
86    ACPI_NAMESPACE_NODE     *TargetNode,
87    char                    *AmlNameString,
88    char                    **NewPath);
89
90
91/*******************************************************************************
92 *
93 * FUNCTION:    OptSearchToRoot
94 *
95 * PARAMETERS:  Op                  - Current parser op
96 *              WalkState           - Current state
97 *              CurrentNode         - Where we are in the namespace
98 *              TargetNode          - Node to which we are referring
99 *              TargetPath          - External full path to the target node
100 *              NewPath             - Where the optimized path is returned
101 *
102 * RETURN:      Status
103 *
104 * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI
105 *              name utilizing the search-to-root name resolution algorithm
106 *              that is used by AML interpreters.
107 *
108 ******************************************************************************/
109
110static ACPI_STATUS
111OptSearchToRoot (
112    ACPI_PARSE_OBJECT       *Op,
113    ACPI_WALK_STATE         *WalkState,
114    ACPI_NAMESPACE_NODE     *CurrentNode,
115    ACPI_NAMESPACE_NODE     *TargetNode,
116    ACPI_BUFFER             *TargetPath,
117    char                    **NewPath)
118{
119    ACPI_NAMESPACE_NODE     *Node;
120    ACPI_GENERIC_STATE      ScopeInfo;
121    ACPI_STATUS             Status;
122    char                    *Path;
123
124
125    ACPI_FUNCTION_NAME (OptSearchToRoot);
126
127
128    /*
129     * Check if search-to-root can be utilized. Use the last NameSeg of
130     * the NamePath and 1) See if can be found and 2) If found, make
131     * sure that it is the same node that we want. If there is another
132     * name in the search path before the one we want, the nodes will
133     * not match, and we cannot use this optimization.
134     */
135    Path = &(((char *) TargetPath->Pointer)[
136        TargetPath->Length - ACPI_NAME_SIZE]),
137    ScopeInfo.Scope.Node = CurrentNode;
138
139    /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */
140
141    Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
142        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
143        WalkState, &(Node));
144    if (ACPI_FAILURE (Status))
145    {
146        return (Status);
147    }
148
149    /*
150     * We found the name, but we must check to make sure that the node
151     * matches. Otherwise, there is another identical name in the search
152     * path that precludes the use of this optimization.
153     */
154    if (Node != TargetNode)
155    {
156        /*
157         * This means that another object with the same name was found first,
158         * and we cannot use this optimization.
159         */
160        return (AE_NOT_FOUND);
161    }
162
163    /* Found the node, we can use this optimization */
164
165    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
166        "NAMESEG:   %-24s", Path));
167
168    /* We must allocate a new string for the name (TargetPath gets deleted) */
169
170    *NewPath = UtStringCacheCalloc (ACPI_NAME_SIZE + 1);
171    strcpy (*NewPath, Path);
172
173    if (strncmp (*NewPath, "_T_", 3))
174    {
175        AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION,
176            Op, *NewPath);
177    }
178
179    return (AE_OK);
180}
181
182
183/*******************************************************************************
184 *
185 * FUNCTION:    OptBuildShortestPath
186 *
187 * PARAMETERS:  Op                  - Current parser op
188 *              WalkState           - Current state
189 *              CurrentNode         - Where we are in the namespace
190 *              TargetNode          - Node to which we are referring
191 *              CurrentPath         - External full path to the current node
192 *              TargetPath          - External full path to the target node
193 *              AmlNameStringLength - Length of the original namepath
194 *              IsDeclaration       - TRUE for declaration, FALSE for reference
195 *              ReturnNewPath       - Where the optimized path is returned
196 *
197 * RETURN:      Status
198 *
199 * DESCRIPTION: Build an optimal NamePath using carats
200 *
201 ******************************************************************************/
202
203static ACPI_STATUS
204OptBuildShortestPath (
205    ACPI_PARSE_OBJECT       *Op,
206    ACPI_WALK_STATE         *WalkState,
207    ACPI_NAMESPACE_NODE     *CurrentNode,
208    ACPI_NAMESPACE_NODE     *TargetNode,
209    ACPI_BUFFER             *CurrentPath,
210    ACPI_BUFFER             *TargetPath,
211    ACPI_SIZE               AmlNameStringLength,
212    UINT8                   IsDeclaration,
213    char                    **ReturnNewPath)
214{
215    UINT32                  NumCommonSegments;
216    UINT32                  MaxCommonSegments;
217    UINT32                  Index;
218    UINT32                  NumCarats;
219    UINT32                  i;
220    char                    *NewPathInternal;
221    char                    *NewPathExternal;
222    ACPI_NAMESPACE_NODE     *Node;
223    ACPI_GENERIC_STATE      ScopeInfo;
224    ACPI_STATUS             Status;
225    BOOLEAN                 SubPath = FALSE;
226
227
228    ACPI_FUNCTION_NAME (OptBuildShortestPath);
229
230
231    ScopeInfo.Scope.Node = CurrentNode;
232
233    /*
234     * Determine the maximum number of NameSegs that the Target and Current paths
235     * can possibly have in common. (To optimize, we have to have at least 1)
236     *
237     * Note: The external NamePath string lengths are always a multiple of 5
238     * (ACPI_NAME_SIZE + separator)
239     */
240    MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
241    if (CurrentPath->Length < TargetPath->Length)
242    {
243        MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
244    }
245
246    /*
247     * Determine how many NameSegs the two paths have in common.
248     * (Starting from the root)
249     */
250    for (NumCommonSegments = 0;
251         NumCommonSegments < MaxCommonSegments;
252         NumCommonSegments++)
253    {
254        /* Compare two single NameSegs */
255
256        Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
257
258        if (!ACPI_COMPARE_NAME (
259            &(ACPI_CAST_PTR (char, TargetPath->Pointer)) [Index],
260            &(ACPI_CAST_PTR (char, CurrentPath->Pointer)) [Index]))
261        {
262            /* Mismatch */
263
264            break;
265        }
266    }
267
268    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u",
269        NumCommonSegments));
270
271    /* There must be at least 1 common NameSeg in order to optimize */
272
273    if (NumCommonSegments == 0)
274    {
275        return (AE_NOT_FOUND);
276    }
277
278    if (NumCommonSegments == MaxCommonSegments)
279    {
280        if (CurrentPath->Length == TargetPath->Length)
281        {
282            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
283            return (AE_NOT_FOUND);
284        }
285        else
286        {
287            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
288            SubPath = TRUE;
289        }
290    }
291
292    /* Determine how many prefix Carats are required */
293
294    NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
295        NumCommonSegments;
296
297    /*
298     * Construct a new target string
299     */
300    NewPathExternal =
301        ACPI_ALLOCATE_ZEROED (TargetPath->Length + NumCarats + 1);
302
303    /* Insert the Carats into the Target string */
304
305    for (i = 0; i < NumCarats; i++)
306    {
307        NewPathExternal[i] = AML_PARENT_PREFIX;
308    }
309
310    /*
311     * Copy only the necessary (optimal) segments from the original
312     * target string
313     */
314    Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
315
316    /* Special handling for exact subpath in a name declaration */
317
318    if (IsDeclaration && SubPath &&
319        (CurrentPath->Length > TargetPath->Length))
320    {
321        /*
322         * The current path is longer than the target, and the target is a
323         * subpath of the current path. We must include one more NameSeg of
324         * the target path
325         */
326        Index -= ACPI_PATH_SEGMENT_LENGTH;
327
328        /* Special handling for Scope() operator */
329
330        if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
331        {
332            NewPathExternal[i] = AML_PARENT_PREFIX;
333            i++;
334            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
335        }
336    }
337
338    /* Make sure we haven't gone off the end of the target path */
339
340    if (Index > TargetPath->Length)
341    {
342        Index = TargetPath->Length;
343    }
344
345    strcpy (&NewPathExternal[i],
346        &(ACPI_CAST_PTR (char, TargetPath->Pointer))[Index]);
347    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
348
349    /*
350     * Internalize the new target string and check it against the original
351     * string to make sure that this is in fact an optimization. If the
352     * original string is already optimal, there is no point in continuing.
353     */
354    Status = AcpiNsInternalizeName (NewPathExternal, &NewPathInternal);
355    if (ACPI_FAILURE (Status))
356    {
357        AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
358            ASL_NO_ABORT);
359        goto Cleanup;
360    }
361
362    if (strlen (NewPathInternal) >= AmlNameStringLength)
363    {
364        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
365            " NOT SHORTER (New %u old %u)",
366            (UINT32) strlen (NewPathInternal),
367            (UINT32) AmlNameStringLength));
368
369        ACPI_FREE (NewPathInternal);
370        Status = AE_NOT_FOUND;
371        goto Cleanup;
372    }
373
374    /*
375     * Check to make sure that the optimization finds the node we are
376     * looking for. This is simply a sanity check on the new
377     * path that has been created.
378     */
379    Status = AcpiNsLookup (&ScopeInfo, NewPathInternal,
380        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
381        ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
382    if (ACPI_SUCCESS (Status))
383    {
384        /* Found the namepath, but make sure the node is correct */
385
386        if (Node == TargetNode)
387        {
388            /* The lookup matched the node, accept this optimization */
389
390            AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
391                Op, NewPathExternal);
392            *ReturnNewPath = NewPathInternal;
393        }
394        else
395        {
396            /* Node is not correct, do not use this optimization */
397
398            Status = AE_NOT_FOUND;
399            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
400            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
401                "Not using optimized name - found wrong node");
402        }
403    }
404    else
405    {
406        /* The lookup failed, we obviously cannot use this optimization */
407
408        ACPI_FREE (NewPathInternal);
409
410        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
411        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
412            "Not using optimized name - did not find node");
413    }
414
415Cleanup:
416
417    ACPI_FREE (NewPathExternal);
418    return (Status);
419}
420
421
422/*******************************************************************************
423 *
424 * FUNCTION:    OptOptimizeNameDeclaration
425 *
426 * PARAMETERS:  Op                  - Current parser op
427 *              WalkState           - Current state
428 *              CurrentNode         - Where we are in the namespace
429 *              AmlNameString       - Unoptimized namepath
430 *              NewPath             - Where the optimized path is returned
431 *
432 * RETURN:      Status. AE_OK If path is optimized
433 *
434 * DESCRIPTION: Perform a simple optimization of removing an extraneous
435 *              backslash prefix if we are already at the root scope.
436 *
437 ******************************************************************************/
438
439static ACPI_STATUS
440OptOptimizeNameDeclaration (
441    ACPI_PARSE_OBJECT       *Op,
442    ACPI_WALK_STATE         *WalkState,
443    ACPI_NAMESPACE_NODE     *CurrentNode,
444    ACPI_NAMESPACE_NODE     *TargetNode,
445    char                    *AmlNameString,
446    char                    **NewPath)
447{
448    ACPI_STATUS             Status;
449    char                    *NewPathExternal;
450    ACPI_NAMESPACE_NODE     *Node;
451
452
453    ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration);
454
455
456    if (((CurrentNode == AcpiGbl_RootNode) ||
457        (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK)) &&
458            (ACPI_IS_ROOT_PREFIX (AmlNameString[0])))
459    {
460        /*
461         * The current scope is the root, and the namepath has a root prefix
462         * that is therefore extraneous. Remove it.
463         */
464        *NewPath = &AmlNameString[1];
465
466        /* Debug output */
467
468        Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
469            NULL, &NewPathExternal);
470        if (ACPI_FAILURE (Status))
471        {
472            AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
473                ASL_NO_ABORT);
474            return (Status);
475        }
476
477        /*
478         * Check to make sure that the optimization finds the node we are
479         * looking for. This is simply a sanity check on the new
480         * path that has been created.
481         *
482         * We know that we are at the root, so NULL is used for the scope.
483         */
484        Status = AcpiNsLookup (NULL, *NewPath,
485            ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
486            ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
487        if (ACPI_SUCCESS (Status))
488        {
489            /* Found the namepath, but make sure the node is correct */
490
491            if (Node == TargetNode)
492            {
493                /* The lookup matched the node, accept this optimization */
494
495                AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
496                    Op, NewPathExternal);
497
498                ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
499                    "AT ROOT:   %-24s", NewPathExternal));
500            }
501            else
502            {
503                /* Node is not correct, do not use this optimization */
504
505                Status = AE_NOT_FOUND;
506                ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
507                    " ***** WRONG NODE"));
508                AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
509                    "Not using optimized name - found wrong node");
510            }
511        }
512        else
513        {
514            /* The lookup failed, we obviously cannot use this optimization */
515
516            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
517                " ***** NOT FOUND"));
518            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
519                "Not using optimized name - did not find node");
520        }
521
522        ACPI_FREE (NewPathExternal);
523        return (Status);
524    }
525
526    /* Could not optimize */
527
528    return (AE_NOT_FOUND);
529}
530
531
532/*******************************************************************************
533 *
534 * FUNCTION:    OptOptimizeNamePath
535 *
536 * PARAMETERS:  Op                  - Current parser op
537 *              Flags               - Opcode info flags
538 *              WalkState           - Current state
539 *              AmlNameString       - Unoptimized namepath
540 *              TargetNode          - Node to which AmlNameString refers
541 *
542 * RETURN:      None. If path is optimized, the Op is updated with new path
543 *
544 * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
545 *              Must take into account both the current location in the
546 *              namespace and the actual reference path.
547 *
548 ******************************************************************************/
549
550void
551OptOptimizeNamePath (
552    ACPI_PARSE_OBJECT       *Op,
553    UINT32                  Flags,
554    ACPI_WALK_STATE         *WalkState,
555    char                    *AmlNameString,
556    ACPI_NAMESPACE_NODE     *TargetNode)
557{
558    ACPI_STATUS             Status;
559    ACPI_BUFFER             TargetPath;
560    ACPI_BUFFER             CurrentPath;
561    ACPI_SIZE               AmlNameStringLength;
562    ACPI_NAMESPACE_NODE     *CurrentNode;
563    char                    *ExternalNameString;
564    char                    *NewPath = NULL;
565    ACPI_SIZE               HowMuchShorter;
566    ACPI_PARSE_OBJECT       *NextOp;
567
568
569    ACPI_FUNCTION_TRACE (OptOptimizeNamePath);
570
571
572    /* This is an optional optimization */
573
574    if (!Gbl_ReferenceOptimizationFlag)
575    {
576        return_VOID;
577    }
578
579    /* Various required items */
580
581    if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
582    {
583        return_VOID;
584    }
585
586    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
587        "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ",
588        Op->Asl.LogicalLineNumber,
589        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
590        AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
591
592    if (!(Flags & (AML_NAMED | AML_CREATE)))
593    {
594        if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
595        {
596            /* We don't want to fuss with actual name declaration nodes here */
597
598            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
599                "******* NAME DECLARATION\n"));
600            return_VOID;
601        }
602    }
603
604    /*
605     * The original path must be longer than one NameSeg (4 chars) for there
606     * to be any possibility that it can be optimized to a shorter string
607     */
608    AmlNameStringLength = strlen (AmlNameString);
609    if (AmlNameStringLength <= ACPI_NAME_SIZE)
610    {
611        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
612            "NAMESEG %4.4s\n", AmlNameString));
613        return_VOID;
614    }
615
616    /*
617     * We need to obtain the node that represents the current scope -- where
618     * we are right now in the namespace. We will compare this path
619     * against the Namepath, looking for commonality.
620     */
621    CurrentNode = AcpiGbl_RootNode;
622    if (WalkState->ScopeInfo)
623    {
624        CurrentNode = WalkState->ScopeInfo->Scope.Node;
625    }
626
627    if (Flags & (AML_NAMED | AML_CREATE))
628    {
629        /* This is the declaration of a new name */
630
631        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n"));
632
633        /*
634         * The node of interest is the parent of this node (the containing
635         * scope). The actual namespace node may be up more than one level
636         * of parse op or it may not exist at all (if we traverse back
637         * up to the root.)
638         */
639        NextOp = Op->Asl.Parent;
640        while (NextOp && (!NextOp->Asl.Node))
641        {
642            NextOp = NextOp->Asl.Parent;
643        }
644
645        if (NextOp && NextOp->Asl.Node)
646        {
647            CurrentNode = NextOp->Asl.Node;
648        }
649        else
650        {
651            CurrentNode = AcpiGbl_RootNode;
652        }
653    }
654    else
655    {
656        /* This is a reference to an existing named object */
657
658        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n"));
659    }
660
661    /*
662     * Obtain the full paths to the two nodes that we are interested in
663     * (Target and current namespace location) in external
664     * format -- something we can easily manipulate
665     */
666    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
667    Status = AcpiNsHandleToPathname (TargetNode, &TargetPath, FALSE);
668    if (ACPI_FAILURE (Status))
669    {
670        AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
671            ASL_NO_ABORT);
672        return_VOID;
673    }
674
675    TargetPath.Length--;    /* Subtract one for null terminator */
676
677    /* CurrentPath is the path to this scope (where we are in the namespace) */
678
679    CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
680    Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath, FALSE);
681    if (ACPI_FAILURE (Status))
682    {
683        AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
684            ASL_NO_ABORT);
685        return_VOID;
686    }
687
688    CurrentPath.Length--;   /* Subtract one for null terminator */
689
690    /* Debug output only */
691
692    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
693        NULL, &ExternalNameString);
694    if (ACPI_FAILURE (Status))
695    {
696        AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
697            ASL_NO_ABORT);
698        return_VOID;
699    }
700
701    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
702        "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n",
703        (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer,
704        (UINT32) TargetPath.Length, (char *) TargetPath.Pointer,
705        ExternalNameString));
706
707    ACPI_FREE (ExternalNameString);
708
709    /*
710     * Attempt an optmization depending on the type of namepath
711     */
712    if (Flags & (AML_NAMED | AML_CREATE))
713    {
714        /*
715         * This is a named opcode and the namepath is a name declaration, not
716         * a reference.
717         */
718        Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
719            TargetNode, AmlNameString, &NewPath);
720        if (ACPI_FAILURE (Status))
721        {
722            /*
723             * 2) now attempt to
724             *    optimize the namestring with carats (up-arrow)
725             */
726            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
727                TargetNode, &CurrentPath, &TargetPath,
728                AmlNameStringLength, 1, &NewPath);
729        }
730    }
731    else
732    {
733        /*
734         * This is a reference to an existing named object
735         *
736         * 1) Check if search-to-root can be utilized using the last
737         *    NameSeg of the NamePath
738         */
739        Status = OptSearchToRoot (Op, WalkState, CurrentNode,
740            TargetNode, &TargetPath, &NewPath);
741        if (ACPI_FAILURE (Status))
742        {
743            /*
744             * 2) Search-to-root could not be used, now attempt to
745             *    optimize the namestring with carats (up-arrow)
746             */
747            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
748                TargetNode, &CurrentPath, &TargetPath,
749                AmlNameStringLength, 0, &NewPath);
750        }
751    }
752
753    /*
754     * Success from above indicates that the NamePath was successfully
755     * optimized. We need to update the parse op with the new name
756     */
757    if (ACPI_SUCCESS (Status))
758    {
759        HowMuchShorter = (AmlNameStringLength - strlen (NewPath));
760        OptTotal += HowMuchShorter;
761
762        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
763            " REDUCED BY %2u (TOTAL SAVED %2u)",
764            (UINT32) HowMuchShorter, OptTotal));
765
766        if (Flags & AML_NAMED)
767        {
768            if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
769            {
770                /*
771                 * ALIAS is the only oddball opcode, the name declaration
772                 * (alias name) is the second operand
773                 */
774                Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
775                Op->Asl.Child->Asl.Next->Asl.AmlLength = strlen (NewPath);
776            }
777            else
778            {
779                Op->Asl.Child->Asl.Value.String = NewPath;
780                Op->Asl.Child->Asl.AmlLength = strlen (NewPath);
781            }
782        }
783        else if (Flags & AML_CREATE)
784        {
785            /* Name must appear as the last parameter */
786
787            NextOp = Op->Asl.Child;
788            while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
789            {
790                NextOp = NextOp->Asl.Next;
791            }
792            /* Update the parse node with the new NamePath */
793
794            NextOp->Asl.Value.String = NewPath;
795            NextOp->Asl.AmlLength = strlen (NewPath);
796        }
797        else
798        {
799            /* Update the parse node with the new NamePath */
800
801            Op->Asl.Value.String = NewPath;
802            Op->Asl.AmlLength = strlen (NewPath);
803        }
804    }
805    else
806    {
807        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
808    }
809
810    /* Cleanup path buffers */
811
812    ACPI_FREE (TargetPath.Pointer);
813    ACPI_FREE (CurrentPath.Pointer);
814
815    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
816    return_VOID;
817}
818