FreeBSD/sys/contrib/dev/acpica/compiler/aslmethod.c
/*******************************************************************************
 *
 * FUNCTION:    MtMethodAnalysisWalkEnd
 *
 * PARAMETERS:  ASL_WALK_CALLBACK
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Ascending callback for analysis walk. Complete method
 *              return analysis.
 *
 ******************************************************************************/


Status

Ascending callback for analysis walk. Complete method
return analysis.
Status Ascending callback for analysis walk . Complete method return analysis .
ACPI_STATUS
MtMethodAnalysisWalkEnd (
    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;
        if ((!AnLastStatementIsReturn (Op)) &&
            (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
        {
            MethodInfo->NumReturnNoValue++;
        }
        if (MethodInfo->NumReturnNoValue &&
            MethodInfo->NumReturnWithValue)
        {
            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
                Op->Asl.ExternalName);
        }
        if (MethodInfo->NumReturnNoValue)
        {
            if (MethodInfo->NumReturnWithValue)
            {
                Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
            }
            else
            {
                Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
            }
        }
        if (ApCheckForPredefinedMethod (Op, MethodInfo))
        {
            ApCheckForGpeNameConflict (Op);
            ApCheckRegMethod (Op);
        }
        ACPI_FREE (MethodInfo);
        break;
    case PARSEOP_NAME:
        ApCheckForGpeNameConflict (Op);
        break;
    case PARSEOP_RETURN:
        ApCheckPredefinedReturnValue (Op, MethodInfo);
        Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
        Op->Asl.ParentMethod = MethodInfo->Op;
        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))
        {
            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))
        {
            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
        }
        break;
    default:
        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
            (Op->Asl.Parent))
        {
            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
        }
        break;
    }
    return (AE_OK);
}
ACPI_STATUS MtMethodAnalysisWalkEnd ( 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 ( " \n " , Op -> Asl . Namepath ) ; AslError ( ASL_ERROR , ASL_MSG_COMPILER_INTERNAL , Op , " " ) ; CmCleanupAndExit ( ) ; return ( AE_AML_INTERNAL ) ; } break ; default : break ; } switch ( Op -> Asl . ParseOpcode ) { case PARSEOP_METHOD : WalkInfo -> MethodStack = MethodInfo -> Next ; if ( ( ! AnLastStatementIsReturn ( Op ) ) && ( ! ( Op -> Asl . CompileFlags & NODE_HAS_NO_EXIT ) ) ) { MethodInfo -> NumReturnNoValue ++ ; } if ( MethodInfo -> NumReturnNoValue && MethodInfo -> NumReturnWithValue ) { AslError ( ASL_WARNING , ASL_MSG_RETURN_TYPES , Op , Op -> Asl . ExternalName ) ; } if ( MethodInfo -> NumReturnNoValue ) { if ( MethodInfo -> NumReturnWithValue ) { Op -> Asl . CompileFlags |= NODE_METHOD_SOME_NO_RETVAL ; } else { Op -> Asl . CompileFlags |= NODE_METHOD_NO_RETVAL ; } } if ( ApCheckForPredefinedMethod ( Op , MethodInfo ) ) { ApCheckForGpeNameConflict ( Op ) ; ApCheckRegMethod ( Op ) ; } ACPI_FREE ( MethodInfo ) ; break ; case PARSEOP_NAME : ApCheckForGpeNameConflict ( Op ) ; break ; case PARSEOP_RETURN : ApCheckPredefinedReturnValue ( Op , MethodInfo ) ; Op -> Asl . Parent -> Asl . CompileFlags |= NODE_HAS_NO_EXIT ; Op -> Asl . ParentMethod = MethodInfo -> Op ; 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 ) ) { 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 ) ) { Op -> Asl . Parent -> Asl . CompileFlags |= NODE_HAS_NO_EXIT ; } break ; default : if ( ( Op -> Asl . CompileFlags & NODE_HAS_NO_EXIT ) && ( Op -> Asl . Parent ) ) { Op -> Asl . Parent -> Asl . CompileFlags |= NODE_HAS_NO_EXIT ; } break ; } return ( AE_OK ) ; }
FUNCTION:    MtMethodAnalysisWalkEnd
 PARAMETERS:  ASL_WALK_CALLBACK
FUNCTION : MtMethodAnalysisWalkEnd PARAMETERS : ASL_WALK_CALLBACK
/*
         * 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.
         */ /*
             * No return statement, and execution can possibly exit
             * via this path. This is equivalent to Return ()
             */ /*
         * 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 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.
         */ /*
         * Check predefined method names for correct return behavior
         * and correct number of arguments. Also, some special checks
         * For GPE and _REG methods.
         */ /* Special check for two names like _L01 and _E01 in same scope */ /*
             * Special check for _REG: Must have an operation region definition
             * within the same scope!
             */ /* Special check for two names like _L01 and _E01 in same scope */ /*
         * If the parent is a predefined method name, attempt to typecheck
         * the return value. Only static types can be validated.
         */ /*
         * The parent block does not "exit" and continue execution -- the
         * method is terminated here with the Return() statement.
         */ /* Used in the "typing" pass later */ /*
         * 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.
         */ /*
             * 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.
             */ /*
             * This ELSE block has no exit and the corresponding IF block
             * has no exit either. Therefore, the parent node has no exit.
             */ /* If this node has no exit, then the parent has no exit either */