1*efcc2a30SJung-uk Kim /****************************************************************************** 2*efcc2a30SJung-uk Kim * 3*efcc2a30SJung-uk Kim * Module Name: aslmethod.c - Control method analysis walk 4*efcc2a30SJung-uk Kim * 5*efcc2a30SJung-uk Kim *****************************************************************************/ 6*efcc2a30SJung-uk Kim 7*efcc2a30SJung-uk Kim /* 8*efcc2a30SJung-uk Kim * Copyright (C) 2000 - 2013, Intel Corp. 9*efcc2a30SJung-uk Kim * All rights reserved. 10*efcc2a30SJung-uk Kim * 11*efcc2a30SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12*efcc2a30SJung-uk Kim * modification, are permitted provided that the following conditions 13*efcc2a30SJung-uk Kim * are met: 14*efcc2a30SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15*efcc2a30SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16*efcc2a30SJung-uk Kim * without modification. 17*efcc2a30SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18*efcc2a30SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19*efcc2a30SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20*efcc2a30SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21*efcc2a30SJung-uk Kim * binary redistribution. 22*efcc2a30SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23*efcc2a30SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24*efcc2a30SJung-uk Kim * from this software without specific prior written permission. 25*efcc2a30SJung-uk Kim * 26*efcc2a30SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27*efcc2a30SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28*efcc2a30SJung-uk Kim * Software Foundation. 29*efcc2a30SJung-uk Kim * 30*efcc2a30SJung-uk Kim * NO WARRANTY 31*efcc2a30SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32*efcc2a30SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33*efcc2a30SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34*efcc2a30SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35*efcc2a30SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*efcc2a30SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*efcc2a30SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*efcc2a30SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39*efcc2a30SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40*efcc2a30SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41*efcc2a30SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42*efcc2a30SJung-uk Kim */ 43*efcc2a30SJung-uk Kim 44*efcc2a30SJung-uk Kim 45*efcc2a30SJung-uk Kim #include <contrib/dev/acpica/compiler/aslcompiler.h> 46*efcc2a30SJung-uk Kim #include "aslcompiler.y.h" 47*efcc2a30SJung-uk Kim 48*efcc2a30SJung-uk Kim 49*efcc2a30SJung-uk Kim #define _COMPONENT ACPI_COMPILER 50*efcc2a30SJung-uk Kim ACPI_MODULE_NAME ("aslmethod") 51*efcc2a30SJung-uk Kim 52*efcc2a30SJung-uk Kim 53*efcc2a30SJung-uk Kim /******************************************************************************* 54*efcc2a30SJung-uk Kim * 55*efcc2a30SJung-uk Kim * FUNCTION: MtMethodAnalysisWalkBegin 56*efcc2a30SJung-uk Kim * 57*efcc2a30SJung-uk Kim * PARAMETERS: ASL_WALK_CALLBACK 58*efcc2a30SJung-uk Kim * 59*efcc2a30SJung-uk Kim * RETURN: Status 60*efcc2a30SJung-uk Kim * 61*efcc2a30SJung-uk Kim * DESCRIPTION: Descending callback for the analysis walk. Check methods for: 62*efcc2a30SJung-uk Kim * 1) Initialized local variables 63*efcc2a30SJung-uk Kim * 2) Valid arguments 64*efcc2a30SJung-uk Kim * 3) Return types 65*efcc2a30SJung-uk Kim * 66*efcc2a30SJung-uk Kim ******************************************************************************/ 67*efcc2a30SJung-uk Kim 68*efcc2a30SJung-uk Kim ACPI_STATUS 69*efcc2a30SJung-uk Kim MtMethodAnalysisWalkBegin ( 70*efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *Op, 71*efcc2a30SJung-uk Kim UINT32 Level, 72*efcc2a30SJung-uk Kim void *Context) 73*efcc2a30SJung-uk Kim { 74*efcc2a30SJung-uk Kim ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 75*efcc2a30SJung-uk Kim ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 76*efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *Next; 77*efcc2a30SJung-uk Kim UINT32 RegisterNumber; 78*efcc2a30SJung-uk Kim UINT32 i; 79*efcc2a30SJung-uk Kim char LocalName[] = "Local0"; 80*efcc2a30SJung-uk Kim char ArgName[] = "Arg0"; 81*efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *ArgNode; 82*efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *NextType; 83*efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *NextParamType; 84*efcc2a30SJung-uk Kim UINT8 ActualArgs = 0; 85*efcc2a30SJung-uk Kim 86*efcc2a30SJung-uk Kim 87*efcc2a30SJung-uk Kim switch (Op->Asl.ParseOpcode) 88*efcc2a30SJung-uk Kim { 89*efcc2a30SJung-uk Kim case PARSEOP_METHOD: 90*efcc2a30SJung-uk Kim 91*efcc2a30SJung-uk Kim TotalMethods++; 92*efcc2a30SJung-uk Kim 93*efcc2a30SJung-uk Kim /* Create and init method info */ 94*efcc2a30SJung-uk Kim 95*efcc2a30SJung-uk Kim MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 96*efcc2a30SJung-uk Kim MethodInfo->Next = WalkInfo->MethodStack; 97*efcc2a30SJung-uk Kim MethodInfo->Op = Op; 98*efcc2a30SJung-uk Kim 99*efcc2a30SJung-uk Kim WalkInfo->MethodStack = MethodInfo; 100*efcc2a30SJung-uk Kim 101*efcc2a30SJung-uk Kim /* Get the name node, ignored here */ 102*efcc2a30SJung-uk Kim 103*efcc2a30SJung-uk Kim Next = Op->Asl.Child; 104*efcc2a30SJung-uk Kim 105*efcc2a30SJung-uk Kim /* Get the NumArguments node */ 106*efcc2a30SJung-uk Kim 107*efcc2a30SJung-uk Kim Next = Next->Asl.Next; 108*efcc2a30SJung-uk Kim MethodInfo->NumArguments = (UINT8) 109*efcc2a30SJung-uk Kim (((UINT8) Next->Asl.Value.Integer) & 0x07); 110*efcc2a30SJung-uk Kim 111*efcc2a30SJung-uk Kim /* Get the SerializeRule and SyncLevel nodes, ignored here */ 112*efcc2a30SJung-uk Kim 113*efcc2a30SJung-uk Kim Next = Next->Asl.Next; 114*efcc2a30SJung-uk Kim Next = Next->Asl.Next; 115*efcc2a30SJung-uk Kim ArgNode = Next; 116*efcc2a30SJung-uk Kim 117*efcc2a30SJung-uk Kim /* Get the ReturnType node */ 118*efcc2a30SJung-uk Kim 119*efcc2a30SJung-uk Kim Next = Next->Asl.Next; 120*efcc2a30SJung-uk Kim 121*efcc2a30SJung-uk Kim NextType = Next->Asl.Child; 122*efcc2a30SJung-uk Kim while (NextType) 123*efcc2a30SJung-uk Kim { 124*efcc2a30SJung-uk Kim /* Get and map each of the ReturnTypes */ 125*efcc2a30SJung-uk Kim 126*efcc2a30SJung-uk Kim MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); 127*efcc2a30SJung-uk Kim NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 128*efcc2a30SJung-uk Kim NextType = NextType->Asl.Next; 129*efcc2a30SJung-uk Kim } 130*efcc2a30SJung-uk Kim 131*efcc2a30SJung-uk Kim /* Get the ParameterType node */ 132*efcc2a30SJung-uk Kim 133*efcc2a30SJung-uk Kim Next = Next->Asl.Next; 134*efcc2a30SJung-uk Kim 135*efcc2a30SJung-uk Kim NextType = Next->Asl.Child; 136*efcc2a30SJung-uk Kim while (NextType) 137*efcc2a30SJung-uk Kim { 138*efcc2a30SJung-uk Kim if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 139*efcc2a30SJung-uk Kim { 140*efcc2a30SJung-uk Kim NextParamType = NextType->Asl.Child; 141*efcc2a30SJung-uk Kim while (NextParamType) 142*efcc2a30SJung-uk Kim { 143*efcc2a30SJung-uk Kim MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); 144*efcc2a30SJung-uk Kim NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 145*efcc2a30SJung-uk Kim NextParamType = NextParamType->Asl.Next; 146*efcc2a30SJung-uk Kim } 147*efcc2a30SJung-uk Kim } 148*efcc2a30SJung-uk Kim else 149*efcc2a30SJung-uk Kim { 150*efcc2a30SJung-uk Kim MethodInfo->ValidArgTypes[ActualArgs] = 151*efcc2a30SJung-uk Kim AnMapObjTypeToBtype (NextType); 152*efcc2a30SJung-uk Kim NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 153*efcc2a30SJung-uk Kim ActualArgs++; 154*efcc2a30SJung-uk Kim } 155*efcc2a30SJung-uk Kim 156*efcc2a30SJung-uk Kim NextType = NextType->Asl.Next; 157*efcc2a30SJung-uk Kim } 158*efcc2a30SJung-uk Kim 159*efcc2a30SJung-uk Kim if ((MethodInfo->NumArguments) && 160*efcc2a30SJung-uk Kim (MethodInfo->NumArguments != ActualArgs)) 161*efcc2a30SJung-uk Kim { 162*efcc2a30SJung-uk Kim /* error: Param list did not match number of args */ 163*efcc2a30SJung-uk Kim } 164*efcc2a30SJung-uk Kim 165*efcc2a30SJung-uk Kim /* Allow numarguments == 0 for Function() */ 166*efcc2a30SJung-uk Kim 167*efcc2a30SJung-uk Kim if ((!MethodInfo->NumArguments) && (ActualArgs)) 168*efcc2a30SJung-uk Kim { 169*efcc2a30SJung-uk Kim MethodInfo->NumArguments = ActualArgs; 170*efcc2a30SJung-uk Kim ArgNode->Asl.Value.Integer |= ActualArgs; 171*efcc2a30SJung-uk Kim } 172*efcc2a30SJung-uk Kim 173*efcc2a30SJung-uk Kim /* 174*efcc2a30SJung-uk Kim * Actual arguments are initialized at method entry. 175*efcc2a30SJung-uk Kim * All other ArgX "registers" can be used as locals, so we 176*efcc2a30SJung-uk Kim * track their initialization. 177*efcc2a30SJung-uk Kim */ 178*efcc2a30SJung-uk Kim for (i = 0; i < MethodInfo->NumArguments; i++) 179*efcc2a30SJung-uk Kim { 180*efcc2a30SJung-uk Kim MethodInfo->ArgInitialized[i] = TRUE; 181*efcc2a30SJung-uk Kim } 182*efcc2a30SJung-uk Kim break; 183*efcc2a30SJung-uk Kim 184*efcc2a30SJung-uk Kim 185*efcc2a30SJung-uk Kim case PARSEOP_METHODCALL: 186*efcc2a30SJung-uk Kim 187*efcc2a30SJung-uk Kim if (MethodInfo && 188*efcc2a30SJung-uk Kim (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 189*efcc2a30SJung-uk Kim { 190*efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 191*efcc2a30SJung-uk Kim } 192*efcc2a30SJung-uk Kim break; 193*efcc2a30SJung-uk Kim 194*efcc2a30SJung-uk Kim 195*efcc2a30SJung-uk Kim case PARSEOP_LOCAL0: 196*efcc2a30SJung-uk Kim case PARSEOP_LOCAL1: 197*efcc2a30SJung-uk Kim case PARSEOP_LOCAL2: 198*efcc2a30SJung-uk Kim case PARSEOP_LOCAL3: 199*efcc2a30SJung-uk Kim case PARSEOP_LOCAL4: 200*efcc2a30SJung-uk Kim case PARSEOP_LOCAL5: 201*efcc2a30SJung-uk Kim case PARSEOP_LOCAL6: 202*efcc2a30SJung-uk Kim case PARSEOP_LOCAL7: 203*efcc2a30SJung-uk Kim 204*efcc2a30SJung-uk Kim if (!MethodInfo) 205*efcc2a30SJung-uk Kim { 206*efcc2a30SJung-uk Kim /* 207*efcc2a30SJung-uk Kim * Local was used outside a control method, or there was an error 208*efcc2a30SJung-uk Kim * in the method declaration. 209*efcc2a30SJung-uk Kim */ 210*efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 211*efcc2a30SJung-uk Kim return (AE_ERROR); 212*efcc2a30SJung-uk Kim } 213*efcc2a30SJung-uk Kim 214*efcc2a30SJung-uk Kim RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 215*efcc2a30SJung-uk Kim 216*efcc2a30SJung-uk Kim /* 217*efcc2a30SJung-uk Kim * If the local is being used as a target, mark the local 218*efcc2a30SJung-uk Kim * initialized 219*efcc2a30SJung-uk Kim */ 220*efcc2a30SJung-uk Kim if (Op->Asl.CompileFlags & NODE_IS_TARGET) 221*efcc2a30SJung-uk Kim { 222*efcc2a30SJung-uk Kim MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 223*efcc2a30SJung-uk Kim } 224*efcc2a30SJung-uk Kim 225*efcc2a30SJung-uk Kim /* 226*efcc2a30SJung-uk Kim * Otherwise, this is a reference, check if the local 227*efcc2a30SJung-uk Kim * has been previously initialized. 228*efcc2a30SJung-uk Kim * 229*efcc2a30SJung-uk Kim * The only operator that accepts an uninitialized value is ObjectType() 230*efcc2a30SJung-uk Kim */ 231*efcc2a30SJung-uk Kim else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && 232*efcc2a30SJung-uk Kim (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 233*efcc2a30SJung-uk Kim { 234*efcc2a30SJung-uk Kim LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 235*efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 236*efcc2a30SJung-uk Kim } 237*efcc2a30SJung-uk Kim break; 238*efcc2a30SJung-uk Kim 239*efcc2a30SJung-uk Kim 240*efcc2a30SJung-uk Kim case PARSEOP_ARG0: 241*efcc2a30SJung-uk Kim case PARSEOP_ARG1: 242*efcc2a30SJung-uk Kim case PARSEOP_ARG2: 243*efcc2a30SJung-uk Kim case PARSEOP_ARG3: 244*efcc2a30SJung-uk Kim case PARSEOP_ARG4: 245*efcc2a30SJung-uk Kim case PARSEOP_ARG5: 246*efcc2a30SJung-uk Kim case PARSEOP_ARG6: 247*efcc2a30SJung-uk Kim 248*efcc2a30SJung-uk Kim if (!MethodInfo) 249*efcc2a30SJung-uk Kim { 250*efcc2a30SJung-uk Kim /* 251*efcc2a30SJung-uk Kim * Arg was used outside a control method, or there was an error 252*efcc2a30SJung-uk Kim * in the method declaration. 253*efcc2a30SJung-uk Kim */ 254*efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 255*efcc2a30SJung-uk Kim return (AE_ERROR); 256*efcc2a30SJung-uk Kim } 257*efcc2a30SJung-uk Kim 258*efcc2a30SJung-uk Kim RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 259*efcc2a30SJung-uk Kim ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 260*efcc2a30SJung-uk Kim 261*efcc2a30SJung-uk Kim /* 262*efcc2a30SJung-uk Kim * If the Arg is being used as a target, mark the local 263*efcc2a30SJung-uk Kim * initialized 264*efcc2a30SJung-uk Kim */ 265*efcc2a30SJung-uk Kim if (Op->Asl.CompileFlags & NODE_IS_TARGET) 266*efcc2a30SJung-uk Kim { 267*efcc2a30SJung-uk Kim MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 268*efcc2a30SJung-uk Kim } 269*efcc2a30SJung-uk Kim 270*efcc2a30SJung-uk Kim /* 271*efcc2a30SJung-uk Kim * Otherwise, this is a reference, check if the Arg 272*efcc2a30SJung-uk Kim * has been previously initialized. 273*efcc2a30SJung-uk Kim * 274*efcc2a30SJung-uk Kim * The only operator that accepts an uninitialized value is ObjectType() 275*efcc2a30SJung-uk Kim */ 276*efcc2a30SJung-uk Kim else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && 277*efcc2a30SJung-uk Kim (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 278*efcc2a30SJung-uk Kim { 279*efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 280*efcc2a30SJung-uk Kim } 281*efcc2a30SJung-uk Kim 282*efcc2a30SJung-uk Kim /* Flag this arg if it is not a "real" argument to the method */ 283*efcc2a30SJung-uk Kim 284*efcc2a30SJung-uk Kim if (RegisterNumber >= MethodInfo->NumArguments) 285*efcc2a30SJung-uk Kim { 286*efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 287*efcc2a30SJung-uk Kim } 288*efcc2a30SJung-uk Kim break; 289*efcc2a30SJung-uk Kim 290*efcc2a30SJung-uk Kim 291*efcc2a30SJung-uk Kim case PARSEOP_RETURN: 292*efcc2a30SJung-uk Kim 293*efcc2a30SJung-uk Kim if (!MethodInfo) 294*efcc2a30SJung-uk Kim { 295*efcc2a30SJung-uk Kim /* 296*efcc2a30SJung-uk Kim * Probably was an error in the method declaration, 297*efcc2a30SJung-uk Kim * no additional error here 298*efcc2a30SJung-uk Kim */ 299*efcc2a30SJung-uk Kim ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); 300*efcc2a30SJung-uk Kim return (AE_ERROR); 301*efcc2a30SJung-uk Kim } 302*efcc2a30SJung-uk Kim 303*efcc2a30SJung-uk Kim /* 304*efcc2a30SJung-uk Kim * A child indicates a possible return value. A simple Return or 305*efcc2a30SJung-uk Kim * Return() is marked with NODE_IS_NULL_RETURN by the parser so 306*efcc2a30SJung-uk Kim * that it is not counted as a "real" return-with-value, although 307*efcc2a30SJung-uk Kim * the AML code that is actually emitted is Return(0). The AML 308*efcc2a30SJung-uk Kim * definition of Return has a required parameter, so we are 309*efcc2a30SJung-uk Kim * forced to convert a null return to Return(0). 310*efcc2a30SJung-uk Kim */ 311*efcc2a30SJung-uk Kim if ((Op->Asl.Child) && 312*efcc2a30SJung-uk Kim (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && 313*efcc2a30SJung-uk Kim (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN))) 314*efcc2a30SJung-uk Kim { 315*efcc2a30SJung-uk Kim MethodInfo->NumReturnWithValue++; 316*efcc2a30SJung-uk Kim } 317*efcc2a30SJung-uk Kim else 318*efcc2a30SJung-uk Kim { 319*efcc2a30SJung-uk Kim MethodInfo->NumReturnNoValue++; 320*efcc2a30SJung-uk Kim } 321*efcc2a30SJung-uk Kim break; 322*efcc2a30SJung-uk Kim 323*efcc2a30SJung-uk Kim 324*efcc2a30SJung-uk Kim case PARSEOP_BREAK: 325*efcc2a30SJung-uk Kim case PARSEOP_CONTINUE: 326*efcc2a30SJung-uk Kim 327*efcc2a30SJung-uk Kim Next = Op->Asl.Parent; 328*efcc2a30SJung-uk Kim while (Next) 329*efcc2a30SJung-uk Kim { 330*efcc2a30SJung-uk Kim if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 331*efcc2a30SJung-uk Kim { 332*efcc2a30SJung-uk Kim break; 333*efcc2a30SJung-uk Kim } 334*efcc2a30SJung-uk Kim Next = Next->Asl.Parent; 335*efcc2a30SJung-uk Kim } 336*efcc2a30SJung-uk Kim 337*efcc2a30SJung-uk Kim if (!Next) 338*efcc2a30SJung-uk Kim { 339*efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 340*efcc2a30SJung-uk Kim } 341*efcc2a30SJung-uk Kim break; 342*efcc2a30SJung-uk Kim 343*efcc2a30SJung-uk Kim 344*efcc2a30SJung-uk Kim case PARSEOP_STALL: 345*efcc2a30SJung-uk Kim 346*efcc2a30SJung-uk Kim /* We can range check if the argument is an integer */ 347*efcc2a30SJung-uk Kim 348*efcc2a30SJung-uk Kim if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 349*efcc2a30SJung-uk Kim (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) 350*efcc2a30SJung-uk Kim { 351*efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 352*efcc2a30SJung-uk Kim } 353*efcc2a30SJung-uk Kim break; 354*efcc2a30SJung-uk Kim 355*efcc2a30SJung-uk Kim 356*efcc2a30SJung-uk Kim case PARSEOP_DEVICE: 357*efcc2a30SJung-uk Kim case PARSEOP_EVENT: 358*efcc2a30SJung-uk Kim case PARSEOP_MUTEX: 359*efcc2a30SJung-uk Kim case PARSEOP_OPERATIONREGION: 360*efcc2a30SJung-uk Kim case PARSEOP_POWERRESOURCE: 361*efcc2a30SJung-uk Kim case PARSEOP_PROCESSOR: 362*efcc2a30SJung-uk Kim case PARSEOP_THERMALZONE: 363*efcc2a30SJung-uk Kim 364*efcc2a30SJung-uk Kim /* 365*efcc2a30SJung-uk Kim * The first operand is a name to be created in the namespace. 366*efcc2a30SJung-uk Kim * Check against the reserved list. 367*efcc2a30SJung-uk Kim */ 368*efcc2a30SJung-uk Kim i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); 369*efcc2a30SJung-uk Kim if (i < ACPI_VALID_RESERVED_NAME_MAX) 370*efcc2a30SJung-uk Kim { 371*efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 372*efcc2a30SJung-uk Kim } 373*efcc2a30SJung-uk Kim break; 374*efcc2a30SJung-uk Kim 375*efcc2a30SJung-uk Kim 376*efcc2a30SJung-uk Kim case PARSEOP_NAME: 377*efcc2a30SJung-uk Kim 378*efcc2a30SJung-uk Kim /* Typecheck any predefined names statically defined with Name() */ 379*efcc2a30SJung-uk Kim 380*efcc2a30SJung-uk Kim ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); 381*efcc2a30SJung-uk Kim 382*efcc2a30SJung-uk Kim /* Special typechecking for _HID */ 383*efcc2a30SJung-uk Kim 384*efcc2a30SJung-uk Kim if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) 385*efcc2a30SJung-uk Kim { 386*efcc2a30SJung-uk Kim Next = Op->Asl.Child->Asl.Next; 387*efcc2a30SJung-uk Kim AnCheckId (Next, ASL_TYPE_HID); 388*efcc2a30SJung-uk Kim } 389*efcc2a30SJung-uk Kim 390*efcc2a30SJung-uk Kim /* Special typechecking for _CID */ 391*efcc2a30SJung-uk Kim 392*efcc2a30SJung-uk Kim else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) 393*efcc2a30SJung-uk Kim { 394*efcc2a30SJung-uk Kim Next = Op->Asl.Child->Asl.Next; 395*efcc2a30SJung-uk Kim 396*efcc2a30SJung-uk Kim if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || 397*efcc2a30SJung-uk Kim (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 398*efcc2a30SJung-uk Kim { 399*efcc2a30SJung-uk Kim Next = Next->Asl.Child; 400*efcc2a30SJung-uk Kim while (Next) 401*efcc2a30SJung-uk Kim { 402*efcc2a30SJung-uk Kim AnCheckId (Next, ASL_TYPE_CID); 403*efcc2a30SJung-uk Kim Next = Next->Asl.Next; 404*efcc2a30SJung-uk Kim } 405*efcc2a30SJung-uk Kim } 406*efcc2a30SJung-uk Kim else 407*efcc2a30SJung-uk Kim { 408*efcc2a30SJung-uk Kim AnCheckId (Next, ASL_TYPE_CID); 409*efcc2a30SJung-uk Kim } 410*efcc2a30SJung-uk Kim } 411*efcc2a30SJung-uk Kim break; 412*efcc2a30SJung-uk Kim 413*efcc2a30SJung-uk Kim 414*efcc2a30SJung-uk Kim default: 415*efcc2a30SJung-uk Kim break; 416*efcc2a30SJung-uk Kim } 417*efcc2a30SJung-uk Kim 418*efcc2a30SJung-uk Kim return (AE_OK); 419*efcc2a30SJung-uk Kim } 420*efcc2a30SJung-uk Kim 421*efcc2a30SJung-uk Kim 422*efcc2a30SJung-uk Kim /******************************************************************************* 423*efcc2a30SJung-uk Kim * 424*efcc2a30SJung-uk Kim * FUNCTION: MtMethodAnalysisWalkEnd 425*efcc2a30SJung-uk Kim * 426*efcc2a30SJung-uk Kim * PARAMETERS: ASL_WALK_CALLBACK 427*efcc2a30SJung-uk Kim * 428*efcc2a30SJung-uk Kim * RETURN: Status 429*efcc2a30SJung-uk Kim * 430*efcc2a30SJung-uk Kim * DESCRIPTION: Ascending callback for analysis walk. Complete method 431*efcc2a30SJung-uk Kim * return analysis. 432*efcc2a30SJung-uk Kim * 433*efcc2a30SJung-uk Kim ******************************************************************************/ 434*efcc2a30SJung-uk Kim 435*efcc2a30SJung-uk Kim ACPI_STATUS 436*efcc2a30SJung-uk Kim MtMethodAnalysisWalkEnd ( 437*efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *Op, 438*efcc2a30SJung-uk Kim UINT32 Level, 439*efcc2a30SJung-uk Kim void *Context) 440*efcc2a30SJung-uk Kim { 441*efcc2a30SJung-uk Kim ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 442*efcc2a30SJung-uk Kim ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 443*efcc2a30SJung-uk Kim 444*efcc2a30SJung-uk Kim 445*efcc2a30SJung-uk Kim switch (Op->Asl.ParseOpcode) 446*efcc2a30SJung-uk Kim { 447*efcc2a30SJung-uk Kim case PARSEOP_METHOD: 448*efcc2a30SJung-uk Kim case PARSEOP_RETURN: 449*efcc2a30SJung-uk Kim if (!MethodInfo) 450*efcc2a30SJung-uk Kim { 451*efcc2a30SJung-uk Kim printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 452*efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 453*efcc2a30SJung-uk Kim "No method info for this method"); 454*efcc2a30SJung-uk Kim 455*efcc2a30SJung-uk Kim CmCleanupAndExit (); 456*efcc2a30SJung-uk Kim return (AE_AML_INTERNAL); 457*efcc2a30SJung-uk Kim } 458*efcc2a30SJung-uk Kim break; 459*efcc2a30SJung-uk Kim 460*efcc2a30SJung-uk Kim default: 461*efcc2a30SJung-uk Kim break; 462*efcc2a30SJung-uk Kim } 463*efcc2a30SJung-uk Kim 464*efcc2a30SJung-uk Kim switch (Op->Asl.ParseOpcode) 465*efcc2a30SJung-uk Kim { 466*efcc2a30SJung-uk Kim case PARSEOP_METHOD: 467*efcc2a30SJung-uk Kim 468*efcc2a30SJung-uk Kim WalkInfo->MethodStack = MethodInfo->Next; 469*efcc2a30SJung-uk Kim 470*efcc2a30SJung-uk Kim /* 471*efcc2a30SJung-uk Kim * Check if there is no return statement at the end of the 472*efcc2a30SJung-uk Kim * method AND we can actually get there -- i.e., the execution 473*efcc2a30SJung-uk Kim * of the method can possibly terminate without a return statement. 474*efcc2a30SJung-uk Kim */ 475*efcc2a30SJung-uk Kim if ((!AnLastStatementIsReturn (Op)) && 476*efcc2a30SJung-uk Kim (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 477*efcc2a30SJung-uk Kim { 478*efcc2a30SJung-uk Kim /* 479*efcc2a30SJung-uk Kim * No return statement, and execution can possibly exit 480*efcc2a30SJung-uk Kim * via this path. This is equivalent to Return () 481*efcc2a30SJung-uk Kim */ 482*efcc2a30SJung-uk Kim MethodInfo->NumReturnNoValue++; 483*efcc2a30SJung-uk Kim } 484*efcc2a30SJung-uk Kim 485*efcc2a30SJung-uk Kim /* 486*efcc2a30SJung-uk Kim * Check for case where some return statements have a return value 487*efcc2a30SJung-uk Kim * and some do not. Exit without a return statement is a return with 488*efcc2a30SJung-uk Kim * no value 489*efcc2a30SJung-uk Kim */ 490*efcc2a30SJung-uk Kim if (MethodInfo->NumReturnNoValue && 491*efcc2a30SJung-uk Kim MethodInfo->NumReturnWithValue) 492*efcc2a30SJung-uk Kim { 493*efcc2a30SJung-uk Kim AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, 494*efcc2a30SJung-uk Kim Op->Asl.ExternalName); 495*efcc2a30SJung-uk Kim } 496*efcc2a30SJung-uk Kim 497*efcc2a30SJung-uk Kim /* 498*efcc2a30SJung-uk Kim * If there are any RETURN() statements with no value, or there is a 499*efcc2a30SJung-uk Kim * control path that allows the method to exit without a return value, 500*efcc2a30SJung-uk Kim * we mark the method as a method that does not return a value. This 501*efcc2a30SJung-uk Kim * knowledge can be used to check method invocations that expect a 502*efcc2a30SJung-uk Kim * returned value. 503*efcc2a30SJung-uk Kim */ 504*efcc2a30SJung-uk Kim if (MethodInfo->NumReturnNoValue) 505*efcc2a30SJung-uk Kim { 506*efcc2a30SJung-uk Kim if (MethodInfo->NumReturnWithValue) 507*efcc2a30SJung-uk Kim { 508*efcc2a30SJung-uk Kim Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 509*efcc2a30SJung-uk Kim } 510*efcc2a30SJung-uk Kim else 511*efcc2a30SJung-uk Kim { 512*efcc2a30SJung-uk Kim Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 513*efcc2a30SJung-uk Kim } 514*efcc2a30SJung-uk Kim } 515*efcc2a30SJung-uk Kim 516*efcc2a30SJung-uk Kim /* 517*efcc2a30SJung-uk Kim * Check predefined method names for correct return behavior 518*efcc2a30SJung-uk Kim * and correct number of arguments. Also, some special checks 519*efcc2a30SJung-uk Kim * For GPE and _REG methods. 520*efcc2a30SJung-uk Kim */ 521*efcc2a30SJung-uk Kim if (ApCheckForPredefinedMethod (Op, MethodInfo)) 522*efcc2a30SJung-uk Kim { 523*efcc2a30SJung-uk Kim /* Special check for two names like _L01 and _E01 in same scope */ 524*efcc2a30SJung-uk Kim 525*efcc2a30SJung-uk Kim ApCheckForGpeNameConflict (Op); 526*efcc2a30SJung-uk Kim 527*efcc2a30SJung-uk Kim /* 528*efcc2a30SJung-uk Kim * Special check for _REG: Must have an operation region definition 529*efcc2a30SJung-uk Kim * within the same scope! 530*efcc2a30SJung-uk Kim */ 531*efcc2a30SJung-uk Kim ApCheckRegMethod (Op); 532*efcc2a30SJung-uk Kim } 533*efcc2a30SJung-uk Kim 534*efcc2a30SJung-uk Kim ACPI_FREE (MethodInfo); 535*efcc2a30SJung-uk Kim break; 536*efcc2a30SJung-uk Kim 537*efcc2a30SJung-uk Kim 538*efcc2a30SJung-uk Kim case PARSEOP_NAME: 539*efcc2a30SJung-uk Kim 540*efcc2a30SJung-uk Kim /* Special check for two names like _L01 and _E01 in same scope */ 541*efcc2a30SJung-uk Kim 542*efcc2a30SJung-uk Kim ApCheckForGpeNameConflict (Op); 543*efcc2a30SJung-uk Kim break; 544*efcc2a30SJung-uk Kim 545*efcc2a30SJung-uk Kim 546*efcc2a30SJung-uk Kim case PARSEOP_RETURN: 547*efcc2a30SJung-uk Kim 548*efcc2a30SJung-uk Kim /* 549*efcc2a30SJung-uk Kim * If the parent is a predefined method name, attempt to typecheck 550*efcc2a30SJung-uk Kim * the return value. Only static types can be validated. 551*efcc2a30SJung-uk Kim */ 552*efcc2a30SJung-uk Kim ApCheckPredefinedReturnValue (Op, MethodInfo); 553*efcc2a30SJung-uk Kim 554*efcc2a30SJung-uk Kim /* 555*efcc2a30SJung-uk Kim * The parent block does not "exit" and continue execution -- the 556*efcc2a30SJung-uk Kim * method is terminated here with the Return() statement. 557*efcc2a30SJung-uk Kim */ 558*efcc2a30SJung-uk Kim Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 559*efcc2a30SJung-uk Kim 560*efcc2a30SJung-uk Kim /* Used in the "typing" pass later */ 561*efcc2a30SJung-uk Kim 562*efcc2a30SJung-uk Kim Op->Asl.ParentMethod = MethodInfo->Op; 563*efcc2a30SJung-uk Kim 564*efcc2a30SJung-uk Kim /* 565*efcc2a30SJung-uk Kim * If there is a peer node after the return statement, then this 566*efcc2a30SJung-uk Kim * node is unreachable code -- i.e., it won't be executed because of 567*efcc2a30SJung-uk Kim * the preceding Return() statement. 568*efcc2a30SJung-uk Kim */ 569*efcc2a30SJung-uk Kim if (Op->Asl.Next) 570*efcc2a30SJung-uk Kim { 571*efcc2a30SJung-uk Kim AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 572*efcc2a30SJung-uk Kim } 573*efcc2a30SJung-uk Kim break; 574*efcc2a30SJung-uk Kim 575*efcc2a30SJung-uk Kim 576*efcc2a30SJung-uk Kim case PARSEOP_IF: 577*efcc2a30SJung-uk Kim 578*efcc2a30SJung-uk Kim if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 579*efcc2a30SJung-uk Kim (Op->Asl.Next) && 580*efcc2a30SJung-uk Kim (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 581*efcc2a30SJung-uk Kim { 582*efcc2a30SJung-uk Kim /* 583*efcc2a30SJung-uk Kim * This IF has a corresponding ELSE. The IF block has no exit, 584*efcc2a30SJung-uk Kim * (it contains an unconditional Return) 585*efcc2a30SJung-uk Kim * mark the ELSE block to remember this fact. 586*efcc2a30SJung-uk Kim */ 587*efcc2a30SJung-uk Kim Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 588*efcc2a30SJung-uk Kim } 589*efcc2a30SJung-uk Kim break; 590*efcc2a30SJung-uk Kim 591*efcc2a30SJung-uk Kim 592*efcc2a30SJung-uk Kim case PARSEOP_ELSE: 593*efcc2a30SJung-uk Kim 594*efcc2a30SJung-uk Kim if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 595*efcc2a30SJung-uk Kim (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 596*efcc2a30SJung-uk Kim { 597*efcc2a30SJung-uk Kim /* 598*efcc2a30SJung-uk Kim * This ELSE block has no exit and the corresponding IF block 599*efcc2a30SJung-uk Kim * has no exit either. Therefore, the parent node has no exit. 600*efcc2a30SJung-uk Kim */ 601*efcc2a30SJung-uk Kim Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 602*efcc2a30SJung-uk Kim } 603*efcc2a30SJung-uk Kim break; 604*efcc2a30SJung-uk Kim 605*efcc2a30SJung-uk Kim 606*efcc2a30SJung-uk Kim default: 607*efcc2a30SJung-uk Kim 608*efcc2a30SJung-uk Kim if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 609*efcc2a30SJung-uk Kim (Op->Asl.Parent)) 610*efcc2a30SJung-uk Kim { 611*efcc2a30SJung-uk Kim /* If this node has no exit, then the parent has no exit either */ 612*efcc2a30SJung-uk Kim 613*efcc2a30SJung-uk Kim Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 614*efcc2a30SJung-uk Kim } 615*efcc2a30SJung-uk Kim break; 616*efcc2a30SJung-uk Kim } 617*efcc2a30SJung-uk Kim 618*efcc2a30SJung-uk Kim return (AE_OK); 619*efcc2a30SJung-uk Kim } 620