Path: blob/main/sys/contrib/dev/acpica/compiler/aslmethod.c
48371 views
/******************************************************************************1*2* Module Name: aslmethod.c - Control method analysis walk3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/compiler/aslcompiler.h>152#include "aslcompiler.y.h"153#include <contrib/dev/acpica/include/acnamesp.h>154#include <contrib/dev/acpica/include/acparser.h>155#include <contrib/dev/acpica/include/amlcode.h>156157158#define _COMPONENT ACPI_COMPILER159ACPI_MODULE_NAME ("aslmethod")160161162/* Local prototypes */163164static void165MtCheckNamedObjectInMethod (166ACPI_PARSE_OBJECT *Op,167ASL_METHOD_INFO *MethodInfo);168169static void170MtCheckStaticOperationRegionInMethod (171ACPI_PARSE_OBJECT *Op);172173174/*******************************************************************************175*176* FUNCTION: MtMethodAnalysisWalkBegin177*178* PARAMETERS: ASL_WALK_CALLBACK179*180* RETURN: Status181*182* DESCRIPTION: Descending callback for the analysis walk. Check methods for:183* 1) Initialized local variables184* 2) Valid arguments185* 3) Return types186*187******************************************************************************/188189ACPI_STATUS190MtMethodAnalysisWalkBegin (191ACPI_PARSE_OBJECT *Op,192UINT32 Level,193void *Context)194{195ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;196ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;197ACPI_PARSE_OBJECT *Next;198UINT32 RegisterNumber;199UINT32 i;200char LocalName[] = "Local0";201char ArgName[] = "Arg0";202ACPI_PARSE_OBJECT *ArgNode;203ACPI_PARSE_OBJECT *NextType;204UINT8 ActualArgs = 0;205BOOLEAN HidExists;206BOOLEAN AdrExists;207BOOLEAN PrsExists;208BOOLEAN CrsExists;209BOOLEAN SrsExists;210BOOLEAN DisExists;211212213/* Build cross-reference output file if requested */214215if (AslGbl_CrossReferenceOutput)216{217OtXrefWalkPart1 (Op, Level, MethodInfo);218}219220switch (Op->Asl.ParseOpcode)221{222case PARSEOP_METHOD:223224AslGbl_TotalMethods++;225226/* Create and init method info */227228MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));229MethodInfo->Next = WalkInfo->MethodStack;230MethodInfo->Op = Op;231232WalkInfo->MethodStack = MethodInfo;233234/*235* Special handling for _PSx methods. Dependency rules (same scope):236*237* 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3238* 2) _PS1/_PS2/_PS3: A _PS0 must exist239*/240if (ACPI_COMPARE_NAMESEG (METHOD_NAME__PS0, Op->Asl.NameSeg))241{242/* For _PS0, one of _PS1/_PS2/_PS3 must exist */243244if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) &&245(!ApFindNameInScope (METHOD_NAME__PS2, Op)) &&246(!ApFindNameInScope (METHOD_NAME__PS3, Op)))247{248AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,249"_PS0 requires one of _PS1/_PS2/_PS3 in same scope");250}251}252else if (253ACPI_COMPARE_NAMESEG (METHOD_NAME__PS1, Op->Asl.NameSeg) ||254ACPI_COMPARE_NAMESEG (METHOD_NAME__PS2, Op->Asl.NameSeg) ||255ACPI_COMPARE_NAMESEG (METHOD_NAME__PS3, Op->Asl.NameSeg))256{257/* For _PS1/_PS2/_PS3, a _PS0 must exist */258259if (!ApFindNameInScope (METHOD_NAME__PS0, Op))260{261sprintf (AslGbl_MsgBuffer,262"%4.4s requires _PS0 in same scope", Op->Asl.NameSeg);263264AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,265AslGbl_MsgBuffer);266}267}268269/* Get the name node */270271Next = Op->Asl.Child;272273/* Get the NumArguments node */274275Next = Next->Asl.Next;276MethodInfo->NumArguments = (UINT8)277(((UINT8) Next->Asl.Value.Integer) & 0x07);278279/* Get the SerializeRule and SyncLevel nodes, ignored here */280281Next = Next->Asl.Next;282MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer;283284Next = Next->Asl.Next;285ArgNode = Next;286287/* Get the ReturnType node */288289Next = Next->Asl.Next;290291NextType = Next->Asl.Child;292293MethodInfo->ValidReturnTypes = MtProcessTypeOp (NextType);294Op->Asl.AcpiBtype |= MethodInfo->ValidReturnTypes;295296/* Get the ParameterType node */297298Next = Next->Asl.Next;299300NextType = Next->Asl.Child;301if (!NextType)302{303/*304* The optional parameter types list was omitted at the source305* level. Use the Argument count parameter instead.306*/307ActualArgs = MethodInfo->NumArguments;308}309else310{311ActualArgs = MtProcessParameterTypeList (NextType,312MethodInfo->ValidArgTypes);313MethodInfo->NumArguments = ActualArgs;314ArgNode->Asl.Value.Integer |= ActualArgs;315}316317if ((MethodInfo->NumArguments) &&318(MethodInfo->NumArguments != ActualArgs))319{320sprintf (AslGbl_MsgBuffer,321"Length = %u", ActualArgs);322AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_MISMATCH,323Op->Asl.Child->Asl.Next, AslGbl_MsgBuffer);324}325326/* Allow numarguments == 0 for Function() */327328if ((!MethodInfo->NumArguments) && (ActualArgs))329{330MethodInfo->NumArguments = ActualArgs;331ArgNode->Asl.Value.Integer |= ActualArgs;332}333334/*335* Actual arguments are initialized at method entry.336* All other ArgX "registers" can be used as locals, so we337* track their initialization.338*/339for (i = 0; i < MethodInfo->NumArguments; i++)340{341MethodInfo->ArgInitialized[i] = TRUE;342}343break;344345case PARSEOP_METHODCALL:346347/* Check for a recursive method call */348349if (MethodInfo &&350(Op->Asl.Node == MethodInfo->Op->Asl.Node))351{352if (MethodInfo->CreatesNamedObjects)353{354/*355* This is an error, as it will fail at runtime on all ACPI356* implementations. Any named object declarations will be357* executed twice, causing failure the second time. Note,358* this is independent of whether the method is declared359* Serialized, because the same thread is attempting to360* reenter the method, and this will always succeed.361*/362AslDualParseOpError (ASL_ERROR, ASL_MSG_ILLEGAL_RECURSION, Op,363Op->Asl.Value.String, ASL_MSG_FOUND_HERE, MethodInfo->Op,364MethodInfo->Op->Asl.ExternalName);365}366else367{368/* Method does not create objects, issue a remark */369370AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);371}372}373break;374375case PARSEOP_LOCAL0:376case PARSEOP_LOCAL1:377case PARSEOP_LOCAL2:378case PARSEOP_LOCAL3:379case PARSEOP_LOCAL4:380case PARSEOP_LOCAL5:381case PARSEOP_LOCAL6:382case PARSEOP_LOCAL7:383384if (!MethodInfo)385{386/*387* Local was used outside a control method, or there was an error388* in the method declaration.389*/390AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,391Op, Op->Asl.ExternalName);392return (AE_ERROR);393}394395RegisterNumber = (Op->Asl.AmlOpcode & 0x0007);396397/*398* If the local is being used as a target, mark the local399* initialized400*/401if (Op->Asl.CompileFlags & OP_IS_TARGET)402{403MethodInfo->LocalInitialized[RegisterNumber] = TRUE;404}405406/*407* Otherwise, this is a reference, check if the local408* has been previously initialized.409*410* The only operator that accepts an uninitialized value is ObjectType()411*/412else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&413(Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))414{415LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);416AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);417}418break;419420case PARSEOP_ARG0:421case PARSEOP_ARG1:422case PARSEOP_ARG2:423case PARSEOP_ARG3:424case PARSEOP_ARG4:425case PARSEOP_ARG5:426case PARSEOP_ARG6:427428if (!MethodInfo)429{430/*431* Arg was used outside a control method, or there was an error432* in the method declaration.433*/434AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,435Op, Op->Asl.ExternalName);436return (AE_ERROR);437}438439RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;440ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);441442/*443* If the Arg is being used as a target, mark the local444* initialized445*/446if (Op->Asl.CompileFlags & OP_IS_TARGET)447{448MethodInfo->ArgInitialized[RegisterNumber] = TRUE;449}450451/*452* Otherwise, this is a reference, check if the Arg453* has been previously initialized.454*455* The only operator that accepts an uninitialized value is ObjectType()456*/457else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&458(Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))459{460AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);461}462463/* Flag this arg if it is not a "real" argument to the method */464465if (RegisterNumber >= MethodInfo->NumArguments)466{467AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);468}469break;470471case PARSEOP_RETURN:472473if (!MethodInfo)474{475/*476* Probably was an error in the method declaration,477* no additional error here478*/479ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));480return (AE_ERROR);481}482483/*484* A child indicates a possible return value. A simple Return or485* Return() is marked with OP_IS_NULL_RETURN by the parser so486* that it is not counted as a "real" return-with-value, although487* the AML code that is actually emitted is Return(0). The AML488* definition of Return has a required parameter, so we are489* forced to convert a null return to Return(0).490*/491if ((Op->Asl.Child) &&492(Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&493(!(Op->Asl.Child->Asl.CompileFlags & OP_IS_NULL_RETURN)))494{495MethodInfo->NumReturnWithValue++;496}497else498{499MethodInfo->NumReturnNoValue++;500}501break;502503case PARSEOP_BREAK:504case PARSEOP_CONTINUE:505506Next = Op->Asl.Parent;507while (Next)508{509if (Next->Asl.ParseOpcode == PARSEOP_WHILE)510{511break;512}513Next = Next->Asl.Parent;514}515516if (!Next)517{518AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);519}520break;521522case PARSEOP_STALL:523524/* We can range check if the argument is an integer */525526if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&527(Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))528{529AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);530}531break;532533case PARSEOP_DEVICE:534535/* Check usage of _HID and _ADR objects */536537HidExists = ApFindNameInDeviceTree (METHOD_NAME__HID, Op);538AdrExists = ApFindNameInDeviceTree (METHOD_NAME__ADR, Op);539540if (!HidExists && !AdrExists)541{542AslError (ASL_ERROR, ASL_MSG_MISSING_DEPENDENCY, Op,543"Device object requires a _HID or _ADR");544}545else if (HidExists && AdrExists)546{547/*548* "A device object must contain either an _HID object or549* an _ADR object, but must not contain both".550* (ACPI spec 6.3, Errata A Section 6.1, page 327)551*/552AslError (ASL_WARNING, ASL_MSG_MULTIPLE_TYPES, Op,553"Device object requires either a _HID or _ADR, but not both");554}555556/*557* Check usage of _CRS, _DIS, _PRS, and _SRS objects (July 2021).558*559* Under the Device Object:560*561* 1) If _PRS present, must have _CRS and _SRS562* 2) If _SRS present, must have _PRS (_PRS requires _CRS and _SRS)563* 3) If _DIS present, must have _SRS (_SRS requires _PRS, _PRS requires _CRS and _SRS)564* 4) If _SRS present, probably should have a _DIS (Remark only)565*/566CrsExists = ApFindNameInDeviceTree (METHOD_NAME__CRS, Op);567DisExists = ApFindNameInDeviceTree (METHOD_NAME__DIS, Op);568PrsExists = ApFindNameInDeviceTree (METHOD_NAME__PRS, Op);569SrsExists = ApFindNameInDeviceTree (METHOD_NAME__SRS, Op);570571/* 1) If _PRS is present, must have a _CRS and _SRS */572573if (PrsExists)574{575if (!CrsExists)576{577AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,578"Device has a _PRS, missing a _CRS, required");579}580if (!SrsExists)581{582AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,583"Device has a _PRS, missing a _SRS, required");584}585}586587/* 2) If _SRS is present, must have _PRS (_PRS requires _CRS and _SRS) */588589if ((SrsExists) && (!PrsExists))590{591AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,592"Device has a _SRS, missing a _PRS, required");593}594595/* 3) If _DIS is present, must have a _SRS */596597if ((DisExists) && (!SrsExists))598{599AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,600"Device has a _DIS, missing a _SRS, required");601}602603/*604* 4) If _SRS is present, should have a _DIS (_PRS requires _CRS605* and _SRS) Remark only.606*/607if ((SrsExists) && (!DisExists))608{609AslError (ASL_REMARK, ASL_MSG_MISSING_DEPENDENCY, Op,610"Device has a _SRS, no corresponding _DIS");611}612break;613614case PARSEOP_EVENT:615case PARSEOP_MUTEX:616case PARSEOP_OPERATIONREGION:617case PARSEOP_POWERRESOURCE:618case PARSEOP_PROCESSOR:619case PARSEOP_THERMALZONE:620621/*622* The first operand is a name to be created in the namespace.623* Check against the reserved list.624*/625i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);626if (i < ACPI_VALID_RESERVED_NAME_MAX)627{628AslError (ASL_ERROR, ASL_MSG_RESERVED_USE,629Op, Op->Asl.ExternalName);630}631632MtCheckStaticOperationRegionInMethod (Op);633break;634635case PARSEOP_NAME:636637/* Typecheck any predefined names statically defined with Name() */638639ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);640641/* Special typechecking for _HID */642643if (ACPI_COMPARE_NAMESEG (METHOD_NAME__HID, Op->Asl.NameSeg))644{645Next = Op->Asl.Child->Asl.Next;646AnCheckId (Next, ASL_TYPE_HID);647}648649/* Special typechecking for _CID */650651else if (ACPI_COMPARE_NAMESEG (METHOD_NAME__CID, Op->Asl.NameSeg))652{653Next = Op->Asl.Child->Asl.Next;654655if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||656(Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))657{658Next = Next->Asl.Child;659while (Next)660{661AnCheckId (Next, ASL_TYPE_CID);662Next = Next->Asl.Next;663}664}665else666{667AnCheckId (Next, ASL_TYPE_CID);668}669}670671break;672673default:674675break;676}677678/* Check for named object creation within a non-serialized method */679680MtCheckNamedObjectInMethod (Op, MethodInfo);681return (AE_OK);682}683684685/*******************************************************************************686*687* FUNCTION: MtProcessTypeOp688*689* PARAMETERS: Op - Op representing a btype690*691* RETURN: Btype represented by Op692*693* DESCRIPTION: Process a parse object that represents single parameter type or694* a return type in method, function, and external declarations.695*696******************************************************************************/697698UINT32699MtProcessTypeOp (700ACPI_PARSE_OBJECT *TypeOp)701{702UINT32 Btype = ACPI_BTYPE_ANY;703704705while (TypeOp)706{707Btype |= AnMapObjTypeToBtype (TypeOp);708TypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;709TypeOp = TypeOp->Asl.Next;710}711712return (Btype);713}714715716/*******************************************************************************717*718* FUNCTION: MtProcessParameterTypeList719*720* PARAMETERS: Op - Op representing a btype721*722* RETURN: Btype represented by Op723*724* DESCRIPTION: Process a parse object that represents a parameter type list in725* method, function, and external declarations.726*727******************************************************************************/728729UINT8730MtProcessParameterTypeList (731ACPI_PARSE_OBJECT *ParamTypeOp,732UINT32 *TypeList)733{734UINT8 ParameterCount = 0;735736737if (ParamTypeOp && ParamTypeOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)738{739/* Special case for a single parameter without braces */740741TypeList[ParameterCount] =742MtProcessTypeOp (ParamTypeOp);743744return (1);745}746747while (ParamTypeOp)748{749TypeList[ParameterCount] =750MtProcessTypeOp (ParamTypeOp->Asl.Child);751752ParameterCount++;753ParamTypeOp = ParamTypeOp->Asl.Next;754}755756return (ParameterCount);757}758759760/*******************************************************************************761*762* FUNCTION: MtCheckNamedObjectInMethod763*764* PARAMETERS: Op - Current parser op765* MethodInfo - Info for method being parsed766*767* RETURN: None768*769* DESCRIPTION: Detect if a non-serialized method is creating a named object,770* which could possibly cause problems if two threads execute771* the method concurrently. Emit a remark in this case.772*773******************************************************************************/774775static void776MtCheckNamedObjectInMethod (777ACPI_PARSE_OBJECT *Op,778ASL_METHOD_INFO *MethodInfo)779{780const ACPI_OPCODE_INFO *OpInfo;781char *ExternalPath;782783784/* We don't care about actual method declarations or scopes */785786if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||787(Op->Asl.AmlOpcode == AML_SCOPE_OP))788{789return;790}791792/* Determine if we are creating a named object within a method */793794if (!MethodInfo)795{796return;797}798799OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);800if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_FIELD_OP))801{802/*803* 1) Mark the method as a method that creates named objects.804*805* 2) Issue a remark indicating the inefficiency of creating named806* objects within a method (Except for compiler-emitted temporary807* variables).808*809* 3) If the method is non-serialized, emit a remark that the method810* should be serialized.811*812* Reason: If a thread blocks within the method for any reason, and813* another thread enters the method, the method will fail because814* an attempt will be made to create the same object twice.815*816* Note: The Field opcode is disallowed here because Field() does not817* create a new named object.818*/819ExternalPath = AcpiNsGetNormalizedPathname (MethodInfo->Op->Asl.Node, TRUE);820821/* No error for compiler temp variables (name starts with "_T_") */822823if ((Op->Asl.NameSeg[0] != '_') &&824(Op->Asl.NameSeg[1] != 'T') &&825(Op->Asl.NameSeg[2] != '_'))826{827AslError (ASL_REMARK, ASL_MSG_NAMED_OBJECT_CREATION, Op,828ExternalPath);829}830831MethodInfo->CreatesNamedObjects = TRUE;832if (!MethodInfo->ShouldBeSerialized)833{834AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,835ExternalPath);836837/* Emit message only ONCE per method */838839MethodInfo->ShouldBeSerialized = TRUE;840}841842if (ExternalPath)843{844ACPI_FREE (ExternalPath);845}846}847}848849850/*******************************************************************************851*852* FUNCTION: MtCheckStaticOperationRegionInMethod853*854* PARAMETERS: Op - Current parser op855*856* RETURN: None857*858* DESCRIPTION: Warns if an Operation Region with static address or length859* is declared inside a control method860*861******************************************************************************/862863static void864MtCheckStaticOperationRegionInMethod(865ACPI_PARSE_OBJECT* Op)866{867ACPI_PARSE_OBJECT* AddressOp;868ACPI_PARSE_OBJECT* LengthOp;869870871if (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION)872{873return;874}875876/*877* OperationRegion should have 4 arguments defined. At this point, we878* assume that the parse tree is well-formed.879*/880AddressOp = Op->Asl.Child->Asl.Next->Asl.Next;881LengthOp = Op->Asl.Child->Asl.Next->Asl.Next->Asl.Next;882883if (UtGetParentMethodOp (Op) &&884AddressOp->Asl.ParseOpcode == PARSEOP_INTEGER &&885LengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)886{887/*888* At this point, a static operation region declared inside of a889* control method has been found. Throw a warning because this is890* highly inefficient.891*/892AslError(ASL_WARNING, ASL_MSG_STATIC_OPREGION_IN_METHOD, Op, NULL);893}894895return;896}897898899/*******************************************************************************900*901* FUNCTION: MtMethodAnalysisWalkEnd902*903* PARAMETERS: ASL_WALK_CALLBACK904*905* RETURN: Status906*907* DESCRIPTION: Ascending callback for analysis walk. Complete method908* return analysis.909*910******************************************************************************/911912ACPI_STATUS913MtMethodAnalysisWalkEnd (914ACPI_PARSE_OBJECT *Op,915UINT32 Level,916void *Context)917{918ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;919ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;920char *ExternalPath;921922923switch (Op->Asl.ParseOpcode)924{925case PARSEOP_METHOD:926case PARSEOP_RETURN:927928if (!MethodInfo)929{930printf ("No method info for method! [%s]\n", Op->Asl.Namepath);931AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,932"No method info for this method");933934CmCleanupAndExit ();935return (AE_AML_INTERNAL);936}937break;938939default:940941break;942}943944switch (Op->Asl.ParseOpcode)945{946case PARSEOP_METHOD:947948WalkInfo->MethodStack = MethodInfo->Next;949950/*951* Check if there is no return statement at the end of the952* method AND we can actually get there -- i.e., the execution953* of the method can possibly terminate without a return statement.954*/955if ((!AnLastStatementIsReturn (Op)) &&956(!(Op->Asl.CompileFlags & OP_HAS_NO_EXIT)))957{958/*959* No return statement, and execution can possibly exit960* via this path. This is equivalent to Return ()961*/962MethodInfo->NumReturnNoValue++;963}964965/*966* Check for case where some return statements have a return value967* and some do not. Exit without a return statement is a return with968* no value969*/970if (MethodInfo->NumReturnNoValue &&971MethodInfo->NumReturnWithValue)972{973ExternalPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);974975AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,976ExternalPath);977978if (ExternalPath)979{980ACPI_FREE (ExternalPath);981}982}983984/*985* If there are any RETURN() statements with no value, or there is a986* control path that allows the method to exit without a return value,987* we mark the method as a method that does not return a value. This988* knowledge can be used to check method invocations that expect a989* returned value.990*/991if (MethodInfo->NumReturnNoValue)992{993if (MethodInfo->NumReturnWithValue)994{995Op->Asl.CompileFlags |= OP_METHOD_SOME_NO_RETVAL;996}997else998{999Op->Asl.CompileFlags |= OP_METHOD_NO_RETVAL;1000}1001}10021003/*1004* Check predefined method names for correct return behavior1005* and correct number of arguments. Also, some special checks1006* For GPE and _REG methods.1007*/1008if (ApCheckForPredefinedMethod (Op, MethodInfo))1009{1010/* Special check for two names like _L01 and _E01 in same scope */10111012ApCheckForGpeNameConflict (Op);10131014/*1015* Special check for _REG: Must have an operation region definition1016* within the same scope!1017*/1018ApCheckRegMethod (Op);1019}10201021ACPI_FREE (MethodInfo);1022break;10231024case PARSEOP_NAME:10251026/* Special check for two names like _L01 and _E01 in same scope */10271028ApCheckForGpeNameConflict (Op);1029break;10301031case PARSEOP_RETURN:10321033/*1034* If the parent is a predefined method name, attempt to typecheck1035* the return value. Only static types can be validated.1036*/1037ApCheckPredefinedReturnValue (Op, MethodInfo);10381039/*1040* The parent block does not "exit" and continue execution -- the1041* method is terminated here with the Return() statement.1042*/1043Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;10441045/* Used in the "typing" pass later */10461047Op->Asl.ParentMethod = MethodInfo->Op;10481049/*1050* If there is a peer node after the return statement, then this1051* node is unreachable code -- i.e., it won't be executed because of1052* the preceding Return() statement.1053*/1054if (Op->Asl.Next)1055{1056AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE,1057Op->Asl.Next, NULL);1058}1059break;10601061case PARSEOP_IF:10621063if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&1064(Op->Asl.Next) &&1065(Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))1066{1067/*1068* This IF has a corresponding ELSE. The IF block has no exit,1069* (it contains an unconditional Return)1070* mark the ELSE block to remember this fact.1071*/1072Op->Asl.Next->Asl.CompileFlags |= OP_IF_HAS_NO_EXIT;1073}1074break;10751076case PARSEOP_ELSE:10771078if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&1079(Op->Asl.CompileFlags & OP_IF_HAS_NO_EXIT))1080{1081/*1082* This ELSE block has no exit and the corresponding IF block1083* has no exit either. Therefore, the parent node has no exit.1084*/1085Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;1086}1087break;108810891090default:10911092if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&1093(Op->Asl.Parent))1094{1095/* If this node has no exit, then the parent has no exit either */10961097Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;1098}1099break;1100}11011102return (AE_OK);1103}110411051106