1118611Snjl/******************************************************************************
2118611Snjl *
3118611Snjl * Module Name: aslcompile - top level compile module
4118611Snjl *
5118611Snjl *****************************************************************************/
6118611Snjl
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9118611Snjl * All rights reserved.
10118611Snjl *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25118611Snjl *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29118611Snjl *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43118611Snjl
44217365Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45246849Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h>
46217365Sjkim
47118611Snjl#include <stdio.h>
48151937Sjkim#include <time.h>
49213806Sjkim#include <contrib/dev/acpica/include/acapps.h>
50118611Snjl
51118611Snjl#define _COMPONENT          ACPI_COMPILER
52118611Snjl        ACPI_MODULE_NAME    ("aslcompile")
53118611Snjl
54243347Sjkim/*
55243347Sjkim * Main parser entry
56243347Sjkim * External is here in case the parser emits the same external in the
57243347Sjkim * generated header. (Newer versions of Bison)
58243347Sjkim */
59243347Sjkimint
60243347SjkimAslCompilerparse(
61243347Sjkim    void);
62243347Sjkim
63151937Sjkim/* Local prototypes */
64118611Snjl
65151937Sjkimstatic void
66151937SjkimCmFlushSourceCode (
67151937Sjkim    void);
68151937Sjkim
69212761Sjkimstatic void
70193529SjkimFlConsumeAnsiComment (
71235945Sjkim    FILE                    *Handle,
72193529Sjkim    ASL_FILE_STATUS         *Status);
73151937Sjkim
74212761Sjkimstatic void
75193529SjkimFlConsumeNewComment (
76235945Sjkim    FILE                    *Handle,
77193529Sjkim    ASL_FILE_STATUS         *Status);
78193529Sjkim
79237412Sjkimstatic void
80237412SjkimCmDumpAllEvents (
81237412Sjkim    void);
82193529Sjkim
83237412Sjkim
84118611Snjl/*******************************************************************************
85118611Snjl *
86118611Snjl * FUNCTION:    AslCompilerSignon
87118611Snjl *
88118611Snjl * PARAMETERS:  FileId      - ID of the output file
89118611Snjl *
90118611Snjl * RETURN:      None
91118611Snjl *
92118611Snjl * DESCRIPTION: Display compiler signon
93118611Snjl *
94118611Snjl ******************************************************************************/
95118611Snjl
96118611Snjlvoid
97118611SnjlAslCompilerSignon (
98118611Snjl    UINT32                  FileId)
99118611Snjl{
100118611Snjl    char                    *Prefix = "";
101213806Sjkim    char                    *UtilityName;
102118611Snjl
103118611Snjl
104151937Sjkim    /* Set line prefix depending on the destination file type */
105151937Sjkim
106118611Snjl    switch (FileId)
107118611Snjl    {
108118611Snjl    case ASL_FILE_ASM_SOURCE_OUTPUT:
109118611Snjl    case ASL_FILE_ASM_INCLUDE_OUTPUT:
110118611Snjl
111118611Snjl        Prefix = "; ";
112118611Snjl        break;
113118611Snjl
114118611Snjl    case ASL_FILE_HEX_OUTPUT:
115118611Snjl
116118611Snjl        if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM)
117118611Snjl        {
118118611Snjl            Prefix = "; ";
119118611Snjl        }
120207344Sjkim        else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
121207344Sjkim                 (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
122118611Snjl        {
123118611Snjl            FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
124118611Snjl            Prefix = " * ";
125118611Snjl        }
126118611Snjl        break;
127118611Snjl
128118611Snjl    case ASL_FILE_C_SOURCE_OUTPUT:
129249112Sjkim    case ASL_FILE_C_OFFSET_OUTPUT:
130118611Snjl    case ASL_FILE_C_INCLUDE_OUTPUT:
131118611Snjl
132118611Snjl        Prefix = " * ";
133118611Snjl        break;
134118611Snjl
135118611Snjl    default:
136250838Sjkim
137118611Snjl        /* No other output types supported */
138250838Sjkim
139118611Snjl        break;
140118611Snjl    }
141118611Snjl
142151937Sjkim    /* Running compiler or disassembler? */
143151937Sjkim
144151937Sjkim    if (Gbl_DisasmFlag)
145151937Sjkim    {
146213806Sjkim        UtilityName = AML_DISASSEMBLER_NAME;
147151937Sjkim    }
148151937Sjkim    else
149151937Sjkim    {
150213806Sjkim        UtilityName = ASL_COMPILER_NAME;
151151937Sjkim    }
152151937Sjkim
153213806Sjkim    /* Compiler signon with copyright */
154151937Sjkim
155213806Sjkim    FlPrintFile (FileId, "%s\n", Prefix);
156213806Sjkim    FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
157118611Snjl}
158118611Snjl
159118611Snjl
160118611Snjl/*******************************************************************************
161118611Snjl *
162118611Snjl * FUNCTION:    AslCompilerFileHeader
163118611Snjl *
164118611Snjl * PARAMETERS:  FileId      - ID of the output file
165118611Snjl *
166118611Snjl * RETURN:      None
167118611Snjl *
168118611Snjl * DESCRIPTION: Header used at the beginning of output files
169118611Snjl *
170118611Snjl ******************************************************************************/
171118611Snjl
172118611Snjlvoid
173118611SnjlAslCompilerFileHeader (
174118611Snjl    UINT32                  FileId)
175118611Snjl{
176118611Snjl    struct tm               *NewTime;
177118611Snjl    time_t                  Aclock;
178118611Snjl    char                    *Prefix = "";
179118611Snjl
180118611Snjl
181151937Sjkim    /* Set line prefix depending on the destination file type */
182151937Sjkim
183118611Snjl    switch (FileId)
184118611Snjl    {
185118611Snjl    case ASL_FILE_ASM_SOURCE_OUTPUT:
186118611Snjl    case ASL_FILE_ASM_INCLUDE_OUTPUT:
187118611Snjl
188118611Snjl        Prefix = "; ";
189118611Snjl        break;
190118611Snjl
191118611Snjl    case ASL_FILE_HEX_OUTPUT:
192118611Snjl
193118611Snjl        if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM)
194118611Snjl        {
195118611Snjl            Prefix = "; ";
196118611Snjl        }
197207344Sjkim        else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
198207344Sjkim                 (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
199118611Snjl        {
200118611Snjl            Prefix = " * ";
201118611Snjl        }
202118611Snjl        break;
203118611Snjl
204118611Snjl    case ASL_FILE_C_SOURCE_OUTPUT:
205249112Sjkim    case ASL_FILE_C_OFFSET_OUTPUT:
206118611Snjl    case ASL_FILE_C_INCLUDE_OUTPUT:
207118611Snjl
208118611Snjl        Prefix = " * ";
209118611Snjl        break;
210118611Snjl
211118611Snjl    default:
212250838Sjkim
213118611Snjl        /* No other output types supported */
214250838Sjkim
215118611Snjl        break;
216118611Snjl    }
217118611Snjl
218118611Snjl    /* Compilation header with timestamp */
219118611Snjl
220118611Snjl    (void) time (&Aclock);
221118611Snjl    NewTime = localtime (&Aclock);
222118611Snjl
223118611Snjl    FlPrintFile (FileId,
224118611Snjl        "%sCompilation of \"%s\" - %s%s\n",
225118611Snjl        Prefix, Gbl_Files[ASL_FILE_INPUT].Filename, asctime (NewTime),
226118611Snjl        Prefix);
227118611Snjl
228118611Snjl    switch (FileId)
229118611Snjl    {
230118611Snjl    case ASL_FILE_C_SOURCE_OUTPUT:
231249112Sjkim    case ASL_FILE_C_OFFSET_OUTPUT:
232118611Snjl    case ASL_FILE_C_INCLUDE_OUTPUT:
233250838Sjkim
234118611Snjl        FlPrintFile (FileId, " */\n");
235118611Snjl        break;
236118611Snjl
237118611Snjl    default:
238250838Sjkim
239118611Snjl        /* Nothing to do for other output types */
240250838Sjkim
241118611Snjl        break;
242118611Snjl    }
243118611Snjl}
244118611Snjl
245118611Snjl
246118611Snjl/*******************************************************************************
247118611Snjl *
248118611Snjl * FUNCTION:    CmFlushSourceCode
249118611Snjl *
250118611Snjl * PARAMETERS:  None
251118611Snjl *
252118611Snjl * RETURN:      None
253118611Snjl *
254118611Snjl * DESCRIPTION: Read in any remaining source code after the parse tree
255118611Snjl *              has been constructed.
256118611Snjl *
257118611Snjl ******************************************************************************/
258118611Snjl
259151937Sjkimstatic void
260151937SjkimCmFlushSourceCode (
261151937Sjkim    void)
262118611Snjl{
263118611Snjl    char                    Buffer;
264118611Snjl
265118611Snjl
266118611Snjl    while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
267118611Snjl    {
268234623Sjkim        AslInsertLineBuffer ((int) Buffer);
269118611Snjl    }
270118611Snjl
271234623Sjkim    AslResetCurrentLineBuffer ();
272118611Snjl}
273118611Snjl
274118611Snjl
275118611Snjl/*******************************************************************************
276118611Snjl *
277167802Sjkim * FUNCTION:    FlConsume*
278167802Sjkim *
279235945Sjkim * PARAMETERS:  Handle              - Open input file
280235945Sjkim *              Status              - File current status struct
281167802Sjkim *
282167802Sjkim * RETURN:      Number of lines consumed
283167802Sjkim *
284167802Sjkim * DESCRIPTION: Step over both types of comment during check for ascii chars
285167802Sjkim *
286167802Sjkim ******************************************************************************/
287167802Sjkim
288212761Sjkimstatic void
289167802SjkimFlConsumeAnsiComment (
290235945Sjkim    FILE                    *Handle,
291167802Sjkim    ASL_FILE_STATUS         *Status)
292167802Sjkim{
293167802Sjkim    UINT8                   Byte;
294167802Sjkim    BOOLEAN                 ClosingComment = FALSE;
295167802Sjkim
296167802Sjkim
297243347Sjkim    while (fread (&Byte, 1, 1, Handle) == 1)
298167802Sjkim    {
299167802Sjkim        /* Scan until comment close is found */
300167802Sjkim
301167802Sjkim        if (ClosingComment)
302167802Sjkim        {
303167802Sjkim            if (Byte == '/')
304167802Sjkim            {
305167802Sjkim                return;
306167802Sjkim            }
307167802Sjkim
308167802Sjkim            if (Byte != '*')
309167802Sjkim            {
310167802Sjkim                /* Reset */
311167802Sjkim
312167802Sjkim                ClosingComment = FALSE;
313167802Sjkim            }
314167802Sjkim        }
315167802Sjkim        else if (Byte == '*')
316167802Sjkim        {
317167802Sjkim            ClosingComment = TRUE;
318167802Sjkim        }
319167802Sjkim
320167802Sjkim        /* Maintain line count */
321167802Sjkim
322167802Sjkim        if (Byte == 0x0A)
323167802Sjkim        {
324167802Sjkim            Status->Line++;
325167802Sjkim        }
326167802Sjkim
327167802Sjkim        Status->Offset++;
328167802Sjkim    }
329167802Sjkim}
330167802Sjkim
331167802Sjkim
332212761Sjkimstatic void
333167802SjkimFlConsumeNewComment (
334235945Sjkim    FILE                    *Handle,
335167802Sjkim    ASL_FILE_STATUS         *Status)
336167802Sjkim{
337167802Sjkim    UINT8                   Byte;
338167802Sjkim
339167802Sjkim
340243347Sjkim    while (fread (&Byte, 1, 1, Handle) == 1)
341167802Sjkim    {
342167802Sjkim        Status->Offset++;
343167802Sjkim
344167802Sjkim        /* Comment ends at newline */
345167802Sjkim
346167802Sjkim        if (Byte == 0x0A)
347167802Sjkim        {
348167802Sjkim            Status->Line++;
349167802Sjkim            return;
350167802Sjkim        }
351167802Sjkim    }
352167802Sjkim}
353167802Sjkim
354167802Sjkim
355167802Sjkim/*******************************************************************************
356167802Sjkim *
357246849Sjkim * FUNCTION:    FlCheckForAcpiTable
358246849Sjkim *
359246849Sjkim * PARAMETERS:  Handle              - Open input file
360246849Sjkim *
361246849Sjkim * RETURN:      Status
362246849Sjkim *
363246849Sjkim * DESCRIPTION: Determine if a file seems to be a binary ACPI table, via the
364246849Sjkim *              following checks on what would be the table header:
365246849Sjkim *              0) File must be at least as long as an ACPI_TABLE_HEADER
366246849Sjkim *              1) The header length field must match the file size
367246849Sjkim *              2) Signature, OemId, OemTableId, AslCompilerId must be ASCII
368246849Sjkim *
369246849Sjkim ******************************************************************************/
370246849Sjkim
371246849SjkimACPI_STATUS
372246849SjkimFlCheckForAcpiTable (
373246849Sjkim    FILE                    *Handle)
374246849Sjkim{
375246849Sjkim    ACPI_TABLE_HEADER       Table;
376246849Sjkim    UINT32                  FileSize;
377246849Sjkim    size_t                  Actual;
378246849Sjkim    UINT32                  i;
379246849Sjkim
380246849Sjkim
381246849Sjkim    /* Read a potential table header */
382246849Sjkim
383246849Sjkim    Actual = fread (&Table, 1, sizeof (ACPI_TABLE_HEADER), Handle);
384246849Sjkim    fseek (Handle, 0, SEEK_SET);
385246849Sjkim
386246849Sjkim    if (Actual < sizeof (ACPI_TABLE_HEADER))
387246849Sjkim    {
388246849Sjkim        return (AE_ERROR);
389246849Sjkim    }
390246849Sjkim
391246849Sjkim    /* Header length field must match the file size */
392246849Sjkim
393246849Sjkim    FileSize = DtGetFileSize (Handle);
394246849Sjkim    if (Table.Length != FileSize)
395246849Sjkim    {
396246849Sjkim        return (AE_ERROR);
397246849Sjkim    }
398246849Sjkim
399246849Sjkim    /*
400246849Sjkim     * These fields must be ASCII:
401246849Sjkim     * Signature, OemId, OemTableId, AslCompilerId.
402246849Sjkim     * We allow a NULL terminator in OemId and OemTableId.
403246849Sjkim     */
404246849Sjkim    for (i = 0; i < ACPI_NAME_SIZE; i++)
405246849Sjkim    {
406246849Sjkim        if (!ACPI_IS_ASCII ((UINT8) Table.Signature[i]))
407246849Sjkim        {
408246849Sjkim            return (AE_ERROR);
409246849Sjkim        }
410246849Sjkim
411246849Sjkim        if (!ACPI_IS_ASCII ((UINT8) Table.AslCompilerId[i]))
412246849Sjkim        {
413246849Sjkim            return (AE_ERROR);
414246849Sjkim        }
415246849Sjkim    }
416246849Sjkim
417246849Sjkim    for (i = 0; (i < ACPI_OEM_ID_SIZE) && (Table.OemId[i]); i++)
418246849Sjkim    {
419246849Sjkim        if (!ACPI_IS_ASCII ((UINT8) Table.OemId[i]))
420246849Sjkim        {
421246849Sjkim            return (AE_ERROR);
422246849Sjkim        }
423246849Sjkim    }
424246849Sjkim
425246849Sjkim    for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (Table.OemTableId[i]); i++)
426246849Sjkim    {
427246849Sjkim        if (!ACPI_IS_ASCII ((UINT8) Table.OemTableId[i]))
428246849Sjkim        {
429246849Sjkim            return (AE_ERROR);
430246849Sjkim        }
431246849Sjkim    }
432246849Sjkim
433246849Sjkim    printf ("Binary file appears to be a valid ACPI table, disassembling\n");
434246849Sjkim    return (AE_OK);
435246849Sjkim}
436246849Sjkim
437246849Sjkim
438246849Sjkim/*******************************************************************************
439246849Sjkim *
440123315Snjl * FUNCTION:    FlCheckForAscii
441123315Snjl *
442235945Sjkim * PARAMETERS:  Handle              - Open input file
443235945Sjkim *              Filename            - Input filename
444235945Sjkim *              DisplayErrors       - TRUE if error messages desired
445123315Snjl *
446151937Sjkim * RETURN:      Status
447123315Snjl *
448167802Sjkim * DESCRIPTION: Verify that the input file is entirely ASCII. Ignores characters
449167802Sjkim *              within comments. Note: does not handle nested comments and does
450167802Sjkim *              not handle comment delimiters within string literals. However,
451167802Sjkim *              on the rare chance this happens and an invalid character is
452167802Sjkim *              missed, the parser will catch the error by failing in some
453167802Sjkim *              spectactular manner.
454123315Snjl *
455123315Snjl ******************************************************************************/
456123315Snjl
457209746SjkimACPI_STATUS
458123315SnjlFlCheckForAscii (
459235945Sjkim    FILE                    *Handle,
460235945Sjkim    char                    *Filename,
461235945Sjkim    BOOLEAN                 DisplayErrors)
462123315Snjl{
463123315Snjl    UINT8                   Byte;
464123315Snjl    ACPI_SIZE               BadBytes = 0;
465167802Sjkim    BOOLEAN                 OpeningComment = FALSE;
466167802Sjkim    ASL_FILE_STATUS         Status;
467123315Snjl
468123315Snjl
469167802Sjkim    Status.Line = 1;
470167802Sjkim    Status.Offset = 0;
471167802Sjkim
472123315Snjl    /* Read the entire file */
473123315Snjl
474243347Sjkim    while (fread (&Byte, 1, 1, Handle) == 1)
475123315Snjl    {
476167802Sjkim        /* Ignore comment fields (allow non-ascii within) */
477167802Sjkim
478167802Sjkim        if (OpeningComment)
479167802Sjkim        {
480167802Sjkim            /* Check for second comment open delimiter */
481167802Sjkim
482167802Sjkim            if (Byte == '*')
483167802Sjkim            {
484235945Sjkim                FlConsumeAnsiComment (Handle, &Status);
485167802Sjkim            }
486167802Sjkim
487167802Sjkim            if (Byte == '/')
488167802Sjkim            {
489235945Sjkim                FlConsumeNewComment (Handle, &Status);
490167802Sjkim            }
491167802Sjkim
492167802Sjkim            /* Reset */
493167802Sjkim
494167802Sjkim            OpeningComment = FALSE;
495167802Sjkim        }
496167802Sjkim        else if (Byte == '/')
497167802Sjkim        {
498167802Sjkim            OpeningComment = TRUE;
499167802Sjkim        }
500167802Sjkim
501123315Snjl        /* Check for an ASCII character */
502123315Snjl
503193529Sjkim        if (!ACPI_IS_ASCII (Byte))
504123315Snjl        {
505235945Sjkim            if ((BadBytes < 10) && (DisplayErrors))
506123315Snjl            {
507151937Sjkim                AcpiOsPrintf (
508167802Sjkim                    "Non-ASCII character [0x%2.2X] found in line %u, file offset 0x%.2X\n",
509167802Sjkim                    Byte, Status.Line, Status.Offset);
510123315Snjl            }
511167802Sjkim
512123315Snjl            BadBytes++;
513123315Snjl        }
514167802Sjkim
515167802Sjkim        /* Update line counter */
516167802Sjkim
517167802Sjkim        else if (Byte == 0x0A)
518167802Sjkim        {
519167802Sjkim            Status.Line++;
520167802Sjkim        }
521167802Sjkim
522167802Sjkim        Status.Offset++;
523123315Snjl    }
524123315Snjl
525151937Sjkim    /* Seek back to the beginning of the source file */
526151937Sjkim
527235945Sjkim    fseek (Handle, 0, SEEK_SET);
528151937Sjkim
529123315Snjl    /* Were there any non-ASCII characters in the file? */
530123315Snjl
531123315Snjl    if (BadBytes)
532123315Snjl    {
533235945Sjkim        if (DisplayErrors)
534235945Sjkim        {
535235945Sjkim            AcpiOsPrintf (
536235945Sjkim                "%u non-ASCII characters found in input source text, could be a binary file\n",
537235945Sjkim                BadBytes);
538235945Sjkim            AslError (ASL_ERROR, ASL_MSG_NON_ASCII, NULL, Filename);
539235945Sjkim        }
540235945Sjkim
541123315Snjl        return (AE_BAD_CHARACTER);
542123315Snjl    }
543123315Snjl
544235945Sjkim    /* File is OK (100% ASCII) */
545123315Snjl
546123315Snjl    return (AE_OK);
547123315Snjl}
548123315Snjl
549123315Snjl
550123315Snjl/*******************************************************************************
551123315Snjl *
552118611Snjl * FUNCTION:    CmDoCompile
553118611Snjl *
554118611Snjl * PARAMETERS:  None
555118611Snjl *
556118611Snjl * RETURN:      Status (0 = OK)
557118611Snjl *
558118611Snjl * DESCRIPTION: This procedure performs the entire compile
559118611Snjl *
560118611Snjl ******************************************************************************/
561118611Snjl
562118611Snjlint
563151937SjkimCmDoCompile (
564151937Sjkim    void)
565118611Snjl{
566118611Snjl    ACPI_STATUS             Status;
567151937Sjkim    UINT8                   FullCompile;
568151937Sjkim    UINT8                   Event;
569118611Snjl
570118611Snjl
571151937Sjkim    FullCompile = UtBeginEvent ("*** Total Compile time ***");
572151937Sjkim    Event = UtBeginEvent ("Open input and output files");
573151937Sjkim    UtEndEvent (Event);
574118611Snjl
575233250Sjkim    Event = UtBeginEvent ("Preprocess input file");
576234623Sjkim    if (Gbl_PreprocessFlag)
577233250Sjkim    {
578234623Sjkim        /* Preprocessor */
579234623Sjkim
580234623Sjkim        PrDoPreprocess ();
581234623Sjkim        if (Gbl_PreprocessOnly)
582234623Sjkim        {
583234623Sjkim            UtEndEvent (Event);
584234623Sjkim            CmCleanupAndExit ();
585241973Sjkim            return (0);
586234623Sjkim        }
587233250Sjkim    }
588234623Sjkim    UtEndEvent (Event);
589233250Sjkim
590118611Snjl    /* Build the parse tree */
591118611Snjl
592151937Sjkim    Event = UtBeginEvent ("Parse source code and build parse tree");
593118611Snjl    AslCompilerparse();
594151937Sjkim    UtEndEvent (Event);
595118611Snjl
596254745Sjkim    /* Check for parse errors */
597118611Snjl
598254745Sjkim    Status = AslCheckForErrorExit ();
599254745Sjkim    if (ACPI_FAILURE (Status))
600254745Sjkim    {
601254745Sjkim        fprintf (stderr, "Compiler aborting due to parser-detected syntax error(s)\n");
602254745Sjkim        LsDumpParseTree ();
603254745Sjkim        goto ErrorExit;
604254745Sjkim    }
605118611Snjl
606118611Snjl    /* Did the parse tree get successfully constructed? */
607118611Snjl
608118611Snjl    if (!RootNode)
609118611Snjl    {
610234623Sjkim        /*
611234623Sjkim         * If there are no errors, then we have some sort of
612234623Sjkim         * internal problem.
613234623Sjkim         */
614254745Sjkim        AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
615254745Sjkim            NULL, "- Could not resolve parse tree root node");
616234623Sjkim
617233250Sjkim        goto ErrorExit;
618118611Snjl    }
619118611Snjl
620254745Sjkim
621254745Sjkim    /* Flush out any remaining source after parse tree is complete */
622254745Sjkim
623254745Sjkim    Event = UtBeginEvent ("Flush source input");
624254745Sjkim    CmFlushSourceCode ();
625254745Sjkim
626167802Sjkim    /* Optional parse tree dump, compiler debug output only */
627167802Sjkim
628167802Sjkim    LsDumpParseTree ();
629167802Sjkim
630118611Snjl    OpcGetIntegerWidth (RootNode);
631151937Sjkim    UtEndEvent (Event);
632118611Snjl
633118611Snjl    /* Pre-process parse tree for any operator transforms */
634118611Snjl
635151937Sjkim    Event = UtBeginEvent ("Parse tree transforms");
636118611Snjl    DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
637151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
638151937Sjkim        TrAmlTransformWalk, NULL, NULL);
639151937Sjkim    UtEndEvent (Event);
640118611Snjl
641118611Snjl    /* Generate AML opcodes corresponding to the parse tokens */
642118611Snjl
643151937Sjkim    Event = UtBeginEvent ("Generate AML opcodes");
644118611Snjl    DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n");
645151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
646151937Sjkim        OpcAmlOpcodeWalk, NULL);
647151937Sjkim    UtEndEvent (Event);
648118611Snjl
649118611Snjl    /*
650118611Snjl     * Now that the input is parsed, we can open the AML output file.
651118611Snjl     * Note: by default, the name of this file comes from the table descriptor
652118611Snjl     * within the input file.
653118611Snjl     */
654151937Sjkim    Event = UtBeginEvent ("Open AML output file");
655118611Snjl    Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix);
656233250Sjkim    UtEndEvent (Event);
657118611Snjl    if (ACPI_FAILURE (Status))
658118611Snjl    {
659118611Snjl        AePrintErrorLog (ASL_FILE_STDERR);
660241973Sjkim        return (-1);
661118611Snjl    }
662118611Snjl
663118611Snjl    /* Interpret and generate all compile-time constants */
664118611Snjl
665151937Sjkim    Event = UtBeginEvent ("Constant folding via AML interpreter");
666151937Sjkim    DbgPrint (ASL_DEBUG_OUTPUT,
667151937Sjkim        "\nInterpreting compile-time constant expressions\n\n");
668151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
669151937Sjkim        OpcAmlConstantWalk, NULL, NULL);
670151937Sjkim    UtEndEvent (Event);
671118611Snjl
672151937Sjkim    /* Update AML opcodes if necessary, after constant folding */
673151937Sjkim
674151937Sjkim    Event = UtBeginEvent ("Updating AML opcodes after constant folding");
675151937Sjkim    DbgPrint (ASL_DEBUG_OUTPUT,
676151937Sjkim        "\nUpdating AML opcodes after constant folding\n\n");
677151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
678151937Sjkim        NULL, OpcAmlOpcodeUpdateWalk, NULL);
679151937Sjkim    UtEndEvent (Event);
680151937Sjkim
681118611Snjl    /* Calculate all AML package lengths */
682118611Snjl
683151937Sjkim    Event = UtBeginEvent ("Generate AML package lengths");
684118611Snjl    DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
685151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
686151937Sjkim        LnPackageLengthWalk, NULL);
687151937Sjkim    UtEndEvent (Event);
688118611Snjl
689118611Snjl    if (Gbl_ParseOnlyFlag)
690118611Snjl    {
691234623Sjkim        AePrintErrorLog (ASL_FILE_STDERR);
692234623Sjkim        UtDisplaySummary (ASL_FILE_STDERR);
693118611Snjl        if (Gbl_DebugFlag)
694118611Snjl        {
695234623Sjkim            /* Print error summary to the stdout also */
696118611Snjl
697234623Sjkim            AePrintErrorLog (ASL_FILE_STDOUT);
698234623Sjkim            UtDisplaySummary (ASL_FILE_STDOUT);
699118611Snjl        }
700233250Sjkim        UtEndEvent (FullCompile);
701241973Sjkim        return (0);
702118611Snjl    }
703118611Snjl
704118611Snjl    /*
705118611Snjl     * Create an internal namespace and use it as a symbol table
706118611Snjl     */
707118611Snjl
708118611Snjl    /* Namespace loading */
709118611Snjl
710151937Sjkim    Event = UtBeginEvent ("Create ACPI Namespace");
711118611Snjl    Status = LdLoadNamespace (RootNode);
712151937Sjkim    UtEndEvent (Event);
713118611Snjl    if (ACPI_FAILURE (Status))
714118611Snjl    {
715233250Sjkim        goto ErrorExit;
716118611Snjl    }
717118611Snjl
718167802Sjkim    /* Namespace cross-reference */
719118611Snjl
720151937Sjkim    AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace");
721245582Sjkim    Status = XfCrossReferenceNamespace ();
722118611Snjl    if (ACPI_FAILURE (Status))
723118611Snjl    {
724233250Sjkim        goto ErrorExit;
725118611Snjl    }
726118611Snjl
727167802Sjkim    /* Namespace - Check for non-referenced objects */
728167802Sjkim
729167802Sjkim    LkFindUnreferencedObjects ();
730167802Sjkim    UtEndEvent (AslGbl_NamespaceEvent);
731167802Sjkim
732118611Snjl    /*
733241973Sjkim     * Semantic analysis. This can happen only after the
734118611Snjl     * namespace has been loaded and cross-referenced.
735118611Snjl     *
736118611Snjl     * part one - check control methods
737118611Snjl     */
738151937Sjkim    Event = UtBeginEvent ("Analyze control method return types");
739118611Snjl    AnalysisWalkInfo.MethodStack = NULL;
740118611Snjl
741118611Snjl    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n");
742151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE,
743245582Sjkim        MtMethodAnalysisWalkBegin,
744245582Sjkim        MtMethodAnalysisWalkEnd, &AnalysisWalkInfo);
745151937Sjkim    UtEndEvent (Event);
746118611Snjl
747118611Snjl    /* Semantic error checking part two - typing of method returns */
748118611Snjl
749151937Sjkim    Event = UtBeginEvent ("Determine object types returned by methods");
750151937Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n");
751218590Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
752218590Sjkim        NULL, AnMethodTypingWalkEnd, NULL);
753151937Sjkim    UtEndEvent (Event);
754118611Snjl
755118611Snjl    /* Semantic error checking part three - operand type checking */
756118611Snjl
757151937Sjkim    Event = UtBeginEvent ("Analyze AML operand types");
758151937Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n");
759218590Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
760218590Sjkim        NULL, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo);
761151937Sjkim    UtEndEvent (Event);
762118611Snjl
763118611Snjl    /* Semantic error checking part four - other miscellaneous checks */
764118611Snjl
765151937Sjkim    Event = UtBeginEvent ("Miscellaneous analysis");
766151937Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n");
767218590Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
768151937Sjkim        AnOtherSemanticAnalysisWalkBegin,
769218590Sjkim        NULL, &AnalysisWalkInfo);
770151937Sjkim    UtEndEvent (Event);
771118611Snjl
772118611Snjl    /* Calculate all AML package lengths */
773118611Snjl
774151937Sjkim    Event = UtBeginEvent ("Finish AML package length generation");
775118611Snjl    DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
776151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
777151937Sjkim        LnInitLengthsWalk, NULL);
778151937Sjkim    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
779151937Sjkim        LnPackageLengthWalk, NULL);
780151937Sjkim    UtEndEvent (Event);
781118611Snjl
782118611Snjl    /* Code generation - emit the AML */
783118611Snjl
784151937Sjkim    Event = UtBeginEvent ("Generate AML code and write output files");
785118611Snjl    CgGenerateAmlOutput ();
786151937Sjkim    UtEndEvent (Event);
787118611Snjl
788151937Sjkim    Event = UtBeginEvent ("Write optional output files");
789118611Snjl    CmDoOutputFiles ();
790151937Sjkim    UtEndEvent (Event);
791118611Snjl
792151937Sjkim    UtEndEvent (FullCompile);
793118611Snjl    CmCleanupAndExit ();
794241973Sjkim    return (0);
795233250Sjkim
796233250SjkimErrorExit:
797233250Sjkim    UtEndEvent (FullCompile);
798233250Sjkim    CmCleanupAndExit ();
799233250Sjkim    return (-1);
800118611Snjl}
801118611Snjl
802151937Sjkim
803151937Sjkim/*******************************************************************************
804151937Sjkim *
805151937Sjkim * FUNCTION:    CmDoOutputFiles
806151937Sjkim *
807151937Sjkim * PARAMETERS:  None
808151937Sjkim *
809151937Sjkim * RETURN:      None.
810151937Sjkim *
811151937Sjkim * DESCRIPTION: Create all "listing" type files
812151937Sjkim *
813151937Sjkim ******************************************************************************/
814151937Sjkim
815118611Snjlvoid
816151937SjkimCmDoOutputFiles (
817151937Sjkim    void)
818118611Snjl{
819118611Snjl
820118611Snjl    /* Create listings and hex files */
821118611Snjl
822118611Snjl    LsDoListings ();
823245582Sjkim    HxDoHexOutput ();
824118611Snjl
825118611Snjl    /* Dump the namespace to the .nsp file if requested */
826118611Snjl
827245582Sjkim    (void) NsDisplayNamespace ();
828118611Snjl}
829118611Snjl
830118611Snjl
831118611Snjl/*******************************************************************************
832118611Snjl *
833237412Sjkim * FUNCTION:    CmDumpAllEvents
834151937Sjkim *
835237412Sjkim * PARAMETERS:  None
836151937Sjkim *
837151937Sjkim * RETURN:      None.
838151937Sjkim *
839237412Sjkim * DESCRIPTION: Dump all compiler events
840151937Sjkim *
841151937Sjkim ******************************************************************************/
842151937Sjkim
843151937Sjkimstatic void
844237412SjkimCmDumpAllEvents (
845237412Sjkim    void)
846151937Sjkim{
847237412Sjkim    ASL_EVENT_INFO          *Event;
848151937Sjkim    UINT32                  Delta;
849151937Sjkim    UINT32                  USec;
850151937Sjkim    UINT32                  MSec;
851237412Sjkim    UINT32                  i;
852151937Sjkim
853237412Sjkim
854237412Sjkim    Event = AslGbl_Events;
855237412Sjkim
856237412Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
857237412Sjkim    if (Gbl_CompileTimesFlag)
858151937Sjkim    {
859237412Sjkim        printf ("\nElapsed time for major events\n\n");
860151937Sjkim    }
861151937Sjkim
862237412Sjkim    for (i = 0; i < AslGbl_NextEvent; i++)
863237412Sjkim    {
864237412Sjkim        if (Event->Valid)
865237412Sjkim        {
866237412Sjkim            /* Delta will be in 100-nanosecond units */
867151937Sjkim
868237412Sjkim            Delta = (UINT32) (Event->EndTime - Event->StartTime);
869151937Sjkim
870245582Sjkim            USec = Delta / ACPI_100NSEC_PER_USEC;
871245582Sjkim            MSec = Delta / ACPI_100NSEC_PER_MSEC;
872151937Sjkim
873237412Sjkim            /* Round milliseconds up */
874151937Sjkim
875245582Sjkim            if ((USec - (MSec * ACPI_USEC_PER_MSEC)) >= 500)
876237412Sjkim            {
877237412Sjkim                MSec++;
878237412Sjkim            }
879237412Sjkim
880237412Sjkim            DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
881237412Sjkim                USec, MSec, Event->EventName);
882237412Sjkim
883237412Sjkim            if (Gbl_CompileTimesFlag)
884237412Sjkim            {
885237412Sjkim                printf ("%8u usec %8u msec - %s\n",
886237412Sjkim                    USec, MSec, Event->EventName);
887237412Sjkim            }
888237412Sjkim        }
889237412Sjkim
890237412Sjkim        Event++;
891151937Sjkim    }
892151937Sjkim}
893151937Sjkim
894151937Sjkim
895151937Sjkim/*******************************************************************************
896151937Sjkim *
897118611Snjl * FUNCTION:    CmCleanupAndExit
898118611Snjl *
899118611Snjl * PARAMETERS:  None
900118611Snjl *
901118611Snjl * RETURN:      None.
902118611Snjl *
903118611Snjl * DESCRIPTION: Close all open files and exit the compiler
904118611Snjl *
905118611Snjl ******************************************************************************/
906118611Snjl
907118611Snjlvoid
908151937SjkimCmCleanupAndExit (
909151937Sjkim    void)
910118611Snjl{
911118611Snjl    UINT32                  i;
912240716Sjkim    BOOLEAN                 DeleteAmlFile = FALSE;
913118611Snjl
914118611Snjl
915234623Sjkim    AePrintErrorLog (ASL_FILE_STDERR);
916118611Snjl    if (Gbl_DebugFlag)
917118611Snjl    {
918234623Sjkim        /* Print error summary to stdout also */
919118611Snjl
920234623Sjkim        AePrintErrorLog (ASL_FILE_STDOUT);
921118611Snjl    }
922118611Snjl
923237412Sjkim    /* Emit compile times if enabled */
924118611Snjl
925237412Sjkim    CmDumpAllEvents ();
926237412Sjkim
927118611Snjl    if (Gbl_CompileTimesFlag)
928118611Snjl    {
929118611Snjl        printf ("\nMiscellaneous compile statistics\n\n");
930118611Snjl        printf ("%11u : %s\n", TotalParseNodes, "Parse nodes");
931118611Snjl        printf ("%11u : %s\n", Gbl_NsLookupCount, "Namespace searches");
932118611Snjl        printf ("%11u : %s\n", TotalNamedObjects, "Named objects");
933118611Snjl        printf ("%11u : %s\n", TotalMethods, "Control methods");
934118611Snjl        printf ("%11u : %s\n", TotalAllocations, "Memory Allocations");
935118611Snjl        printf ("%11u : %s\n", TotalAllocated, "Total allocated memory");
936118611Snjl        printf ("%11u : %s\n", TotalFolds, "Constant subtrees folded");
937118611Snjl        printf ("\n");
938118611Snjl    }
939118611Snjl
940118611Snjl    if (Gbl_NsLookupCount)
941118611Snjl    {
942209746Sjkim        DbgPrint (ASL_DEBUG_OUTPUT,
943209746Sjkim            "\n\nMiscellaneous compile statistics\n\n");
944209746Sjkim
945209746Sjkim        DbgPrint (ASL_DEBUG_OUTPUT,
946209746Sjkim            "%32s : %u\n", "Total Namespace searches",
947151937Sjkim            Gbl_NsLookupCount);
948209746Sjkim
949209746Sjkim        DbgPrint (ASL_DEBUG_OUTPUT,
950209746Sjkim            "%32s : %u usec\n", "Time per search", ((UINT32)
951209746Sjkim            (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
952209746Sjkim                AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
953209746Sjkim                Gbl_NsLookupCount);
954118611Snjl    }
955118611Snjl
956118611Snjl    if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
957118611Snjl    {
958209746Sjkim        printf ("\nMaximum error count (%u) exceeded\n",
959209746Sjkim            ASL_MAX_ERROR_COUNT);
960118611Snjl    }
961118611Snjl
962118611Snjl    UtDisplaySummary (ASL_FILE_STDOUT);
963199337Sjkim
964240716Sjkim    /*
965240716Sjkim     * We will delete the AML file if there are errors and the
966240716Sjkim     * force AML output option has not been used.
967240716Sjkim     */
968240716Sjkim    if ((Gbl_ExceptionCount[ASL_ERROR] > 0) && (!Gbl_IgnoreErrors) &&
969240716Sjkim        Gbl_Files[ASL_FILE_AML_OUTPUT].Handle)
970240716Sjkim    {
971240716Sjkim        DeleteAmlFile = TRUE;
972240716Sjkim    }
973240716Sjkim
974199337Sjkim    /* Close all open files */
975199337Sjkim
976252279Sjkim    /*
977252279Sjkim     * Take care with the preprocessor file (.i), it might be the same
978252279Sjkim     * as the "input" file, depending on where the compiler has terminated
979252279Sjkim     * or aborted. Prevent attempt to close the same file twice in
980252279Sjkim     * loop below.
981252279Sjkim     */
982252279Sjkim    if (Gbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
983252279Sjkim        Gbl_Files[ASL_FILE_INPUT].Handle)
984252279Sjkim    {
985252279Sjkim        Gbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
986252279Sjkim    }
987233250Sjkim
988252279Sjkim    /* Close the standard I/O files */
989252279Sjkim
990233250Sjkim    for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
991199337Sjkim    {
992199337Sjkim        FlCloseFile (i);
993199337Sjkim    }
994200553Sjkim
995200553Sjkim    /* Delete AML file if there are errors */
996200553Sjkim
997240716Sjkim    if (DeleteAmlFile)
998200553Sjkim    {
999240716Sjkim        FlDeleteFile (ASL_FILE_AML_OUTPUT);
1000200553Sjkim    }
1001200553Sjkim
1002233250Sjkim    /* Delete the preprocessor output file (.i) unless -li flag is set */
1003233250Sjkim
1004234623Sjkim    if (!Gbl_PreprocessorOutputFlag &&
1005240716Sjkim        Gbl_PreprocessFlag)
1006233250Sjkim    {
1007240716Sjkim        FlDeleteFile (ASL_FILE_PREPROCESSOR);
1008233250Sjkim    }
1009233250Sjkim
1010200553Sjkim    /*
1011200553Sjkim     * Delete intermediate ("combined") source file (if -ls flag not set)
1012209746Sjkim     * This file is created during normal ASL/AML compiles. It is not
1013209746Sjkim     * created by the data table compiler.
1014200553Sjkim     *
1015209746Sjkim     * If the -ls flag is set, then the .SRC file should not be deleted.
1016209746Sjkim     * In this case, Gbl_SourceOutputFlag is set to TRUE.
1017209746Sjkim     *
1018209746Sjkim     * Note: Handles are cleared by FlCloseFile above, so we look at the
1019209746Sjkim     * filename instead, to determine if the .SRC file was actually
1020209746Sjkim     * created.
1021209746Sjkim     *
1022200553Sjkim     * TBD: SourceOutput should be .TMP, then rename if we want to keep it?
1023200553Sjkim     */
1024240716Sjkim    if (!Gbl_SourceOutputFlag)
1025200553Sjkim    {
1026240716Sjkim        FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
1027200553Sjkim    }
1028118611Snjl}
1029