asllisting.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: asllisting - Listing file generation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#include <contrib/dev/acpica/include/amlcode.h>
47#include <contrib/dev/acpica/include/acparser.h>
48#include <contrib/dev/acpica/include/acnamesp.h>
49
50
51#define _COMPONENT          ACPI_COMPILER
52        ACPI_MODULE_NAME    ("asllisting")
53
54
55/* Local prototypes */
56
57static void
58LsGenerateListing (
59    UINT32                  FileId);
60
61static ACPI_STATUS
62LsAmlListingWalk (
63    ACPI_PARSE_OBJECT       *Op,
64    UINT32                  Level,
65    void                    *Context);
66
67static ACPI_STATUS
68LsTreeWriteWalk (
69    ACPI_PARSE_OBJECT       *Op,
70    UINT32                  Level,
71    void                    *Context);
72
73static void
74LsWriteNodeToListing (
75    ACPI_PARSE_OBJECT       *Op,
76    UINT32                  FileId);
77
78static void
79LsFinishSourceListing (
80    UINT32                  FileId);
81
82
83/*******************************************************************************
84 *
85 * FUNCTION:    LsDoListings
86 *
87 * PARAMETERS:  None. Examines the various output file global flags.
88 *
89 * RETURN:      None
90 *
91 * DESCRIPTION: Generate all requested listing files.
92 *
93 ******************************************************************************/
94
95void
96LsDoListings (
97    void)
98{
99
100    if (Gbl_C_OutputFlag)
101    {
102        LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
103    }
104
105    if (Gbl_ListingFlag)
106    {
107        LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
108    }
109
110    if (Gbl_AsmOutputFlag)
111    {
112        LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
113    }
114
115    if (Gbl_C_IncludeOutputFlag)
116    {
117        LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
118    }
119
120    if (Gbl_AsmIncludeOutputFlag)
121    {
122        LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
123    }
124
125    if (Gbl_C_OffsetTableFlag)
126    {
127        LsGenerateListing (ASL_FILE_C_OFFSET_OUTPUT);
128    }
129}
130
131
132/*******************************************************************************
133 *
134 * FUNCTION:    LsGenerateListing
135 *
136 * PARAMETERS:  FileId      - ID of listing file
137 *
138 * RETURN:      None
139 *
140 * DESCRIPTION: Generate a listing file. This can be one of the several types
141 *              of "listings" supported.
142 *
143 ******************************************************************************/
144
145static void
146LsGenerateListing (
147    UINT32                  FileId)
148{
149
150    /* Start at the beginning of both the source and AML files */
151
152    FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
153    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
154    Gbl_SourceLine = 0;
155    Gbl_CurrentHexColumn = 0;
156    LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename);
157
158    if (FileId == ASL_FILE_C_OFFSET_OUTPUT)
159    {
160        Gbl_CurrentAmlOffset = 0;
161
162        /* Offset table file has a special header and footer */
163
164        LsDoOffsetTableHeader (FileId);
165
166        TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlOffsetWalk,
167            NULL, (void *) ACPI_TO_POINTER (FileId));
168        LsDoOffsetTableFooter (FileId);
169        return;
170    }
171
172    /* Process all parse nodes */
173
174    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk,
175        NULL, (void *) ACPI_TO_POINTER (FileId));
176
177    /* Final processing */
178
179    LsFinishSourceListing (FileId);
180}
181
182
183/*******************************************************************************
184 *
185 * FUNCTION:    LsAmlListingWalk
186 *
187 * PARAMETERS:  ASL_WALK_CALLBACK
188 *
189 * RETURN:      Status
190 *
191 * DESCRIPTION: Process one node during a listing file generation.
192 *
193 ******************************************************************************/
194
195static ACPI_STATUS
196LsAmlListingWalk (
197    ACPI_PARSE_OBJECT       *Op,
198    UINT32                  Level,
199    void                    *Context)
200{
201    UINT8                   FileByte;
202    UINT32                  i;
203    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
204
205
206    LsWriteNodeToListing (Op, FileId);
207
208    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
209    {
210        /* Buffer is a resource template, don't dump the data all at once */
211
212        return (AE_OK);
213    }
214
215    /* Write the hex bytes to the listing file(s) (if requested) */
216
217    for (i = 0; i < Op->Asl.FinalAmlLength; i++)
218    {
219        if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
220        {
221            FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
222            AslAbort ();
223        }
224        LsWriteListingHexBytes (&FileByte, 1, FileId);
225    }
226
227    return (AE_OK);
228}
229
230
231/*******************************************************************************
232 *
233 * FUNCTION:    LsDumpParseTree, LsTreeWriteWalk
234 *
235 * PARAMETERS:  None
236 *
237 * RETURN:      None
238 *
239 * DESCRIPTION: Dump entire parse tree, for compiler debug only
240 *
241 ******************************************************************************/
242
243void
244LsDumpParseTree (
245    void)
246{
247
248    if (!Gbl_DebugFlag)
249    {
250        return;
251    }
252
253    DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
254    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
255        LsTreeWriteWalk, NULL, NULL);
256}
257
258
259static ACPI_STATUS
260LsTreeWriteWalk (
261    ACPI_PARSE_OBJECT       *Op,
262    UINT32                  Level,
263    void                    *Context)
264{
265
266    /* Debug output */
267
268    DbgPrint (ASL_TREE_OUTPUT,
269        "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
270
271    UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
272
273    DbgPrint (ASL_TREE_OUTPUT, "    (%.4X)\n", Op->Asl.ParseOpcode);
274    return (AE_OK);
275}
276
277
278/*******************************************************************************
279 *
280 * FUNCTION:    LsWriteNodeToListing
281 *
282 * PARAMETERS:  Op              - Parse node to write to the listing file.
283 *              FileId          - ID of current listing file
284 *
285 * RETURN:      None.
286 *
287 * DESCRIPTION: Write "a node" to the listing file. This means to
288 *              1) Write out all of the source text associated with the node
289 *              2) Write out all of the AML bytes associated with the node
290 *              3) Write any compiler exceptions associated with the node
291 *
292 ******************************************************************************/
293
294static void
295LsWriteNodeToListing (
296    ACPI_PARSE_OBJECT       *Op,
297    UINT32                  FileId)
298{
299    const ACPI_OPCODE_INFO  *OpInfo;
300    UINT32                  OpClass;
301    char                    *Pathname;
302    UINT32                  Length;
303    UINT32                  i;
304
305
306    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
307    OpClass = OpInfo->Class;
308
309    /* TBD: clean this up with a single flag that says:
310     * I start a named output block
311     */
312    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
313    {
314        switch (Op->Asl.ParseOpcode)
315        {
316        case PARSEOP_DEFINITIONBLOCK:
317        case PARSEOP_METHODCALL:
318        case PARSEOP_INCLUDE:
319        case PARSEOP_INCLUDE_END:
320        case PARSEOP_DEFAULT_ARG:
321
322            break;
323
324        default:
325
326            switch (OpClass)
327            {
328            case AML_CLASS_NAMED_OBJECT:
329
330                switch (Op->Asl.AmlOpcode)
331                {
332                case AML_SCOPE_OP:
333                case AML_ALIAS_OP:
334
335                    break;
336
337                default:
338
339                    if (Op->Asl.ExternalName)
340                    {
341                        LsFlushListingBuffer (FileId);
342                        FlPrintFile (FileId, "    };\n");
343                    }
344                    break;
345                }
346                break;
347
348            default:
349
350                /* Don't care about other objects */
351
352                break;
353            }
354            break;
355        }
356    }
357
358    /* These cases do not have a corresponding AML opcode */
359
360    switch (Op->Asl.ParseOpcode)
361    {
362    case PARSEOP_DEFINITIONBLOCK:
363
364        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
365
366        /* Use the table Signature and TableId to build a unique name */
367
368        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
369        {
370            FlPrintFile (FileId,
371                "%s_%s_Header \\\n",
372                Gbl_TableSignature, Gbl_TableId);
373        }
374        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
375        {
376            FlPrintFile (FileId,
377                "    unsigned char    %s_%s_Header [] =\n    {\n",
378                Gbl_TableSignature, Gbl_TableId);
379        }
380        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
381        {
382            FlPrintFile (FileId,
383                "extrn %s_%s_Header : byte\n",
384                Gbl_TableSignature, Gbl_TableId);
385        }
386        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
387        {
388            FlPrintFile (FileId,
389                "extern unsigned char    %s_%s_Header [];\n",
390                Gbl_TableSignature, Gbl_TableId);
391        }
392        return;
393
394
395    case PARSEOP_METHODCALL:
396
397        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
398            FileId);
399        return;
400
401
402    case PARSEOP_INCLUDE:
403
404        /* Flush everything up to and including the include source line */
405
406        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
407            FileId);
408
409        /* Create a new listing node and push it */
410
411        LsPushNode (Op->Asl.Child->Asl.Value.String);
412        return;
413
414
415    case PARSEOP_INCLUDE_END:
416
417        /* Flush out the rest of the include file */
418
419        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
420            FileId);
421
422        /* Pop off this listing node and go back to the parent file */
423
424        (void) LsPopNode ();
425        return;
426
427
428    case PARSEOP_DEFAULT_ARG:
429
430        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
431        {
432            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
433                FileId);
434        }
435        return;
436
437
438    default:
439
440        /* All other opcodes have an AML opcode */
441
442        break;
443    }
444
445    /*
446     * Otherwise, we look at the AML opcode because we can
447     * switch on the opcode type, getting an entire class
448     * at once
449     */
450    switch (OpClass)
451    {
452    case AML_CLASS_ARGUMENT:       /* argument type only */
453    case AML_CLASS_INTERNAL:
454
455        break;
456
457    case AML_CLASS_NAMED_OBJECT:
458
459        switch (Op->Asl.AmlOpcode)
460        {
461        case AML_FIELD_OP:
462        case AML_INDEX_FIELD_OP:
463        case AML_BANK_FIELD_OP:
464            /*
465             * For fields, we want to dump all the AML after the
466             * entire definition
467             */
468            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
469                FileId);
470            break;
471
472        case AML_NAME_OP:
473
474            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
475            {
476                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
477                    FileId);
478            }
479            else
480            {
481                /*
482                 * For fields, we want to dump all the AML after the
483                 * entire definition
484                 */
485                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
486                    FileId);
487            }
488            break;
489
490        default:
491
492            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
493                FileId);
494            break;
495        }
496
497        switch (Op->Asl.AmlOpcode)
498        {
499        case AML_SCOPE_OP:
500        case AML_ALIAS_OP:
501
502            /* These opcodes do not declare a new object, ignore them */
503
504            break;
505
506        default:
507
508            /* All other named object opcodes come here */
509
510            switch (FileId)
511            {
512            case ASL_FILE_ASM_SOURCE_OUTPUT:
513            case ASL_FILE_C_SOURCE_OUTPUT:
514            case ASL_FILE_ASM_INCLUDE_OUTPUT:
515            case ASL_FILE_C_INCLUDE_OUTPUT:
516                /*
517                 * For named objects, we will create a valid symbol so that the
518                 * AML code can be referenced from C or ASM
519                 */
520                if (Op->Asl.ExternalName)
521                {
522                    /* Get the full pathname associated with this node */
523
524                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
525                    Length = strlen (Pathname);
526                    if (Length >= 4)
527                    {
528                        /* Convert all dots in the path to underscores */
529
530                        for (i = 0; i < Length; i++)
531                        {
532                            if (Pathname[i] == '.')
533                            {
534                                Pathname[i] = '_';
535                            }
536                        }
537
538                        /* Create the appropriate symbol in the output file */
539
540                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
541                        {
542                            FlPrintFile (FileId,
543                                "%s_%s_%s  \\\n",
544                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
545                        }
546                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
547                        {
548                            FlPrintFile (FileId,
549                                "    unsigned char    %s_%s_%s [] =\n    {\n",
550                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
551                        }
552                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
553                        {
554                            FlPrintFile (FileId,
555                                "extrn %s_%s_%s : byte\n",
556                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
557                        }
558                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
559                        {
560                            FlPrintFile (FileId,
561                                "extern unsigned char    %s_%s_%s [];\n",
562                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
563                        }
564                    }
565                    ACPI_FREE (Pathname);
566                }
567                break;
568
569            default:
570
571                /* Nothing to do for listing file */
572
573                break;
574            }
575        }
576        break;
577
578    case AML_CLASS_EXECUTE:
579    case AML_CLASS_CREATE:
580    default:
581
582        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
583            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
584        {
585            return;
586        }
587
588        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
589            FileId);
590        break;
591
592    case AML_CLASS_UNKNOWN:
593
594        break;
595    }
596}
597
598
599/*******************************************************************************
600 *
601 * FUNCTION:    LsFinishSourceListing
602 *
603 * PARAMETERS:  FileId          - ID of current listing file.
604 *
605 * RETURN:      None
606 *
607 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
608 *              listing buffer, and flush out any remaining lines in the
609 *              source input file.
610 *
611 ******************************************************************************/
612
613static void
614LsFinishSourceListing (
615    UINT32                  FileId)
616{
617
618    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
619        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
620    {
621        return;
622    }
623
624    LsFlushListingBuffer (FileId);
625    Gbl_CurrentAmlOffset = 0;
626
627    /* Flush any remaining text in the source file */
628
629    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
630    {
631        FlPrintFile (FileId, "    /*\n");
632    }
633
634    while (LsWriteOneSourceLine (FileId))
635    { ; }
636
637    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
638    {
639        FlPrintFile (FileId, "\n     */\n    };\n");
640    }
641
642    FlPrintFile (FileId, "\n");
643
644    if (FileId == ASL_FILE_LISTING_OUTPUT)
645    {
646        /* Print a summary of the compile exceptions */
647
648        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
649        AePrintErrorLog (FileId);
650        FlPrintFile (FileId, "\n");
651        UtDisplaySummary (FileId);
652        FlPrintFile (FileId, "\n");
653    }
654}
655