asllisting.c revision 281687
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) Flags %8.8X",
274        Op->Asl.ParseOpcode, Op->Asl.CompileFlags);
275    TrPrintNodeCompileFlags (Op->Asl.CompileFlags);
276    DbgPrint (ASL_TREE_OUTPUT, "\n");
277    return (AE_OK);
278}
279
280
281/*******************************************************************************
282 *
283 * FUNCTION:    LsWriteNodeToListing
284 *
285 * PARAMETERS:  Op              - Parse node to write to the listing file.
286 *              FileId          - ID of current listing file
287 *
288 * RETURN:      None.
289 *
290 * DESCRIPTION: Write "a node" to the listing file. This means to
291 *              1) Write out all of the source text associated with the node
292 *              2) Write out all of the AML bytes associated with the node
293 *              3) Write any compiler exceptions associated with the node
294 *
295 ******************************************************************************/
296
297static void
298LsWriteNodeToListing (
299    ACPI_PARSE_OBJECT       *Op,
300    UINT32                  FileId)
301{
302    const ACPI_OPCODE_INFO  *OpInfo;
303    UINT32                  OpClass;
304    char                    *Pathname;
305    UINT32                  Length;
306    UINT32                  i;
307
308
309    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
310    OpClass = OpInfo->Class;
311
312    /* TBD: clean this up with a single flag that says:
313     * I start a named output block
314     */
315    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
316    {
317        switch (Op->Asl.ParseOpcode)
318        {
319        case PARSEOP_DEFINITIONBLOCK:
320        case PARSEOP_METHODCALL:
321        case PARSEOP_INCLUDE:
322        case PARSEOP_INCLUDE_END:
323        case PARSEOP_DEFAULT_ARG:
324
325            break;
326
327        default:
328
329            switch (OpClass)
330            {
331            case AML_CLASS_NAMED_OBJECT:
332
333                switch (Op->Asl.AmlOpcode)
334                {
335                case AML_SCOPE_OP:
336                case AML_ALIAS_OP:
337
338                    break;
339
340                default:
341
342                    if (Op->Asl.ExternalName)
343                    {
344                        LsFlushListingBuffer (FileId);
345                        FlPrintFile (FileId, "    };\n");
346                    }
347                    break;
348                }
349                break;
350
351            default:
352
353                /* Don't care about other objects */
354
355                break;
356            }
357            break;
358        }
359    }
360
361    /* These cases do not have a corresponding AML opcode */
362
363    switch (Op->Asl.ParseOpcode)
364    {
365    case PARSEOP_DEFINITIONBLOCK:
366
367        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
368
369        /* Use the table Signature and TableId to build a unique name */
370
371        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
372        {
373            FlPrintFile (FileId,
374                "%s_%s_Header \\\n",
375                Gbl_TableSignature, Gbl_TableId);
376        }
377        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
378        {
379            FlPrintFile (FileId,
380                "    unsigned char    %s_%s_Header [] =\n    {\n",
381                Gbl_TableSignature, Gbl_TableId);
382        }
383        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
384        {
385            FlPrintFile (FileId,
386                "extrn %s_%s_Header : byte\n",
387                Gbl_TableSignature, Gbl_TableId);
388        }
389        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
390        {
391            FlPrintFile (FileId,
392                "extern unsigned char    %s_%s_Header [];\n",
393                Gbl_TableSignature, Gbl_TableId);
394        }
395        return;
396
397
398    case PARSEOP_METHODCALL:
399
400        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
401            FileId);
402        return;
403
404
405    case PARSEOP_INCLUDE:
406
407        /* Flush everything up to and including the include source line */
408
409        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
410            FileId);
411
412        /* Create a new listing node and push it */
413
414        LsPushNode (Op->Asl.Child->Asl.Value.String);
415        return;
416
417
418    case PARSEOP_INCLUDE_END:
419
420        /* Flush out the rest of the include file */
421
422        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
423            FileId);
424
425        /* Pop off this listing node and go back to the parent file */
426
427        (void) LsPopNode ();
428        return;
429
430
431    case PARSEOP_DEFAULT_ARG:
432
433        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
434        {
435            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
436                FileId);
437        }
438        return;
439
440
441    default:
442
443        /* All other opcodes have an AML opcode */
444
445        break;
446    }
447
448    /*
449     * Otherwise, we look at the AML opcode because we can
450     * switch on the opcode type, getting an entire class
451     * at once
452     */
453    switch (OpClass)
454    {
455    case AML_CLASS_ARGUMENT:       /* argument type only */
456    case AML_CLASS_INTERNAL:
457
458        break;
459
460    case AML_CLASS_NAMED_OBJECT:
461
462        switch (Op->Asl.AmlOpcode)
463        {
464        case AML_FIELD_OP:
465        case AML_INDEX_FIELD_OP:
466        case AML_BANK_FIELD_OP:
467            /*
468             * For fields, we want to dump all the AML after the
469             * entire definition
470             */
471            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
472                FileId);
473            break;
474
475        case AML_NAME_OP:
476
477            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
478            {
479                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
480                    FileId);
481            }
482            else
483            {
484                /*
485                 * For fields, we want to dump all the AML after the
486                 * entire definition
487                 */
488                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
489                    FileId);
490            }
491            break;
492
493        default:
494
495            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
496                FileId);
497            break;
498        }
499
500        switch (Op->Asl.AmlOpcode)
501        {
502        case AML_SCOPE_OP:
503        case AML_ALIAS_OP:
504
505            /* These opcodes do not declare a new object, ignore them */
506
507            break;
508
509        default:
510
511            /* All other named object opcodes come here */
512
513            switch (FileId)
514            {
515            case ASL_FILE_ASM_SOURCE_OUTPUT:
516            case ASL_FILE_C_SOURCE_OUTPUT:
517            case ASL_FILE_ASM_INCLUDE_OUTPUT:
518            case ASL_FILE_C_INCLUDE_OUTPUT:
519                /*
520                 * For named objects, we will create a valid symbol so that the
521                 * AML code can be referenced from C or ASM
522                 */
523                if (Op->Asl.ExternalName)
524                {
525                    /* Get the full pathname associated with this node */
526
527                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
528                    Length = strlen (Pathname);
529                    if (Length >= 4)
530                    {
531                        /* Convert all dots in the path to underscores */
532
533                        for (i = 0; i < Length; i++)
534                        {
535                            if (Pathname[i] == '.')
536                            {
537                                Pathname[i] = '_';
538                            }
539                        }
540
541                        /* Create the appropriate symbol in the output file */
542
543                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
544                        {
545                            FlPrintFile (FileId,
546                                "%s_%s_%s  \\\n",
547                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
548                        }
549                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
550                        {
551                            FlPrintFile (FileId,
552                                "    unsigned char    %s_%s_%s [] =\n    {\n",
553                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
554                        }
555                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
556                        {
557                            FlPrintFile (FileId,
558                                "extrn %s_%s_%s : byte\n",
559                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
560                        }
561                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
562                        {
563                            FlPrintFile (FileId,
564                                "extern unsigned char    %s_%s_%s [];\n",
565                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
566                        }
567                    }
568                    ACPI_FREE (Pathname);
569                }
570                break;
571
572            default:
573
574                /* Nothing to do for listing file */
575
576                break;
577            }
578        }
579        break;
580
581    case AML_CLASS_EXECUTE:
582    case AML_CLASS_CREATE:
583    default:
584
585        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
586            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
587        {
588            return;
589        }
590
591        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
592            FileId);
593        break;
594
595    case AML_CLASS_UNKNOWN:
596
597        break;
598    }
599}
600
601
602/*******************************************************************************
603 *
604 * FUNCTION:    LsFinishSourceListing
605 *
606 * PARAMETERS:  FileId          - ID of current listing file.
607 *
608 * RETURN:      None
609 *
610 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
611 *              listing buffer, and flush out any remaining lines in the
612 *              source input file.
613 *
614 ******************************************************************************/
615
616static void
617LsFinishSourceListing (
618    UINT32                  FileId)
619{
620
621    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
622        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
623    {
624        return;
625    }
626
627    LsFlushListingBuffer (FileId);
628    Gbl_CurrentAmlOffset = 0;
629
630    /* Flush any remaining text in the source file */
631
632    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
633    {
634        FlPrintFile (FileId, "    /*\n");
635    }
636
637    while (LsWriteOneSourceLine (FileId))
638    { ; }
639
640    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
641    {
642        FlPrintFile (FileId, "\n     */\n    };\n");
643    }
644
645    FlPrintFile (FileId, "\n");
646
647    if (FileId == ASL_FILE_LISTING_OUTPUT)
648    {
649        /* Print a summary of the compile exceptions */
650
651        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
652        AePrintErrorLog (FileId);
653        FlPrintFile (FileId, "\n");
654        UtDisplaySummary (FileId);
655        FlPrintFile (FileId, "\n");
656    }
657}
658