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