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