diff options
Diffstat (limited to 'source/compiler/aslwalks.c')
| -rw-r--r-- | source/compiler/aslwalks.c | 571 | 
1 files changed, 1 insertions, 570 deletions
| diff --git a/source/compiler/aslwalks.c b/source/compiler/aslwalks.c index dce037e7706e..2168aec69e8e 100644 --- a/source/compiler/aslwalks.c +++ b/source/compiler/aslwalks.c @@ -1,6 +1,6 @@  /******************************************************************************   * - * Module Name: aslwalks.c - major analytical parse tree walks + * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks   *   *****************************************************************************/ @@ -54,575 +54,6 @@  /*******************************************************************************   * - * FUNCTION:    AnMethodAnalysisWalkBegin - * - * PARAMETERS:  ASL_WALK_CALLBACK - * - * RETURN:      Status - * - * DESCRIPTION: Descending callback for the analysis walk. Check methods for: - *              1) Initialized local variables - *              2) Valid arguments - *              3) Return types - * - ******************************************************************************/ - -ACPI_STATUS -AnMethodAnalysisWalkBegin ( -    ACPI_PARSE_OBJECT       *Op, -    UINT32                  Level, -    void                    *Context) -{ -    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; -    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack; -    ACPI_PARSE_OBJECT       *Next; -    UINT32                  RegisterNumber; -    UINT32                  i; -    char                    LocalName[] = "Local0"; -    char                    ArgName[] = "Arg0"; -    ACPI_PARSE_OBJECT       *ArgNode; -    ACPI_PARSE_OBJECT       *NextType; -    ACPI_PARSE_OBJECT       *NextParamType; -    UINT8                   ActualArgs = 0; - - -    switch (Op->Asl.ParseOpcode) -    { -    case PARSEOP_METHOD: - -        TotalMethods++; - -        /* Create and init method info */ - -        MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); -        MethodInfo->Next = WalkInfo->MethodStack; -        MethodInfo->Op = Op; - -        WalkInfo->MethodStack = MethodInfo; - -        /* Get the name node, ignored here */ - -        Next = Op->Asl.Child; - -        /* Get the NumArguments node */ - -        Next = Next->Asl.Next; -        MethodInfo->NumArguments = (UINT8) -            (((UINT8) Next->Asl.Value.Integer) & 0x07); - -        /* Get the SerializeRule and SyncLevel nodes, ignored here */ - -        Next = Next->Asl.Next; -        Next = Next->Asl.Next; -        ArgNode = Next; - -        /* Get the ReturnType node */ - -        Next = Next->Asl.Next; - -        NextType = Next->Asl.Child; -        while (NextType) -        { -            /* Get and map each of the ReturnTypes */ - -            MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); -            NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; -            NextType = NextType->Asl.Next; -        } - -        /* Get the ParameterType node */ - -        Next = Next->Asl.Next; - -        NextType = Next->Asl.Child; -        while (NextType) -        { -            if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) -            { -                NextParamType = NextType->Asl.Child; -                while (NextParamType) -                { -                    MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); -                    NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; -                    NextParamType = NextParamType->Asl.Next; -                } -            } -            else -            { -                MethodInfo->ValidArgTypes[ActualArgs] = -                    AnMapObjTypeToBtype (NextType); -                NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; -                ActualArgs++; -            } - -            NextType = NextType->Asl.Next; -        } - -        if ((MethodInfo->NumArguments) && -            (MethodInfo->NumArguments != ActualArgs)) -        { -            /* error: Param list did not match number of args */ -        } - -        /* Allow numarguments == 0 for Function() */ - -        if ((!MethodInfo->NumArguments) && (ActualArgs)) -        { -            MethodInfo->NumArguments = ActualArgs; -            ArgNode->Asl.Value.Integer |= ActualArgs; -        } - -        /* -         * Actual arguments are initialized at method entry. -         * All other ArgX "registers" can be used as locals, so we -         * track their initialization. -         */ -        for (i = 0; i < MethodInfo->NumArguments; i++) -        { -            MethodInfo->ArgInitialized[i] = TRUE; -        } -        break; - - -    case PARSEOP_METHODCALL: - -        if (MethodInfo && -           (Op->Asl.Node == MethodInfo->Op->Asl.Node)) -        { -            AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); -        } -        break; - - -    case PARSEOP_LOCAL0: -    case PARSEOP_LOCAL1: -    case PARSEOP_LOCAL2: -    case PARSEOP_LOCAL3: -    case PARSEOP_LOCAL4: -    case PARSEOP_LOCAL5: -    case PARSEOP_LOCAL6: -    case PARSEOP_LOCAL7: - -        if (!MethodInfo) -        { -            /* -             * Local was used outside a control method, or there was an error -             * in the method declaration. -             */ -            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); -            return (AE_ERROR); -        } - -        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); - -        /* -         * If the local is being used as a target, mark the local -         * initialized -         */ -        if (Op->Asl.CompileFlags & NODE_IS_TARGET) -        { -            MethodInfo->LocalInitialized[RegisterNumber] = TRUE; -        } - -        /* -         * Otherwise, this is a reference, check if the local -         * has been previously initialized. -         * -         * The only operator that accepts an uninitialized value is ObjectType() -         */ -        else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && -                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) -        { -            LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); -            AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); -        } -        break; - - -    case PARSEOP_ARG0: -    case PARSEOP_ARG1: -    case PARSEOP_ARG2: -    case PARSEOP_ARG3: -    case PARSEOP_ARG4: -    case PARSEOP_ARG5: -    case PARSEOP_ARG6: - -        if (!MethodInfo) -        { -            /* -             * Arg was used outside a control method, or there was an error -             * in the method declaration. -             */ -            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); -            return (AE_ERROR); -        } - -        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; -        ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); - -        /* -         * If the Arg is being used as a target, mark the local -         * initialized -         */ -        if (Op->Asl.CompileFlags & NODE_IS_TARGET) -        { -            MethodInfo->ArgInitialized[RegisterNumber] = TRUE; -        } - -        /* -         * Otherwise, this is a reference, check if the Arg -         * has been previously initialized. -         * -         * The only operator that accepts an uninitialized value is ObjectType() -         */ -        else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && -                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) -        { -            AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); -        } - -        /* Flag this arg if it is not a "real" argument to the method */ - -        if (RegisterNumber >= MethodInfo->NumArguments) -        { -            AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); -        } -        break; - - -    case PARSEOP_RETURN: - -        if (!MethodInfo) -        { -            /* -             * Probably was an error in the method declaration, -             * no additional error here -             */ -            ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); -            return (AE_ERROR); -        } - -        /* -         * A child indicates a possible return value. A simple Return or -         * Return() is marked with NODE_IS_NULL_RETURN by the parser so -         * that it is not counted as a "real" return-with-value, although -         * the AML code that is actually emitted is Return(0). The AML -         * definition of Return has a required parameter, so we are -         * forced to convert a null return to Return(0). -         */ -        if ((Op->Asl.Child) && -            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && -            (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN))) -        { -            MethodInfo->NumReturnWithValue++; -        } -        else -        { -            MethodInfo->NumReturnNoValue++; -        } -        break; - - -    case PARSEOP_BREAK: -    case PARSEOP_CONTINUE: - -        Next = Op->Asl.Parent; -        while (Next) -        { -            if (Next->Asl.ParseOpcode == PARSEOP_WHILE) -            { -                break; -            } -            Next = Next->Asl.Parent; -        } - -        if (!Next) -        { -            AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); -        } -        break; - - -    case PARSEOP_STALL: - -        /* We can range check if the argument is an integer */ - -        if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && -            (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) -        { -            AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); -        } -        break; - - -    case PARSEOP_DEVICE: -    case PARSEOP_EVENT: -    case PARSEOP_MUTEX: -    case PARSEOP_OPERATIONREGION: -    case PARSEOP_POWERRESOURCE: -    case PARSEOP_PROCESSOR: -    case PARSEOP_THERMALZONE: - -        /* -         * The first operand is a name to be created in the namespace. -         * Check against the reserved list. -         */ -        i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); -        if (i < ACPI_VALID_RESERVED_NAME_MAX) -        { -            AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); -        } -        break; - - -    case PARSEOP_NAME: - -        /* Typecheck any predefined names statically defined with Name() */ - -        ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); - -        /* Special typechecking for _HID */ - -        if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) -        { -            Next = Op->Asl.Child->Asl.Next; -            AnCheckId (Next, ASL_TYPE_HID); -        } - -        /* Special typechecking for _CID */ - -        else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) -        { -            Next = Op->Asl.Child->Asl.Next; - -            if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || -                (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) -            { -                Next = Next->Asl.Child; -                while (Next) -                { -                    AnCheckId (Next, ASL_TYPE_CID); -                    Next = Next->Asl.Next; -                } -            } -            else -            { -                AnCheckId (Next, ASL_TYPE_CID); -            } -        } -        break; - - -    default: -        break; -    } - -    return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION:    AnMethodAnalysisWalkEnd - * - * PARAMETERS:  ASL_WALK_CALLBACK - * - * RETURN:      Status - * - * DESCRIPTION: Ascending callback for analysis walk. Complete method - *              return analysis. - * - ******************************************************************************/ - -ACPI_STATUS -AnMethodAnalysisWalkEnd ( -    ACPI_PARSE_OBJECT       *Op, -    UINT32                  Level, -    void                    *Context) -{ -    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; -    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack; - - -    switch (Op->Asl.ParseOpcode) -    { -    case PARSEOP_METHOD: -    case PARSEOP_RETURN: -        if (!MethodInfo) -        { -            printf ("No method info for method! [%s]\n", Op->Asl.Namepath); -            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, -                "No method info for this method"); - -            CmCleanupAndExit (); -            return (AE_AML_INTERNAL); -        } -        break; - -    default: -        break; -    } - -    switch (Op->Asl.ParseOpcode) -    { -    case PARSEOP_METHOD: - -        WalkInfo->MethodStack = MethodInfo->Next; - -        /* -         * Check if there is no return statement at the end of the -         * method AND we can actually get there -- i.e., the execution -         * of the method can possibly terminate without a return statement. -         */ -        if ((!AnLastStatementIsReturn (Op)) && -            (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) -        { -            /* -             * No return statement, and execution can possibly exit -             * via this path. This is equivalent to Return () -             */ -            MethodInfo->NumReturnNoValue++; -        } - -        /* -         * Check for case where some return statements have a return value -         * and some do not. Exit without a return statement is a return with -         * no value -         */ -        if (MethodInfo->NumReturnNoValue && -            MethodInfo->NumReturnWithValue) -        { -            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, -                Op->Asl.ExternalName); -        } - -        /* -         * If there are any RETURN() statements with no value, or there is a -         * control path that allows the method to exit without a return value, -         * we mark the method as a method that does not return a value. This -         * knowledge can be used to check method invocations that expect a -         * returned value. -         */ -        if (MethodInfo->NumReturnNoValue) -        { -            if (MethodInfo->NumReturnWithValue) -            { -                Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; -            } -            else -            { -                Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; -            } -        } - -        /* -         * Check predefined method names for correct return behavior -         * and correct number of arguments. Also, some special checks -         * For GPE and _REG methods. -         */ -        if (ApCheckForPredefinedMethod (Op, MethodInfo)) -        { -            /* Special check for two names like _L01 and _E01 in same scope */ - -            ApCheckForGpeNameConflict (Op); - -            /* -             * Special check for _REG: Must have an operation region definition -             * within the same scope! -             */ -            ApCheckRegMethod (Op); -        } - -        ACPI_FREE (MethodInfo); -        break; - - -    case PARSEOP_NAME: - -         /* Special check for two names like _L01 and _E01 in same scope */ - -        ApCheckForGpeNameConflict (Op); -        break; - - -    case PARSEOP_RETURN: - -        /* -         * If the parent is a predefined method name, attempt to typecheck -         * the return value. Only static types can be validated. -         */ -        ApCheckPredefinedReturnValue (Op, MethodInfo); - -        /* -         * The parent block does not "exit" and continue execution -- the -         * method is terminated here with the Return() statement. -         */ -        Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; - -        /* Used in the "typing" pass later */ - -        Op->Asl.ParentMethod = MethodInfo->Op; - -        /* -         * If there is a peer node after the return statement, then this -         * node is unreachable code -- i.e., it won't be executed because of -         * the preceding Return() statement. -         */ -        if (Op->Asl.Next) -        { -            AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); -        } -        break; - - -    case PARSEOP_IF: - -        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && -            (Op->Asl.Next) && -            (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) -        { -            /* -             * This IF has a corresponding ELSE. The IF block has no exit, -             * (it contains an unconditional Return) -             * mark the ELSE block to remember this fact. -             */ -            Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; -        } -        break; - - -    case PARSEOP_ELSE: - -        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && -            (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) -        { -            /* -             * This ELSE block has no exit and the corresponding IF block -             * has no exit either. Therefore, the parent node has no exit. -             */ -            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; -        } -        break; - - -    default: - -        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && -            (Op->Asl.Parent)) -        { -            /* If this node has no exit, then the parent has no exit either */ - -            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; -        } -        break; -    } - -    return (AE_OK); -} - - -/******************************************************************************* - *   * FUNCTION:    AnMethodTypingWalkEnd   *   * PARAMETERS:  ASL_WALK_CALLBACK | 
