Subversion Repositories Kolibri OS

Rev

Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed

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