ACPI_STATUS LdLoadNamespace ( ACPI_PARSE_OBJECT *RootOp) { ACPI_WALK_STATE *WalkState; DbgPrint (ASL_DEBUG_OUTPUT, "\nCreating namespace\n\n"); /* Create a new walk state */ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); if (!WalkState) { return (AE_NO_MEMORY); } /* Walk the entire parse tree, first pass */ TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace1Begin, LdCommonNamespaceEnd, WalkState); /* Second pass to handle forward references */ TrWalkParseTree (RootOp, ASL_WALK_VISIT_TWICE, LdNamespace2Begin, LdCommonNamespaceEnd, WalkState); /* Dump the namespace if debug is enabled */ AcpiNsDumpTables (ACPI_NS_ALL, ACPI_UINT32_MAX); return (AE_OK); }
ACPI_STATUS LkCrossReferenceNamespace ( void) { ACPI_WALK_STATE *WalkState; DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n"); /* * Create a new walk state for use when looking up names * within the namespace (Passed as context to the callbacks) */ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); if (!WalkState) { return (AE_NO_MEMORY); } /* Walk the entire parse tree */ TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin, LkNamespaceLocateEnd, WalkState); return (AE_OK); }
ACPI_STATUS AnMethodTypingWalkEnd ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { UINT32 ThisNodeBtype; switch (Op->Asl.ParseOpcode) { case PARSEOP_METHOD: Op->Asl.CompileFlags |= NODE_METHOD_TYPED; break; case PARSEOP_RETURN: if ((Op->Asl.Child) && (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) { ThisNodeBtype = AnGetBtype (Op->Asl.Child); if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && (ThisNodeBtype == (ACPI_UINT32_MAX -1))) { /* * The called method is untyped at this time (typically a * forward reference). * * Check for a recursive method call first. */ if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) { /* We must type the method here */ TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, ASL_WALK_VISIT_UPWARD, NULL, AnMethodTypingWalkEnd, NULL); ThisNodeBtype = AnGetBtype (Op->Asl.Child); } } /* Returns a value, save the value type */ if (Op->Asl.ParentMethod) { Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; } } break; default: break; } return (AE_OK); }
ACPI_STATUS XfCrossReferenceNamespace ( void) { ACPI_WALK_STATE *WalkState; /* * Create a new walk state for use when looking up names * within the namespace (Passed as context to the callbacks) */ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); if (!WalkState) { return (AE_NO_MEMORY); } /* Walk the entire parse tree */ TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin, XfNamespaceLocateEnd, WalkState); ACPI_FREE (WalkState); return (AE_OK); }
void CgGenerateAmlOutput ( void) { /* Generate the AML output file */ TrWalkParseTree (AslGbl_CurrentDB, ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY, CgAmlWriteWalk, NULL, NULL); DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2); CgUpdateHeader (AslGbl_CurrentDB); }
void LsDumpParseTree ( void) { if (!Gbl_DebugFlag) { return; } DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsTreeWriteWalk, NULL, NULL); }
static void LsGenerateListing ( UINT32 FileId) { UINT32 WalkMode = ASL_WALK_VISIT_DOWNWARD | ASL_WALK_VISIT_DB_SEPARATELY; /* Start at the beginning of both the source and AML files */ FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); FlSeekFile (ASL_FILE_AML_OUTPUT, 0); AslGbl_SourceLine = 0; AslGbl_CurrentHexColumn = 0; LsPushNode (AslGbl_Files[ASL_FILE_INPUT].Filename); if (FileId == ASL_FILE_C_OFFSET_OUTPUT) { AslGbl_CurrentAmlOffset = 0; /* Offset table file has a special header and footer */ LsDoOffsetTableHeader (FileId); TrWalkParseTree (AslGbl_CurrentDB, WalkMode, LsAmlOffsetWalk, NULL, (void *) ACPI_TO_POINTER (FileId)); LsDoOffsetTableFooter (FileId); return; } /* Process all parse nodes */ TrWalkParseTree (AslGbl_CurrentDB, WalkMode, LsAmlListingWalk, NULL, (void *) ACPI_TO_POINTER (FileId)); /* Final processing */ LsFinishSourceListing (FileId); }
static void MpXrefDevices ( ACPI_GPIO_INFO *Info) { /* Walk the entire parse tree */ TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, MpNamespaceXrefBegin, NULL, Info); if (!Info->References) { FlPrintFile (ASL_FILE_MAP_OUTPUT, " // **** No references in table"); } }
void CgGenerateAmlOutput ( void) { /* Generate the AML output file */ FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); Gbl_SourceLine = 0; Gbl_NextError = Gbl_ErrorLog; TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD, CgAmlWriteWalk, NULL, NULL); DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER2); CgCloseTable (); }
void CgGenerateAmlOutput ( void) { DbgPrint (ASL_DEBUG_OUTPUT, "\nWriting AML\n\n"); /* Generate the AML output file */ FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); Gbl_SourceLine = 0; Gbl_NextError = Gbl_ErrorLog; TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, CgAmlWriteWalk, NULL, NULL); CgCloseTable (); }
void LsDumpParseTree ( void) { if (!AslGbl_DebugFlag) { return; } DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n"); DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD, LsTreeWriteWalk, NULL, NULL); DbgPrint (ASL_TREE_OUTPUT, ASL_PARSE_TREE_HEADER1); }
BOOLEAN ApFindNameInDeviceTree ( char *Name, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, ApDeviceSubtreeWalk, NULL, Name); if (Status == AE_CTRL_TRUE) { return (TRUE); /* Found a match */ } return (FALSE); }
static void LsGenerateListing ( UINT32 FileId) { /* Start at the beginning of both the source and AML files */ FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); FlSeekFile (ASL_FILE_AML_OUTPUT, 0); Gbl_SourceLine = 0; Gbl_CurrentHexColumn = 0; LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename); /* Process all parse nodes */ TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk, NULL, (void *) ACPI_TO_POINTER (FileId)); /* Final processing */ LsFinishSourceListing (FileId); }
void CgGenerateAmlOutput ( void) { DbgPrint (ASL_DEBUG_OUTPUT, "\nWriting AML\n\n"); /* Generate the AML output file */ FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); Gbl_SourceLine = 0; Gbl_NextError = Gbl_ErrorLog; TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, CgAmlWriteWalk, NULL, NULL); DbgPrint (ASL_TREE_OUTPUT, "%*s Value P_Op A_Op OpLen PByts Len SubLen PSubLen OpPtr" " Parent Child Next Flags AcTyp Final Col L# EL# LL# ELL#\n", 76, " "); CgCloseTable (); }
ACPI_STATUS OpcAmlConstantWalk ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState; ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_PARSE_OBJECT *RootOp; ACPI_PARSE_OBJECT *OriginalParentOp; UINT8 WalkType; /* * Only interested in subtrees that could possibly contain * expressions that can be evaluated at this time */ if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) || (Op->Asl.CompileFlags & NODE_IS_TARGET)) { return (AE_OK); } /* Set the walk type based on the reduction used for this op */ if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG) { /* Op is a TermArg, constant folding is merely optional */ if (!Gbl_FoldConstants) { return (AE_CTRL_DEPTH); } WalkType = ACPI_WALK_CONST_OPTIONAL; } else { /* Op is a DataObject, the expression MUST reduced to a constant */ WalkType = ACPI_WALK_CONST_REQUIRED; } /* Create a new walk state */ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); if (!WalkState) { return AE_NO_MEMORY; } WalkState->NextOp = NULL; WalkState->Params = NULL; WalkState->WalkType = WalkType; WalkState->CallerReturnDesc = &ObjDesc; /* * Examine the entire subtree -- all nodes must be constants * or type 3/4/5 opcodes */ Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, OpcAmlCheckForConstant, NULL, WalkState); /* * Did we find an entire subtree that contains all constants and type 3/4/5 * opcodes? (Only AE_OK or AE_TYPE returned from above) */ if (Status == AE_TYPE) { /* Subtree cannot be reduced to a constant */ if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL) { AcpiDsDeleteWalkState (WalkState); return (AE_OK); } /* Don't descend any further, and use a default "constant" value */ Status = AE_CTRL_DEPTH; } else { /* Subtree can be reduced */ /* Allocate a new temporary root for this subtree */ RootOp = TrAllocateNode (PARSEOP_INTEGER); if (!RootOp) { return (AE_NO_MEMORY); } RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; OriginalParentOp = Op->Common.Parent; Op->Common.Parent = RootOp; /* Hand off the subtree to the AML interpreter */ Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); Op->Common.Parent = OriginalParentOp; /* TBD: we really *should* release the RootOp node */ if (ACPI_SUCCESS (Status)) { TotalFolds++; /* Get the final result */ Status = AcpiDsResultPop (&ObjDesc, WalkState); } /* Check for error from the ACPICA core */ if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Failure during constant evaluation", FALSE); } } if (ACPI_FAILURE (Status)) { /* We could not resolve the subtree for some reason */ AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op, Op->Asl.ParseOpName); /* Set the subtree value to ZERO anyway. Eliminates further errors */ OpcUpdateIntegerNode (Op, 0); } else { AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op, Op->Asl.ParseOpName); /* * Because we know we executed type 3/4/5 opcodes above, we know that * the result must be either an Integer, String, or Buffer. */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_INTEGER: OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value); DbgPrint (ASL_PARSE_OUTPUT, "Constant expression reduced to (%s) %8.8X%8.8X\n", Op->Asl.ParseOpName, ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); break; case ACPI_TYPE_STRING: Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; Op->Common.AmlOpcode = AML_STRING_OP; Op->Asl.AmlLength = ACPI_STRLEN (ObjDesc->String.Pointer) + 1; Op->Common.Value.String = ObjDesc->String.Pointer; DbgPrint (ASL_PARSE_OUTPUT, "Constant expression reduced to (STRING) %s\n", Op->Common.Value.String); break; case ACPI_TYPE_BUFFER: Op->Asl.ParseOpcode = PARSEOP_BUFFER; Op->Common.AmlOpcode = AML_BUFFER_OP; Op->Asl.CompileFlags = NODE_AML_PACKAGE; UtSetParseOpName (Op); /* Child node is the buffer length */ RootOp = TrAllocateNode (PARSEOP_INTEGER); RootOp->Asl.AmlOpcode = AML_DWORD_OP; RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length; RootOp->Asl.Parent = Op; (void) OpcSetOptimalIntegerSize (RootOp); Op->Asl.Child = RootOp; Op = RootOp; UtSetParseOpName (Op); /* Peer to the child is the raw buffer data */ RootOp = TrAllocateNode (PARSEOP_RAW_DATA); RootOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; RootOp->Asl.AmlLength = ObjDesc->Buffer.Length; RootOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer; RootOp->Asl.Parent = Op->Asl.Parent; Op->Asl.Next = RootOp; Op = RootOp; DbgPrint (ASL_PARSE_OUTPUT, "Constant expression reduced to (BUFFER) length %X\n", ObjDesc->Buffer.Length); break; default: printf ("Unsupported return type: %s\n", AcpiUtGetObjectTypeName (ObjDesc)); break; } } UtSetParseOpName (Op); Op->Asl.Child = NULL; AcpiDsDeleteWalkState (WalkState); return (AE_CTRL_DEPTH); }
int CmDoAslMiddleAndBackEnd ( void) { UINT8 Event; ACPI_STATUS Status; /* Interpret and generate all compile-time constants */ Event = UtBeginEvent ("Constant folding via AML interpreter"); DbgPrint (ASL_DEBUG_OUTPUT, "Interpreting compile-time constant expressions\n\n"); if (AslGbl_FoldConstants) { TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlConstantWalk, NULL); } else { DbgPrint (ASL_PARSE_OUTPUT, " Optional folding disabled\n"); } UtEndEvent (Event); /* Update AML opcodes if necessary, after constant folding */ Event = UtBeginEvent ("Updating AML opcodes after constant folding"); DbgPrint (ASL_DEBUG_OUTPUT, "Updating AML opcodes after constant folding\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlOpcodeUpdateWalk, NULL); UtEndEvent (Event); /* Calculate all AML package lengths */ Event = UtBeginEvent ("Generate AML package lengths"); DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, LnPackageLengthWalk, NULL); UtEndEvent (Event); if (AslGbl_ParseOnlyFlag) { AePrintErrorLog (ASL_FILE_STDERR); UtDisplaySummary (ASL_FILE_STDERR); if (AslGbl_DebugFlag) { /* Print error summary to the stdout also */ AePrintErrorLog (ASL_FILE_STDOUT); UtDisplaySummary (ASL_FILE_STDOUT); } return (0); } /* * Create an internal namespace and use it as a symbol table */ /* Namespace loading */ Event = UtBeginEvent ("Create ACPI Namespace"); DbgPrint (ASL_DEBUG_OUTPUT, "Creating ACPI Namespace\n\n"); Status = LdLoadNamespace (AslGbl_ParseTreeRoot); UtEndEvent (Event); if (ACPI_FAILURE (Status)) { return (-1); } /* Namespace cross-reference */ AslGbl_NamespaceEvent = UtBeginEvent ( "Cross reference parse tree and Namespace"); DbgPrint (ASL_DEBUG_OUTPUT, "Cross referencing namespace\n\n"); Status = XfCrossReferenceNamespace (); if (ACPI_FAILURE (Status)) { return (-1); } /* Namespace - Check for non-referenced objects */ LkFindUnreferencedObjects (); UtEndEvent (AslGbl_NamespaceEvent); /* Resolve External Declarations */ Event = UtBeginEvent ("Resolve all Externals"); DbgPrint (ASL_DEBUG_OUTPUT, "\nResolve Externals\n\n"); if (AslGbl_DoExternalsInPlace) { TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD, ExAmlExternalWalkBegin, NULL, NULL); } else { TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE, ExAmlExternalWalkBegin, ExAmlExternalWalkEnd, NULL); } UtEndEvent (Event); /* * Semantic analysis. This can happen only after the * namespace has been loaded and cross-referenced. * * part one - check control methods */ Event = UtBeginEvent ("Analyze control method return types"); AslGbl_AnalysisWalkInfo.MethodStack = NULL; DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method analysis\n\n"); if (AslGbl_CrossReferenceOutput) { OtPrintHeaders ("Part 1: Object Reference Map " "(Object references from within each control method)"); } TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE, MtMethodAnalysisWalkBegin, MtMethodAnalysisWalkEnd, &AslGbl_AnalysisWalkInfo); UtEndEvent (Event); /* Generate the object cross-reference file if requested */ Event = UtBeginEvent ("Generate cross-reference file"); OtCreateXrefFile (); UtEndEvent (Event); /* Semantic error checking part two - typing of method returns */ Event = UtBeginEvent ("Determine object types returned by methods"); DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method typing\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, AnMethodTypingWalkEnd, NULL); UtEndEvent (Event); /* Semantic error checking part three - operand type checking */ Event = UtBeginEvent ("Analyze AML operand types"); DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Operand type checking\n\n"); if (AslGbl_DoTypechecking) { TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, AnOperandTypecheckWalkEnd, &AslGbl_AnalysisWalkInfo); } UtEndEvent (Event); /* Semantic error checking part four - other miscellaneous checks */ Event = UtBeginEvent ("Miscellaneous analysis"); DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - miscellaneous\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD, AnOtherSemanticAnalysisWalkBegin, NULL, &AslGbl_AnalysisWalkInfo); UtEndEvent (Event); /* * ASL-/ASL+ converter: Gbl_ParseTreeRoot->CommentList contains the * very last comment of a given ASL file because it's the last constructed * node during compilation. We take the very last comment and save it in a * global for it to be used by the disassembler. */ if (AcpiGbl_CaptureComments) { AcpiGbl_LastListHead = AslGbl_ParseTreeRoot->Asl.CommentList; AslGbl_ParseTreeRoot->Asl.CommentList = NULL; } /* Calculate all AML package lengths */ Event = UtBeginEvent ("Finish AML package length generation"); DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, LnInitLengthsWalk, NULL); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, LnPackageLengthWalk, NULL); UtEndEvent (Event); /* Code generation - emit the AML */ Event = UtBeginEvent ("Generate AML code and write output files"); DbgPrint (ASL_DEBUG_OUTPUT, "Writing AML byte code\n\n"); AslGbl_CurrentDB = AslGbl_ParseTreeRoot->Asl.Child; while (AslGbl_CurrentDB) { switch (FlSwitchFileSet(AslGbl_CurrentDB->Asl.Filename)) { case SWITCH_TO_DIFFERENT_FILE: /* * Reset these parameters when definition blocks belong in * different files. If they belong in the same file, there is * no need to reset these parameters */ FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0); AslGbl_SourceLine = 0; AslGbl_NextError = AslGbl_ErrorLog; /* fall-through */ case SWITCH_TO_SAME_FILE: CgGenerateAmlOutput (); CmDoOutputFiles (); AslGbl_CurrentDB = AslGbl_CurrentDB->Asl.Next; break; default: /* FILE_NOT_FOUND */ /* The requested file could not be found. Get out of here */ AslGbl_CurrentDB = NULL; break; } } UtEndEvent (Event); Event = UtBeginEvent ("Write optional output files"); UtEndEvent (Event); return (0); }
ACPI_STATUS CmDoCompile ( void) { UINT8 FullCompile; UINT8 Event; ASL_GLOBAL_FILE_NODE *FileNode; FullCompile = UtBeginEvent ("*** Total Compile time ***"); Event = UtBeginEvent ("Open input and output files"); UtEndEvent (Event); Event = UtBeginEvent ("Preprocess input file"); if (AslGbl_PreprocessFlag) { /* Enter compiler name as a #define */ PrAddDefine (ASL_DEFINE, "", FALSE); /* Preprocessor */ PrDoPreprocess (); AslGbl_CurrentLineNumber = 1; AslGbl_LogicalLineNumber = 1; if (AslGbl_PreprocessOnly) { UtEndEvent (Event); CmCleanupAndExit (); return (AE_OK); } } UtEndEvent (Event); /* Build the parse tree */ Event = UtBeginEvent ("Parse source code and build parse tree"); AslCompilerparse(); UtEndEvent (Event); /* Check for parser-detected syntax errors */ if (AslGbl_SyntaxError) { fprintf (stderr, "Compiler aborting due to parser-detected syntax error(s)\n"); /* Flag this error in the FileNode for compilation summary */ FileNode = FlGetCurrentFileNode (); FileNode->ParserErrorDetected = TRUE; AslGbl_ParserErrorDetected = TRUE; LsDumpParseTree (); goto ErrorExit; } /* Did the parse tree get successfully constructed? */ if (!AslGbl_ParseTreeRoot) { /* * If there are no errors, then we have some sort of * internal problem. */ AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL, "- Could not resolve parse tree root node"); goto ErrorExit; } /* Flush out any remaining source after parse tree is complete */ Event = UtBeginEvent ("Flush source input"); CmFlushSourceCode (); /* Prune the parse tree if requested (debug purposes only) */ if (AslGbl_PruneParseTree) { AslPruneParseTree (AslGbl_PruneDepth, AslGbl_PruneType); } /* Optional parse tree dump, compiler debug output only */ LsDumpParseTree (); OpcGetIntegerWidth (AslGbl_ParseTreeRoot->Asl.Child); UtEndEvent (Event); /* Pre-process parse tree for any operator transforms */ Event = UtBeginEvent ("Parse tree transforms"); DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE, TrAmlTransformWalkBegin, TrAmlTransformWalkEnd, NULL); UtEndEvent (Event); /* Generate AML opcodes corresponding to the parse tokens */ Event = UtBeginEvent ("Generate AML opcodes"); DbgPrint (ASL_DEBUG_OUTPUT, "Generating AML opcodes\n\n"); TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlOpcodeWalk, NULL); UtEndEvent (Event); UtEndEvent (FullCompile); return (AE_OK); ErrorExit: UtEndEvent (FullCompile); return (AE_ERROR); }
int CmDoCompile ( void) { ACPI_STATUS Status; UINT8 FullCompile; UINT8 Event; FullCompile = UtBeginEvent ("*** Total Compile time ***"); Event = UtBeginEvent ("Open input and output files"); UtEndEvent (Event); Event = UtBeginEvent ("Preprocess input file"); if (Gbl_PreprocessFlag) { /* Preprocessor */ PrDoPreprocess (); if (Gbl_PreprocessOnly) { UtEndEvent (Event); CmCleanupAndExit (); return (0); } } UtEndEvent (Event); /* Build the parse tree */ Event = UtBeginEvent ("Parse source code and build parse tree"); AslCompilerparse(); UtEndEvent (Event); /* Check for parser-detected syntax errors */ if (Gbl_SyntaxError) { fprintf (stderr, "Compiler aborting due to parser-detected syntax error(s)\n"); LsDumpParseTree (); goto ErrorExit; } /* Did the parse tree get successfully constructed? */ if (!RootNode) { /* * If there are no errors, then we have some sort of * internal problem. */ AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL, "- Could not resolve parse tree root node"); goto ErrorExit; } /* Flush out any remaining source after parse tree is complete */ Event = UtBeginEvent ("Flush source input"); CmFlushSourceCode (); /* Prune the parse tree if requested (debug purposes only) */ if (Gbl_PruneParseTree) { AslPruneParseTree (Gbl_PruneDepth, Gbl_PruneType); } /* Optional parse tree dump, compiler debug output only */ LsDumpParseTree (); OpcGetIntegerWidth (RootNode); UtEndEvent (Event); /* Pre-process parse tree for any operator transforms */ Event = UtBeginEvent ("Parse tree transforms"); DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, TrAmlTransformWalk, NULL, NULL); UtEndEvent (Event); /* Generate AML opcodes corresponding to the parse tokens */ Event = UtBeginEvent ("Generate AML opcodes"); DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlOpcodeWalk, NULL); UtEndEvent (Event); /* * Now that the input is parsed, we can open the AML output file. * Note: by default, the name of this file comes from the table descriptor * within the input file. */ Event = UtBeginEvent ("Open AML output file"); Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix); UtEndEvent (Event); if (ACPI_FAILURE (Status)) { AePrintErrorLog (ASL_FILE_STDERR); return (-1); } /* Interpret and generate all compile-time constants */ Event = UtBeginEvent ("Constant folding via AML interpreter"); DbgPrint (ASL_DEBUG_OUTPUT, "\nInterpreting compile-time constant expressions\n\n"); if (Gbl_FoldConstants) { TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, OpcAmlConstantWalk, NULL, NULL); } else { DbgPrint (ASL_PARSE_OUTPUT, " Optional folding disabled\n"); } UtEndEvent (Event); /* Update AML opcodes if necessary, after constant folding */ Event = UtBeginEvent ("Updating AML opcodes after constant folding"); DbgPrint (ASL_DEBUG_OUTPUT, "\nUpdating AML opcodes after constant folding\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlOpcodeUpdateWalk, NULL); UtEndEvent (Event); /* Calculate all AML package lengths */ Event = UtBeginEvent ("Generate AML package lengths"); DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, LnPackageLengthWalk, NULL); UtEndEvent (Event); if (Gbl_ParseOnlyFlag) { AePrintErrorLog (ASL_FILE_STDERR); UtDisplaySummary (ASL_FILE_STDERR); if (Gbl_DebugFlag) { /* Print error summary to the stdout also */ AePrintErrorLog (ASL_FILE_STDOUT); UtDisplaySummary (ASL_FILE_STDOUT); } UtEndEvent (FullCompile); return (0); } /* * Create an internal namespace and use it as a symbol table */ /* Namespace loading */ Event = UtBeginEvent ("Create ACPI Namespace"); Status = LdLoadNamespace (RootNode); UtEndEvent (Event); if (ACPI_FAILURE (Status)) { goto ErrorExit; } /* Namespace cross-reference */ AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace"); Status = XfCrossReferenceNamespace (); if (ACPI_FAILURE (Status)) { goto ErrorExit; } /* Namespace - Check for non-referenced objects */ LkFindUnreferencedObjects (); UtEndEvent (AslGbl_NamespaceEvent); /* * Semantic analysis. This can happen only after the * namespace has been loaded and cross-referenced. * * part one - check control methods */ Event = UtBeginEvent ("Analyze control method return types"); AnalysisWalkInfo.MethodStack = NULL; DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, MtMethodAnalysisWalkBegin, MtMethodAnalysisWalkEnd, &AnalysisWalkInfo); UtEndEvent (Event); /* Semantic error checking part two - typing of method returns */ Event = UtBeginEvent ("Determine object types returned by methods"); DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, AnMethodTypingWalkEnd, NULL); UtEndEvent (Event); /* Semantic error checking part three - operand type checking */ Event = UtBeginEvent ("Analyze AML operand types"); DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo); UtEndEvent (Event); /* Semantic error checking part four - other miscellaneous checks */ Event = UtBeginEvent ("Miscellaneous analysis"); DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, AnOtherSemanticAnalysisWalkBegin, NULL, &AnalysisWalkInfo); UtEndEvent (Event); /* Calculate all AML package lengths */ Event = UtBeginEvent ("Finish AML package length generation"); DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, LnInitLengthsWalk, NULL); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, LnPackageLengthWalk, NULL); UtEndEvent (Event); /* Code generation - emit the AML */ Event = UtBeginEvent ("Generate AML code and write output files"); CgGenerateAmlOutput (); UtEndEvent (Event); Event = UtBeginEvent ("Write optional output files"); CmDoOutputFiles (); UtEndEvent (Event); UtEndEvent (FullCompile); CmCleanupAndExit (); return (0); ErrorExit: UtEndEvent (FullCompile); CmCleanupAndExit (); return (-1); }
int CmDoCompile ( void) { ACPI_STATUS Status; UINT8 FullCompile; UINT8 Event; FullCompile = UtBeginEvent ("*** Total Compile time ***"); Event = UtBeginEvent ("Open input and output files"); /* Open the required input and output files */ Status = FlOpenInputFile (Gbl_Files[ASL_FILE_INPUT].Filename); if (ACPI_FAILURE (Status)) { AePrintErrorLog (ASL_FILE_STDERR); return -1; } /* Check for 100% ASCII source file (comments are ignored) */ Status = FlCheckForAscii (&Gbl_Files[ASL_FILE_INPUT]); if (ACPI_FAILURE (Status)) { AePrintErrorLog (ASL_FILE_STDERR); return -1; } Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix); if (ACPI_FAILURE (Status)) { AePrintErrorLog (ASL_FILE_STDERR); return -1; } UtEndEvent (Event); /* Build the parse tree */ Event = UtBeginEvent ("Parse source code and build parse tree"); AslCompilerparse(); UtEndEvent (Event); /* Flush out any remaining source after parse tree is complete */ Event = UtBeginEvent ("Flush source input"); CmFlushSourceCode (); /* Did the parse tree get successfully constructed? */ if (!RootNode) { CmCleanupAndExit (); return -1; } /* Optional parse tree dump, compiler debug output only */ LsDumpParseTree (); OpcGetIntegerWidth (RootNode); UtEndEvent (Event); /* Pre-process parse tree for any operator transforms */ Event = UtBeginEvent ("Parse tree transforms"); DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, TrAmlTransformWalk, NULL, NULL); UtEndEvent (Event); /* Generate AML opcodes corresponding to the parse tokens */ Event = UtBeginEvent ("Generate AML opcodes"); DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlOpcodeWalk, NULL); UtEndEvent (Event); /* * Now that the input is parsed, we can open the AML output file. * Note: by default, the name of this file comes from the table descriptor * within the input file. */ Event = UtBeginEvent ("Open AML output file"); Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix); if (ACPI_FAILURE (Status)) { AePrintErrorLog (ASL_FILE_STDERR); return -1; } UtEndEvent (Event); /* Interpret and generate all compile-time constants */ Event = UtBeginEvent ("Constant folding via AML interpreter"); DbgPrint (ASL_DEBUG_OUTPUT, "\nInterpreting compile-time constant expressions\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, OpcAmlConstantWalk, NULL, NULL); UtEndEvent (Event); /* Update AML opcodes if necessary, after constant folding */ Event = UtBeginEvent ("Updating AML opcodes after constant folding"); DbgPrint (ASL_DEBUG_OUTPUT, "\nUpdating AML opcodes after constant folding\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, OpcAmlOpcodeUpdateWalk, NULL); UtEndEvent (Event); /* Calculate all AML package lengths */ Event = UtBeginEvent ("Generate AML package lengths"); DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, LnPackageLengthWalk, NULL); UtEndEvent (Event); if (Gbl_ParseOnlyFlag) { AePrintErrorLog (ASL_FILE_STDOUT); UtDisplaySummary (ASL_FILE_STDOUT); if (Gbl_DebugFlag) { /* Print error summary to the debug file */ AePrintErrorLog (ASL_FILE_STDERR); UtDisplaySummary (ASL_FILE_STDERR); } return 0; } /* * Create an internal namespace and use it as a symbol table */ /* Namespace loading */ Event = UtBeginEvent ("Create ACPI Namespace"); Status = LdLoadNamespace (RootNode); UtEndEvent (Event); if (ACPI_FAILURE (Status)) { return -1; } /* Namespace cross-reference */ AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace"); Status = LkCrossReferenceNamespace (); if (ACPI_FAILURE (Status)) { return -1; } /* Namespace - Check for non-referenced objects */ LkFindUnreferencedObjects (); UtEndEvent (AslGbl_NamespaceEvent); /* * Semantic analysis. This can happen only after the * namespace has been loaded and cross-referenced. * * part one - check control methods */ Event = UtBeginEvent ("Analyze control method return types"); AnalysisWalkInfo.MethodStack = NULL; DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, AnMethodAnalysisWalkBegin, AnMethodAnalysisWalkEnd, &AnalysisWalkInfo); UtEndEvent (Event); /* Semantic error checking part two - typing of method returns */ Event = UtBeginEvent ("Determine object types returned by methods"); DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin, AnMethodTypingWalkEnd, NULL); UtEndEvent (Event); /* Semantic error checking part three - operand type checking */ Event = UtBeginEvent ("Analyze AML operand types"); DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, AnOperandTypecheckWalkBegin, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo); UtEndEvent (Event); /* Semantic error checking part four - other miscellaneous checks */ Event = UtBeginEvent ("Miscellaneous analysis"); DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, AnOtherSemanticAnalysisWalkBegin, AnOtherSemanticAnalysisWalkEnd, &AnalysisWalkInfo); UtEndEvent (Event); /* Calculate all AML package lengths */ Event = UtBeginEvent ("Finish AML package length generation"); DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n"); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, LnInitLengthsWalk, NULL); TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL, LnPackageLengthWalk, NULL); UtEndEvent (Event); /* Code generation - emit the AML */ Event = UtBeginEvent ("Generate AML code and write output files"); CgGenerateAmlOutput (); UtEndEvent (Event); Event = UtBeginEvent ("Write optional output files"); CmDoOutputFiles (); UtEndEvent (Event); UtEndEvent (FullCompile); CmCleanupAndExit (); return 0; }
static ACPI_STATUS TrTransformToStoreOp ( ACPI_PARSE_OBJECT *Op, ACPI_WALK_STATE *WalkState) { ACPI_PARSE_OBJECT *OriginalTarget; ACPI_PARSE_OBJECT *NewTarget; ACPI_PARSE_OBJECT *Child1; ACPI_PARSE_OBJECT *Child2; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_PARSE_OBJECT *NewParent; ACPI_PARSE_OBJECT *OriginalParent; ACPI_STATUS Status; /* Extract the operands */ Child1 = Op->Asl.Child; Child2 = Child1->Asl.Next; /* * Special case for DIVIDE -- it has two targets. The first * is for the remainder and if present, we will not attempt * to reduce the expression. */ if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE) { Child2 = Child2->Asl.Next; if (Child2->Asl.ParseOpcode != PARSEOP_ZERO) { DbgPrint (ASL_PARSE_OUTPUT, "Cannot reduce DIVIDE - has two targets\n\n"); return (AE_OK); } } DbgPrint (ASL_PARSE_OUTPUT, "Reduction/Transform to StoreOp: Store(%s, %s)\n", Child1->Asl.ParseOpName, Child2->Asl.ParseOpName); /* * Create a NULL (zero) target so that we can use the * interpreter to evaluate the expression. */ NewTarget = TrCreateNullTarget (); NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP; /* Handle one-operand cases (NOT, TOBCD, etc.) */ if (!Child2->Asl.Next) { Child2 = Child1; } /* Link in new NULL target as the last operand */ OriginalTarget = Child2->Asl.Next; Child2->Asl.Next = NewTarget; NewTarget->Asl.Parent = OriginalTarget->Asl.Parent; NewParent = TrAllocateNode (PARSEOP_INTEGER); NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; OriginalParent = Op->Common.Parent; Op->Common.Parent = NewParent; /* Hand off the subtree to the AML interpreter */ WalkState->CallerReturnDesc = &ObjDesc; Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); if (ACPI_FAILURE (Status)) { DbgPrint (ASL_PARSE_OUTPUT, "Constant Subtree evaluation(3), %s\n", AcpiFormatException (Status)); goto EvalError; } /* Get the final result */ Status = AcpiDsResultPop (&ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { DbgPrint (ASL_PARSE_OUTPUT, "Constant Subtree evaluation(4), %s\n", AcpiFormatException (Status)); goto EvalError; } /* Truncate any subtree expressions, they have been evaluated */ Child1->Asl.Child = NULL; /* Folded constant is in ObjDesc, store into Child1 */ TrInstallReducedConstant (Child1, ObjDesc); /* Convert operator to STORE */ Op->Asl.ParseOpcode = PARSEOP_STORE; Op->Asl.AmlOpcode = AML_STORE_OP; UtSetParseOpName (Op); Op->Common.Parent = OriginalParent; /* First child is the folded constant */ /* Second child will be the target */ Child1->Asl.Next = OriginalTarget; return (AE_OK); EvalError: /* Restore original links */ Op->Common.Parent = OriginalParent; Child2->Asl.Next = OriginalTarget; return (Status); }
static ACPI_STATUS TrSimpleConstantReduction ( ACPI_PARSE_OBJECT *Op, ACPI_WALK_STATE *WalkState) { ACPI_PARSE_OBJECT *RootOp; ACPI_PARSE_OBJECT *OriginalParentOp; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; DbgPrint (ASL_PARSE_OUTPUT, "Simple subtree constant reduction, operator to constant\n"); /* Allocate a new temporary root for this subtree */ RootOp = TrAllocateNode (PARSEOP_INTEGER); if (!RootOp) { return (AE_NO_MEMORY); } RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; OriginalParentOp = Op->Common.Parent; Op->Common.Parent = RootOp; /* Hand off the subtree to the AML interpreter */ WalkState->CallerReturnDesc = &ObjDesc; Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); /* Restore original parse tree */ Op->Common.Parent = OriginalParentOp; if (ACPI_FAILURE (Status)) { DbgPrint (ASL_PARSE_OUTPUT, "Constant Subtree evaluation(1), %s\n", AcpiFormatException (Status)); return (Status); } /* Get the final result */ Status = AcpiDsResultPop (&ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { DbgPrint (ASL_PARSE_OUTPUT, "Constant Subtree evaluation(2), %s\n", AcpiFormatException (Status)); return (Status); } /* Disconnect any existing children, install new constant */ Op->Asl.Child = NULL; TrInstallReducedConstant (Op, ObjDesc); UtSetParseOpName (Op); return (AE_OK); }
ACPI_STATUS OpcAmlConstantWalk ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState; ACPI_STATUS Status = AE_OK; if (Op->Asl.CompileFlags == 0) { return (AE_OK); } /* * Only interested in subtrees that could possibly contain * expressions that can be evaluated at this time */ if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) || (Op->Asl.CompileFlags & NODE_IS_TARGET)) { return (AE_OK); } /* Create a new walk state */ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); if (!WalkState) { return (AE_NO_MEMORY); } WalkState->NextOp = NULL; WalkState->Params = NULL; /* * Examine the entire subtree -- all nodes must be constants * or type 3/4/5 opcodes */ Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, OpcAmlCheckForConstant, NULL, WalkState); /* * Did we find an entire subtree that contains all constants * and type 3/4/5 opcodes? */ switch (Status) { case AE_OK: /* Simple case, like Add(3,4) -> 7 */ Status = TrSimpleConstantReduction (Op, WalkState); break; case AE_CTRL_RETURN_VALUE: /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */ Status = TrTransformToStoreOp (Op, WalkState); break; case AE_TYPE: AcpiDsDeleteWalkState (WalkState); return (AE_OK); default: AcpiDsDeleteWalkState (WalkState); break; } if (ACPI_FAILURE (Status)) { DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n", AcpiFormatException (Status)); /* We could not resolve the subtree for some reason */ AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op, (char *) AcpiFormatException (Status)); /* Set the subtree value to ZERO anyway. Eliminates further errors */ OpcUpdateIntegerNode (Op, 0); } return (AE_OK); }