asllisting.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: asllisting - Listing file generation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include "aslcompiler.y.h"
46#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 (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
167            LsAmlOffsetWalk, NULL, (void *) ACPI_TO_POINTER (FileId));
168        LsDoOffsetTableFooter (FileId);
169        return;
170    }
171
172    /* Process all parse nodes */
173
174    TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
175        LsAmlListingWalk, 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    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
216        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
217    {
218        return (AE_OK);
219    }
220
221    /* Write the hex bytes to the listing file(s) (if requested) */
222
223    for (i = 0; i < Op->Asl.FinalAmlLength; i++)
224    {
225        if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
226        {
227            FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
228            AslAbort ();
229        }
230
231        LsWriteListingHexBytes (&FileByte, 1, FileId);
232    }
233
234    return (AE_OK);
235}
236
237
238/*******************************************************************************
239 *
240 * FUNCTION:    LsDumpParseTree, LsTreeWriteWalk
241 *
242 * PARAMETERS:  None
243 *
244 * RETURN:      None
245 *
246 * DESCRIPTION: Dump entire parse tree, for compiler debug only
247 *
248 ******************************************************************************/
249
250void
251LsDumpParseTree (
252    void)
253{
254
255    if (!Gbl_DebugFlag)
256    {
257        return;
258    }
259
260    DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
261    DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1);
262
263    TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
264        LsTreeWriteWalk, NULL, NULL);
265
266    DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1);
267}
268
269
270static ACPI_STATUS
271LsTreeWriteWalk (
272    ACPI_PARSE_OBJECT       *Op,
273    UINT32                  Level,
274    void                    *Context)
275{
276
277    /* Dump ParseOp name and possible value */
278
279    switch (Op->Asl.ParseOpcode)
280    {
281        case PARSEOP_NAMESEG:
282        case PARSEOP_NAMESTRING:
283        case PARSEOP_METHODCALL:
284        case PARSEOP_STRING_LITERAL:
285
286        UtDumpStringOp (Op, Level);
287        break;
288
289    case PARSEOP_BYTECONST:
290
291        UtDumpIntegerOp (Op, Level, 2);
292        break;
293
294    case PARSEOP_WORDCONST:
295    case PARSEOP_PACKAGE_LENGTH:
296
297        UtDumpIntegerOp (Op, Level, 4);
298        break;
299
300    case PARSEOP_DWORDCONST:
301    case PARSEOP_EISAID:
302
303        UtDumpIntegerOp (Op, Level, 8);
304        break;
305
306    case PARSEOP_QWORDCONST:
307    case PARSEOP_INTEGER:
308    case PARSEOP_ONE:
309    case PARSEOP_ZERO:
310    case PARSEOP_ONES:
311
312        UtDumpIntegerOp (Op, Level, 16);
313        break;
314
315    case PARSEOP_INCLUDE:
316
317        DbgPrint (ASL_TREE_OUTPUT,
318            "Open: %s\n", Op->Asl.Value.String);
319        return (AE_OK);
320
321    case PARSEOP_INCLUDE_END:
322
323        DbgPrint (ASL_TREE_OUTPUT,
324            "Close: %s\n", Op->Asl.Filename);
325        return (AE_OK);
326
327    default:
328
329        UtDumpBasicOp (Op, Level);
330        break;
331    }
332
333    /* Dump the remaining data */
334
335    DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_DEBUG1,
336        Op->Asl.ParseOpcode, Op->Asl.CompileFlags,
337        Op->Asl.LineNumber, Op->Asl.EndLine,
338        Op->Asl.LogicalLineNumber, Op->Asl.EndLogicalLine);
339
340    TrPrintNodeCompileFlags (Op->Asl.CompileFlags);
341    DbgPrint (ASL_TREE_OUTPUT, "\n");
342    return (AE_OK);
343}
344
345
346/*******************************************************************************
347 *
348 * FUNCTION:    LsWriteNodeToListing
349 *
350 * PARAMETERS:  Op              - Parse node to write to the listing file.
351 *              FileId          - ID of current listing file
352 *
353 * RETURN:      None.
354 *
355 * DESCRIPTION: Write "a node" to the listing file. This means to
356 *              1) Write out all of the source text associated with the node
357 *              2) Write out all of the AML bytes associated with the node
358 *              3) Write any compiler exceptions associated with the node
359 *
360 ******************************************************************************/
361
362static void
363LsWriteNodeToListing (
364    ACPI_PARSE_OBJECT       *Op,
365    UINT32                  FileId)
366{
367    const ACPI_OPCODE_INFO  *OpInfo;
368    UINT32                  OpClass;
369    char                    *Pathname;
370    UINT32                  Length;
371    UINT32                  i;
372
373
374    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
375    OpClass = OpInfo->Class;
376
377    /* TBD: clean this up with a single flag that says:
378     * I start a named output block
379     */
380    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
381    {
382        switch (Op->Asl.ParseOpcode)
383        {
384        case PARSEOP_DEFINITION_BLOCK:
385        case PARSEOP_METHODCALL:
386        case PARSEOP_INCLUDE:
387        case PARSEOP_INCLUDE_END:
388        case PARSEOP_DEFAULT_ARG:
389
390            break;
391
392        default:
393
394            switch (OpClass)
395            {
396            case AML_CLASS_NAMED_OBJECT:
397
398                switch (Op->Asl.AmlOpcode)
399                {
400                case AML_SCOPE_OP:
401                case AML_ALIAS_OP:
402
403                    break;
404
405                default:
406
407                    if (Op->Asl.ExternalName)
408                    {
409                        LsFlushListingBuffer (FileId);
410                        FlPrintFile (FileId, "    };\n");
411                    }
412                    break;
413                }
414                break;
415
416            default:
417
418                /* Don't care about other objects */
419
420                break;
421            }
422            break;
423        }
424    }
425
426    /* These cases do not have a corresponding AML opcode */
427
428    switch (Op->Asl.ParseOpcode)
429    {
430    case PARSEOP_DEFINITION_BLOCK:
431
432        /* Always start a definition block at AML offset zero */
433
434        Gbl_CurrentAmlOffset = 0;
435        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
436
437        /* Use the table Signature and TableId to build a unique name */
438
439        switch (FileId)
440        {
441        case ASL_FILE_ASM_SOURCE_OUTPUT:
442
443            FlPrintFile (FileId,
444                "%s_%s_Header \\\n",
445                Gbl_TableSignature, Gbl_TableId);
446            break;
447
448        case ASL_FILE_C_SOURCE_OUTPUT:
449
450            FlPrintFile (FileId,
451                "    unsigned char    %s_%s_Header [] =\n    {\n",
452                Gbl_TableSignature, Gbl_TableId);
453            break;
454
455        case ASL_FILE_ASM_INCLUDE_OUTPUT:
456
457            FlPrintFile (FileId,
458                "extrn %s_%s_Header : byte\n",
459                Gbl_TableSignature, Gbl_TableId);
460            break;
461
462        case ASL_FILE_C_INCLUDE_OUTPUT:
463
464            FlPrintFile (FileId,
465                "extern unsigned char    %s_%s_Header [];\n",
466                Gbl_TableSignature, Gbl_TableId);
467            break;
468
469        default:
470            break;
471        }
472
473        return;
474
475
476    case PARSEOP_METHODCALL:
477
478        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
479            FileId);
480        return;
481
482
483    case PARSEOP_INCLUDE:
484
485        /* Flush everything up to and including the include source line */
486
487        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
488            FileId);
489
490        /* Create a new listing node and push it */
491
492        LsPushNode (Op->Asl.Value.String);
493        return;
494
495
496    case PARSEOP_INCLUDE_END:
497
498        /* Flush out the rest of the include file */
499
500        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
501            FileId);
502
503        /* Pop off this listing node and go back to the parent file */
504
505        (void) LsPopNode ();
506        return;
507
508
509    case PARSEOP_DEFAULT_ARG:
510
511        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
512        {
513            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
514                FileId);
515        }
516        return;
517
518
519    default:
520
521        /* All other opcodes have an AML opcode */
522
523        break;
524    }
525
526    /*
527     * Otherwise, we look at the AML opcode because we can
528     * switch on the opcode type, getting an entire class
529     * at once
530     */
531    switch (OpClass)
532    {
533    case AML_CLASS_ARGUMENT:       /* argument type only */
534    case AML_CLASS_INTERNAL:
535
536        break;
537
538    case AML_CLASS_NAMED_OBJECT:
539
540        switch (Op->Asl.AmlOpcode)
541        {
542        case AML_FIELD_OP:
543        case AML_INDEX_FIELD_OP:
544        case AML_BANK_FIELD_OP:
545            /*
546             * For fields, we want to dump all the AML after the
547             * entire definition
548             */
549            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
550                FileId);
551            break;
552
553        case AML_NAME_OP:
554
555            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
556            {
557                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
558                    FileId);
559            }
560            else
561            {
562                /*
563                 * For fields, we want to dump all the AML after the
564                 * entire definition
565                 */
566                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
567                    FileId);
568            }
569            break;
570
571        default:
572
573            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
574                FileId);
575            break;
576        }
577
578        switch (Op->Asl.AmlOpcode)
579        {
580        case AML_SCOPE_OP:
581        case AML_ALIAS_OP:
582
583            /* These opcodes do not declare a new object, ignore them */
584
585            break;
586
587        default:
588
589            /* All other named object opcodes come here */
590
591            switch (FileId)
592            {
593            case ASL_FILE_ASM_SOURCE_OUTPUT:
594            case ASL_FILE_C_SOURCE_OUTPUT:
595            case ASL_FILE_ASM_INCLUDE_OUTPUT:
596            case ASL_FILE_C_INCLUDE_OUTPUT:
597                /*
598                 * For named objects, we will create a valid symbol so that the
599                 * AML code can be referenced from C or ASM
600                 */
601                if (Op->Asl.ExternalName)
602                {
603                    /* Get the full pathname associated with this node */
604
605                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
606                    Length = strlen (Pathname);
607                    if (Length >= 4)
608                    {
609                        /* Convert all dots in the path to underscores */
610
611                        for (i = 0; i < Length; i++)
612                        {
613                            if (Pathname[i] == '.')
614                            {
615                                Pathname[i] = '_';
616                            }
617                        }
618
619                        /* Create the appropriate symbol in the output file */
620
621                        switch (FileId)
622                        {
623                        case ASL_FILE_ASM_SOURCE_OUTPUT:
624
625                            FlPrintFile (FileId,
626                                "%s_%s_%s  \\\n",
627                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
628                            break;
629
630                        case ASL_FILE_C_SOURCE_OUTPUT:
631
632                            FlPrintFile (FileId,
633                                "    unsigned char    %s_%s_%s [] =\n    {\n",
634                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
635                            break;
636
637                        case ASL_FILE_ASM_INCLUDE_OUTPUT:
638
639                            FlPrintFile (FileId,
640                                "extrn %s_%s_%s : byte\n",
641                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
642                            break;
643
644                        case ASL_FILE_C_INCLUDE_OUTPUT:
645
646                            FlPrintFile (FileId,
647                                "extern unsigned char    %s_%s_%s [];\n",
648                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
649                            break;
650
651                        default:
652                            break;
653                        }
654                    }
655
656                    ACPI_FREE (Pathname);
657                }
658                break;
659
660            default:
661
662                /* Nothing to do for listing file */
663
664                break;
665            }
666        }
667        break;
668
669    case AML_CLASS_EXECUTE:
670    case AML_CLASS_CREATE:
671    default:
672
673        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
674            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
675        {
676            return;
677        }
678
679        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
680            FileId);
681        break;
682
683    case AML_CLASS_UNKNOWN:
684
685        break;
686    }
687}
688
689
690/*******************************************************************************
691 *
692 * FUNCTION:    LsFinishSourceListing
693 *
694 * PARAMETERS:  FileId          - ID of current listing file.
695 *
696 * RETURN:      None
697 *
698 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
699 *              listing buffer, and flush out any remaining lines in the
700 *              source input file.
701 *
702 ******************************************************************************/
703
704static void
705LsFinishSourceListing (
706    UINT32                  FileId)
707{
708
709    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
710        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
711    {
712        return;
713    }
714
715    LsFlushListingBuffer (FileId);
716    Gbl_CurrentAmlOffset = 0;
717
718    /* Flush any remaining text in the source file */
719
720    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
721    {
722        FlPrintFile (FileId, "    /*\n");
723    }
724
725    while (LsWriteOneSourceLine (FileId))
726    { ; }
727
728    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
729    {
730        FlPrintFile (FileId, "\n     */\n    };\n");
731    }
732
733    FlPrintFile (FileId, "\n");
734
735    if (FileId == ASL_FILE_LISTING_OUTPUT)
736    {
737        /* Print a summary of the compile exceptions */
738
739        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
740        AePrintErrorLog (FileId);
741        FlPrintFile (FileId, "\n");
742        UtDisplaySummary (FileId);
743        FlPrintFile (FileId, "\n");
744    }
745}
746