]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/compiler/asllisting.c
Import ACPICA 20130328.
[FreeBSD/FreeBSD.git] / source / 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 "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 #include "acparser.h"
48 #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 }