]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/compiler/asllisting.c
Import tzdata 2016j
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / compiler / asllisting.c
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
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         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
195 static ACPI_STATUS
196 LsAmlListingWalk (
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
250 void
251 LsDumpParseTree (
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
270 static ACPI_STATUS
271 LsTreeWriteWalk (
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
362 static void
363 LsWriteNodeToListing (
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
704 static void
705 LsFinishSourceListing (
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 }