xref: /freebsd-src/sys/contrib/dev/acpica/compiler/asllisting.c (revision ddd5b8e9b4d8957fce018c520657cdfa4ecffad3)
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 
57 static void
58 LsGenerateListing (
59     UINT32                  FileId);
60 
61 static ACPI_STATUS
62 LsAmlListingWalk (
63     ACPI_PARSE_OBJECT       *Op,
64     UINT32                  Level,
65     void                    *Context);
66 
67 static ACPI_STATUS
68 LsTreeWriteWalk (
69     ACPI_PARSE_OBJECT       *Op,
70     UINT32                  Level,
71     void                    *Context);
72 
73 static void
74 LsWriteNodeToListing (
75     ACPI_PARSE_OBJECT       *Op,
76     UINT32                  FileId);
77 
78 static void
79 LsFinishSourceListing (
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 
95 void
96 LsDoListings (
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 
145 static void
146 LsGenerateListing (
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 
193 static ACPI_STATUS
194 LsAmlListingWalk (
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 
241 void
242 LsDumpParseTree (
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 
257 static ACPI_STATUS
258 LsTreeWriteWalk (
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 
291 static void
292 LsWriteNodeToListing (
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 
601 static void
602 LsFinishSourceListing (
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