asllisting.c revision 249112
1/******************************************************************************
2 *
3 * Module Name: asllisting - Listing file generation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, 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        /* Offset table file has a special header and footer */
161
162        LsDoOffsetTableHeader (FileId);
163
164        TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlOffsetWalk,
165            NULL, (void *) ACPI_TO_POINTER (FileId));
166        LsDoOffsetTableFooter (FileId);
167        return;
168    }
169
170    /* Process all parse nodes */
171
172    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk,
173        NULL, (void *) ACPI_TO_POINTER (FileId));
174
175    /* Final processing */
176
177    LsFinishSourceListing (FileId);
178}
179
180
181/*******************************************************************************
182 *
183 * FUNCTION:    LsAmlListingWalk
184 *
185 * PARAMETERS:  ASL_WALK_CALLBACK
186 *
187 * RETURN:      Status
188 *
189 * DESCRIPTION: Process one node during a listing file generation.
190 *
191 ******************************************************************************/
192
193static ACPI_STATUS
194LsAmlListingWalk (
195    ACPI_PARSE_OBJECT       *Op,
196    UINT32                  Level,
197    void                    *Context)
198{
199    UINT8                   FileByte;
200    UINT32                  i;
201    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
202
203
204    LsWriteNodeToListing (Op, FileId);
205
206    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
207    {
208        /* Buffer is a resource template, don't dump the data all at once */
209
210        return (AE_OK);
211    }
212
213    /* Write the hex bytes to the listing file(s) (if requested) */
214
215    for (i = 0; i < Op->Asl.FinalAmlLength; i++)
216    {
217        if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
218        {
219            FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
220            AslAbort ();
221        }
222        LsWriteListingHexBytes (&FileByte, 1, FileId);
223    }
224
225    return (AE_OK);
226}
227
228
229/*******************************************************************************
230 *
231 * FUNCTION:    LsDumpParseTree, LsTreeWriteWalk
232 *
233 * PARAMETERS:  None
234 *
235 * RETURN:      None
236 *
237 * DESCRIPTION: Dump entire parse tree, for compiler debug only
238 *
239 ******************************************************************************/
240
241void
242LsDumpParseTree (
243    void)
244{
245
246    if (!Gbl_DebugFlag)
247    {
248        return;
249    }
250
251    DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
252    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
253        LsTreeWriteWalk, NULL, NULL);
254}
255
256
257static ACPI_STATUS
258LsTreeWriteWalk (
259    ACPI_PARSE_OBJECT       *Op,
260    UINT32                  Level,
261    void                    *Context)
262{
263
264    /* Debug output */
265
266    DbgPrint (ASL_TREE_OUTPUT,
267        "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
268    UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
269
270    DbgPrint (ASL_TREE_OUTPUT, "\n");
271    return (AE_OK);
272}
273
274
275/*******************************************************************************
276 *
277 * FUNCTION:    LsWriteNodeToListing
278 *
279 * PARAMETERS:  Op              - Parse node to write to the listing file.
280 *              FileId          - ID of current listing file
281 *
282 * RETURN:      None.
283 *
284 * DESCRIPTION: Write "a node" to the listing file. This means to
285 *              1) Write out all of the source text associated with the node
286 *              2) Write out all of the AML bytes associated with the node
287 *              3) Write any compiler exceptions associated with the node
288 *
289 ******************************************************************************/
290
291static void
292LsWriteNodeToListing (
293    ACPI_PARSE_OBJECT       *Op,
294    UINT32                  FileId)
295{
296    const ACPI_OPCODE_INFO  *OpInfo;
297    UINT32                  OpClass;
298    char                    *Pathname;
299    UINT32                  Length;
300    UINT32                  i;
301
302
303    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
304    OpClass = OpInfo->Class;
305
306    /* TBD: clean this up with a single flag that says:
307     * I start a named output block
308     */
309    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
310    {
311        switch (Op->Asl.ParseOpcode)
312        {
313        case PARSEOP_DEFINITIONBLOCK:
314        case PARSEOP_METHODCALL:
315        case PARSEOP_INCLUDE:
316        case PARSEOP_INCLUDE_END:
317        case PARSEOP_DEFAULT_ARG:
318
319            break;
320
321        default:
322            switch (OpClass)
323            {
324            case AML_CLASS_NAMED_OBJECT:
325                switch (Op->Asl.AmlOpcode)
326                {
327                case AML_SCOPE_OP:
328                case AML_ALIAS_OP:
329                    break;
330
331                default:
332                    if (Op->Asl.ExternalName)
333                    {
334                        LsFlushListingBuffer (FileId);
335                        FlPrintFile (FileId, "    };\n");
336                    }
337                    break;
338                }
339                break;
340
341            default:
342                /* Don't care about other objects */
343                break;
344            }
345            break;
346        }
347    }
348
349    /* These cases do not have a corresponding AML opcode */
350
351    switch (Op->Asl.ParseOpcode)
352    {
353    case PARSEOP_DEFINITIONBLOCK:
354
355        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
356
357        /* Use the table Signature and TableId to build a unique name */
358
359        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
360        {
361            FlPrintFile (FileId,
362                "%s_%s_Header \\\n",
363                Gbl_TableSignature, Gbl_TableId);
364        }
365        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
366        {
367            FlPrintFile (FileId,
368                "    unsigned char    %s_%s_Header [] =\n    {\n",
369                Gbl_TableSignature, Gbl_TableId);
370        }
371        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
372        {
373            FlPrintFile (FileId,
374                "extrn %s_%s_Header : byte\n",
375                Gbl_TableSignature, Gbl_TableId);
376        }
377        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
378        {
379            FlPrintFile (FileId,
380                "extern unsigned char    %s_%s_Header [];\n",
381                Gbl_TableSignature, Gbl_TableId);
382        }
383        return;
384
385
386    case PARSEOP_METHODCALL:
387
388        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
389            FileId);
390        return;
391
392
393    case PARSEOP_INCLUDE:
394
395        /* Flush everything up to and including the include source line */
396
397        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
398            FileId);
399
400        /* Create a new listing node and push it */
401
402        LsPushNode (Op->Asl.Child->Asl.Value.String);
403        return;
404
405
406    case PARSEOP_INCLUDE_END:
407
408        /* Flush out the rest of the include file */
409
410        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
411            FileId);
412
413        /* Pop off this listing node and go back to the parent file */
414
415        (void) LsPopNode ();
416        return;
417
418
419    case PARSEOP_DEFAULT_ARG:
420
421        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
422        {
423            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
424                FileId);
425        }
426        return;
427
428
429    default:
430        /* All other opcodes have an AML opcode */
431        break;
432    }
433
434    /*
435     * Otherwise, we look at the AML opcode because we can
436     * switch on the opcode type, getting an entire class
437     * at once
438     */
439    switch (OpClass)
440    {
441    case AML_CLASS_ARGUMENT:       /* argument type only */
442    case AML_CLASS_INTERNAL:
443
444        break;
445
446
447    case AML_CLASS_NAMED_OBJECT:
448
449        switch (Op->Asl.AmlOpcode)
450        {
451        case AML_FIELD_OP:
452        case AML_INDEX_FIELD_OP:
453        case AML_BANK_FIELD_OP:
454
455            /*
456             * For fields, we want to dump all the AML after the
457             * entire definition
458             */
459            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
460                FileId);
461            break;
462
463        case AML_NAME_OP:
464
465            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
466            {
467                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
468                    FileId);
469            }
470            else
471            {
472                /*
473                 * For fields, we want to dump all the AML after the
474                 * entire definition
475                 */
476                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
477                    FileId);
478            }
479            break;
480
481        default:
482            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
483                FileId);
484            break;
485        }
486
487        switch (Op->Asl.AmlOpcode)
488        {
489        case AML_SCOPE_OP:
490        case AML_ALIAS_OP:
491
492            /* These opcodes do not declare a new object, ignore them */
493
494            break;
495
496        default:
497
498            /* All other named object opcodes come here */
499
500            switch (FileId)
501            {
502            case ASL_FILE_ASM_SOURCE_OUTPUT:
503            case ASL_FILE_C_SOURCE_OUTPUT:
504            case ASL_FILE_ASM_INCLUDE_OUTPUT:
505            case ASL_FILE_C_INCLUDE_OUTPUT:
506
507                /*
508                 * For named objects, we will create a valid symbol so that the
509                 * AML code can be referenced from C or ASM
510                 */
511                if (Op->Asl.ExternalName)
512                {
513                    /* Get the full pathname associated with this node */
514
515                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
516                    Length = strlen (Pathname);
517                    if (Length >= 4)
518                    {
519                        /* Convert all dots in the path to underscores */
520
521                        for (i = 0; i < Length; i++)
522                        {
523                            if (Pathname[i] == '.')
524                            {
525                                Pathname[i] = '_';
526                            }
527                        }
528
529                        /* Create the appropriate symbol in the output file */
530
531                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
532                        {
533                            FlPrintFile (FileId,
534                                "%s_%s_%s  \\\n",
535                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
536                        }
537                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
538                        {
539                            FlPrintFile (FileId,
540                                "    unsigned char    %s_%s_%s [] =\n    {\n",
541                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
542                        }
543                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
544                        {
545                            FlPrintFile (FileId,
546                                "extrn %s_%s_%s : byte\n",
547                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
548                        }
549                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
550                        {
551                            FlPrintFile (FileId,
552                                "extern unsigned char    %s_%s_%s [];\n",
553                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
554                        }
555                    }
556                    ACPI_FREE (Pathname);
557                }
558                break;
559
560            default:
561                /* Nothing to do for listing file */
562                break;
563            }
564        }
565        break;
566
567    case AML_CLASS_EXECUTE:
568    case AML_CLASS_CREATE:
569    default:
570
571        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
572            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
573        {
574            return;
575        }
576
577        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
578            FileId);
579        break;
580
581    case AML_CLASS_UNKNOWN:
582        break;
583    }
584}
585
586
587/*******************************************************************************
588 *
589 * FUNCTION:    LsFinishSourceListing
590 *
591 * PARAMETERS:  FileId          - ID of current listing file.
592 *
593 * RETURN:      None
594 *
595 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
596 *              listing buffer, and flush out any remaining lines in the
597 *              source input file.
598 *
599 ******************************************************************************/
600
601static void
602LsFinishSourceListing (
603    UINT32                  FileId)
604{
605
606    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
607        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
608    {
609        return;
610    }
611
612    LsFlushListingBuffer (FileId);
613    Gbl_CurrentAmlOffset = 0;
614
615    /* Flush any remaining text in the source file */
616
617    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
618    {
619        FlPrintFile (FileId, "    /*\n");
620    }
621
622    while (LsWriteOneSourceLine (FileId))
623    { ; }
624
625    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
626    {
627        FlPrintFile (FileId, "\n     */\n    };\n");
628    }
629
630    FlPrintFile (FileId, "\n");
631
632    if (FileId == ASL_FILE_LISTING_OUTPUT)
633    {
634        /* Print a summary of the compile exceptions */
635
636        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
637        AePrintErrorLog (FileId);
638        FlPrintFile (FileId, "\n");
639        UtDisplaySummary (FileId);
640        FlPrintFile (FileId, "\n");
641    }
642}
643