示例#1
0
文件: aslfold.c 项目: olsner/acpica
static void
TrInstallReducedConstant (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     *ObjDesc)
{
    ACPI_PARSE_OBJECT       *LengthOp;
    ACPI_PARSE_OBJECT       *DataOp;


    TotalFolds++;
    AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
        Op->Asl.ParseOpName);

    /*
     * Because we know we executed type 3/4/5 opcodes above, we know that
     * the result must be either an Integer, String, or Buffer.
     */
    switch (ObjDesc->Common.Type)
    {
    case ACPI_TYPE_INTEGER:

        OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);

        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
            Op->Asl.ParseOpName,
            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
        break;

    case ACPI_TYPE_STRING:

        Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
        Op->Common.AmlOpcode = AML_STRING_OP;
        Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
        Op->Common.Value.String = ObjDesc->String.Pointer;

        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant expression reduced to (STRING) %s\n\n",
            Op->Common.Value.String);
        break;

    case ACPI_TYPE_BUFFER:
        /*
         * Create a new parse subtree of the form:
         *
         * BUFFER (Buffer AML opcode)
         *    INTEGER (Buffer length in bytes)
         *    RAW_DATA (Buffer byte data)
         */
        Op->Asl.ParseOpcode = PARSEOP_BUFFER;
        Op->Common.AmlOpcode = AML_BUFFER_OP;
        Op->Asl.CompileFlags = NODE_AML_PACKAGE;
        UtSetParseOpName (Op);

        /* Child node is the buffer length */

        LengthOp = TrAllocateNode (PARSEOP_INTEGER);

        LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
        LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
        LengthOp->Asl.Parent = Op;
        (void) OpcSetOptimalIntegerSize (LengthOp);

        Op->Asl.Child = LengthOp;

        /* Next child is the raw buffer data */

        DataOp = TrAllocateNode (PARSEOP_RAW_DATA);
        DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
        DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
        DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
        DataOp->Asl.Parent = Op;

        LengthOp->Asl.Next = DataOp;

        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant expression reduced to (BUFFER) length %X\n\n",
            ObjDesc->Buffer.Length);
        break;

    default:
        break;
    }
}
示例#2
0
ACPI_STATUS
OpcAmlConstantWalk (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState;
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *RootOp;
    ACPI_PARSE_OBJECT       *OriginalParentOp;
    UINT8                   WalkType;


    /*
     * Only interested in subtrees that could possibly contain
     * expressions that can be evaluated at this time
     */
    if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
          (Op->Asl.CompileFlags & NODE_IS_TARGET))
    {
        return (AE_OK);
    }

    /* Set the walk type based on the reduction used for this op */

    if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
    {
        /* Op is a TermArg, constant folding is merely optional */

        if (!Gbl_FoldConstants)
        {
            return (AE_CTRL_DEPTH);
        }

        WalkType = ACPI_WALK_CONST_OPTIONAL;
    }
    else
    {
        /* Op is a DataObject, the expression MUST reduced to a constant */

        WalkType = ACPI_WALK_CONST_REQUIRED;
    }

    /* Create a new walk state */

    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    if (!WalkState)
    {
        return AE_NO_MEMORY;
    }

    WalkState->NextOp = NULL;
    WalkState->Params = NULL;
    WalkState->WalkType = WalkType;
    WalkState->CallerReturnDesc = &ObjDesc;

    /*
     * Examine the entire subtree -- all nodes must be constants
     * or type 3/4/5 opcodes
     */
    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
        OpcAmlCheckForConstant, NULL, WalkState);

    /*
     * Did we find an entire subtree that contains all constants and type 3/4/5
     * opcodes?  (Only AE_OK or AE_TYPE returned from above)
     */
    if (Status == AE_TYPE)
    {
        /* Subtree cannot be reduced to a constant */

        if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
        {
            AcpiDsDeleteWalkState (WalkState);
            return (AE_OK);
        }

        /* Don't descend any further, and use a default "constant" value */

        Status = AE_CTRL_DEPTH;
    }
    else
    {
        /* Subtree can be reduced */

        /* Allocate a new temporary root for this subtree */

        RootOp = TrAllocateNode (PARSEOP_INTEGER);
        if (!RootOp)
        {
            return (AE_NO_MEMORY);
        }

        RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;

        OriginalParentOp = Op->Common.Parent;
        Op->Common.Parent = RootOp;

        /* Hand off the subtree to the AML interpreter */

        Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
            OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
        Op->Common.Parent = OriginalParentOp;

        /* TBD: we really *should* release the RootOp node */

        if (ACPI_SUCCESS (Status))
        {
            TotalFolds++;

            /* Get the final result */

            Status = AcpiDsResultPop (&ObjDesc, WalkState);
        }

        /* Check for error from the ACPICA core */

        if (ACPI_FAILURE (Status))
        {
            AslCoreSubsystemError (Op, Status,
                "Failure during constant evaluation", FALSE);
        }
    }

    if (ACPI_FAILURE (Status))
    {
        /* We could not resolve the subtree for some reason */

        AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
            Op->Asl.ParseOpName);

        /* Set the subtree value to ZERO anyway. Eliminates further errors */

        OpcUpdateIntegerNode (Op, 0);
    }
    else
    {
        AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
            Op->Asl.ParseOpName);

        /*
         * Because we know we executed type 3/4/5 opcodes above, we know that
         * the result must be either an Integer, String, or Buffer.
         */
        switch (ObjDesc->Common.Type)
        {
        case ACPI_TYPE_INTEGER:

            OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);

            DbgPrint (ASL_PARSE_OUTPUT,
                "Constant expression reduced to (%s) %8.8X%8.8X\n",
                Op->Asl.ParseOpName,
                ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
            break;


        case ACPI_TYPE_STRING:

            Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
            Op->Common.AmlOpcode = AML_STRING_OP;
            Op->Asl.AmlLength = ACPI_STRLEN (ObjDesc->String.Pointer) + 1;
            Op->Common.Value.String = ObjDesc->String.Pointer;

            DbgPrint (ASL_PARSE_OUTPUT,
                "Constant expression reduced to (STRING) %s\n",
                Op->Common.Value.String);

            break;


        case ACPI_TYPE_BUFFER:

            Op->Asl.ParseOpcode = PARSEOP_BUFFER;
            Op->Common.AmlOpcode = AML_BUFFER_OP;
            Op->Asl.CompileFlags = NODE_AML_PACKAGE;
            UtSetParseOpName (Op);

            /* Child node is the buffer length */

            RootOp = TrAllocateNode (PARSEOP_INTEGER);

            RootOp->Asl.AmlOpcode = AML_DWORD_OP;
            RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
            RootOp->Asl.Parent = Op;

            (void) OpcSetOptimalIntegerSize (RootOp);

            Op->Asl.Child = RootOp;
            Op = RootOp;
            UtSetParseOpName (Op);

            /* Peer to the child is the raw buffer data */

            RootOp = TrAllocateNode (PARSEOP_RAW_DATA);
            RootOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
            RootOp->Asl.AmlLength = ObjDesc->Buffer.Length;
            RootOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
            RootOp->Asl.Parent = Op->Asl.Parent;

            Op->Asl.Next = RootOp;
            Op = RootOp;

            DbgPrint (ASL_PARSE_OUTPUT,
                "Constant expression reduced to (BUFFER) length %X\n",
                ObjDesc->Buffer.Length);
            break;


        default:
            printf ("Unsupported return type: %s\n",
                AcpiUtGetObjectTypeName (ObjDesc));
            break;
        }
    }

    UtSetParseOpName (Op);
    Op->Asl.Child = NULL;

    AcpiDsDeleteWalkState (WalkState);
    return (AE_CTRL_DEPTH);
}
示例#3
0
文件: aslfold.c 项目: olsner/acpica
ACPI_STATUS
OpcAmlConstantWalk (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState;
    ACPI_STATUS             Status = AE_OK;


    if (Op->Asl.CompileFlags == 0)
    {
        return (AE_OK);
    }

    /*
     * Only interested in subtrees that could possibly contain
     * expressions that can be evaluated at this time
     */
    if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
          (Op->Asl.CompileFlags & NODE_IS_TARGET))
    {
        return (AE_OK);
    }

    /* Create a new walk state */

    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    if (!WalkState)
    {
        return (AE_NO_MEMORY);
    }

    WalkState->NextOp = NULL;
    WalkState->Params = NULL;

    /*
     * Examine the entire subtree -- all nodes must be constants
     * or type 3/4/5 opcodes
     */
    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
        OpcAmlCheckForConstant, NULL, WalkState);

    /*
     * Did we find an entire subtree that contains all constants
     * and type 3/4/5 opcodes?
     */
    switch (Status)
    {
    case AE_OK:

        /* Simple case, like Add(3,4) -> 7 */

        Status = TrSimpleConstantReduction (Op, WalkState);
        break;

    case AE_CTRL_RETURN_VALUE:

        /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */

        Status = TrTransformToStoreOp (Op, WalkState);
        break;

    case AE_TYPE:

        AcpiDsDeleteWalkState (WalkState);
        return (AE_OK);

    default:
        AcpiDsDeleteWalkState (WalkState);
        break;
    }

    if (ACPI_FAILURE (Status))
    {
        DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n",
            AcpiFormatException (Status));

        /* We could not resolve the subtree for some reason */

        AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
            (char *) AcpiFormatException (Status));

        /* Set the subtree value to ZERO anyway. Eliminates further errors */

        OpcUpdateIntegerNode (Op, 0);
    }

    return (AE_OK);
}