From 136eac2a0638d3c751b1987603f71a9ae26879fd Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Mon, 20 Jul 2015 22:31:50 +0000 Subject: Import ACPICA 20150717. --- source/compiler/aslxref.c | 481 +++++++++++++++++++++++++++++++--------------- 1 file changed, 327 insertions(+), 154 deletions(-) (limited to 'source/compiler/aslxref.c') diff --git a/source/compiler/aslxref.c b/source/compiler/aslxref.c index 8ffe5ad6a1d1..6b65bb1699bf 100644 --- a/source/compiler/aslxref.c +++ b/source/compiler/aslxref.c @@ -66,6 +66,10 @@ XfNamespaceLocateEnd ( UINT32 Level, void *Context); +static ACPI_PARSE_OBJECT * +XfGetParentMethod ( + ACPI_PARSE_OBJECT *Op); + static BOOLEAN XfObjectExists ( char *Name); @@ -280,59 +284,16 @@ XfCheckFieldRange ( } -#ifdef __UNDER_DEVELOPMENT -/******************************************************************************* - * - * FUNCTION: XfIsObjectParental - * - * PARAMETERS: ChildOp - Op to be checked - * PossibleParentOp - Determine if this op is in the family - * - * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp - * - * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to - * detect if a method is declared within another method. - * - ******************************************************************************/ - -static BOOLEAN -XfIsObjectParental ( - ACPI_PARSE_OBJECT *ChildOp, - ACPI_PARSE_OBJECT *PossibleParentOp) -{ - ACPI_PARSE_OBJECT *ParentOp; - - - /* Search upwards through the tree for possible parent */ - - ParentOp = ChildOp; - while (ParentOp) - { - if (ParentOp == PossibleParentOp) - { - return (TRUE); - } - - ParentOp = ParentOp->Asl.Parent; - } - - return (FALSE); -} - - /******************************************************************************* * * FUNCTION: XfGetParentMethod * - * PARAMETERS: Op - Op to be checked - * - * RETURN: Op for parent method. NULL if object is not within a method. + * PARAMETERS: Op - Parse Op to be checked * - * DESCRIPTION: Determine if an object is within a control method. Used to - * implement special rules for named references from within a - * control method. + * RETURN: Control method Op if found. NULL otherwise * - * NOTE: It would be better to have the parser set a flag in the Op if possible. + * DESCRIPTION: Find the control method parent of a parse op. Returns NULL if + * the input Op is not within a control method. * ******************************************************************************/ @@ -340,120 +301,22 @@ static ACPI_PARSE_OBJECT * XfGetParentMethod ( ACPI_PARSE_OBJECT *Op) { - ACPI_PARSE_OBJECT *ParentOp; - - - if (!Op) - { - return (NULL); - } - - if (Op->Asl.ParseOpcode == PARSEOP_METHOD) - { - return (NULL); - } - - /* Walk upwards through the parse tree, up to the root if necessary */ - - ParentOp = Op; - while (ParentOp) - { - if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) - { - return (ParentOp); - } - - ParentOp = ParentOp->Asl.Parent; - } - - /* Object is not within a method */ - - return (NULL); -} - - -/******************************************************************************* - * - * FUNCTION: XfCheckIllegalReference - * - * PARAMETERS: Op - Op referring to the target - * TargetNode - Target of the reference - * - * RETURN: None. Emits error message for an illegal reference - * - * DESCRIPTION: Determine if a named reference is legal. A "named" reference - * is something like: Store(ABCD, ...), where ABCD is an AML - * Nameseg or Namepath. - * - * NOTE: Caller must ensure that the name Op is in fact a reference, and not - * an actual name declaration (creation of a named object). - * - ******************************************************************************/ - -static void -XfCheckIllegalReference ( - ACPI_PARSE_OBJECT *Op, - ACPI_NAMESPACE_NODE *TargetNode) -{ - ACPI_PARSE_OBJECT *MethodOp1; - ACPI_PARSE_OBJECT *MethodOp2; - ACPI_PARSE_OBJECT *TargetOp; - - - /* - * Check for an illegal reference to a named object: - * - * 1) References from one control method to another, non-parent - * method are not allowed, they will fail at runtime. - * - * 2) Forward references within a control method are not allowed. - * AML interpreters use a one-pass parse of control methods - * so these forward references will fail at runtime. - */ - TargetOp = TargetNode->Op; - - MethodOp1 = XfGetParentMethod (Op); - MethodOp2 = XfGetParentMethod (TargetOp); - - /* Are both objects within control method(s)? */ - - if (!MethodOp1 || !MethodOp2) - { - return; - } + ACPI_PARSE_OBJECT *NextOp; - /* Objects not in the same method? */ - if (MethodOp1 != MethodOp2) + NextOp = Op->Asl.Parent; + while (NextOp) { - /* - * 1) Cross-method named reference - * - * This is OK if and only if the target reference is within in a - * method that is a parent of current method - */ - if (!XfIsObjectParental (MethodOp1, MethodOp2)) + if (NextOp->Asl.AmlOpcode == AML_METHOD_OP) { - AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, - Op->Asl.ExternalName); + return (NextOp); } - } - /* - * 2) Both reference and target are in the same method. Check if this is - * an (illegal) forward reference by examining the exact source code - * location of each (the referenced object and the object declaration). - * This is a bit nasty, yet effective. - */ - else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) - { - AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, - Op->Asl.ExternalName); + NextOp = NextOp->Asl.Parent; } + return (NULL); /* No parent method found */ } -#endif - /******************************************************************************* * @@ -496,10 +359,67 @@ XfNamespaceLocateBegin ( UINT8 Message = 0; const ACPI_OPCODE_INFO *OpInfo; UINT32 Flags; + ASL_METHOD_LOCAL *MethodLocals = NULL; + ASL_METHOD_LOCAL *MethodArgs = NULL; + int RegisterNumber; + UINT32 i; ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op); + + if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node) + { + Node = Op->Asl.Node; + + /* Support for method LocalX/ArgX analysis */ + + if (!Node->MethodLocals) + { + /* Create local/arg info blocks */ + + MethodLocals = UtLocalCalloc ( + sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS); + Node->MethodLocals = MethodLocals; + + MethodArgs = UtLocalCalloc ( + sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS); + Node->MethodArgs = MethodArgs; + + /* + * Get the method argument count + * First, get the name node + */ + NextOp = Op->Asl.Child; + + /* Get the NumArguments node */ + + NextOp = NextOp->Asl.Next; + Node->ArgCount = (UINT8) + (((UINT8) NextOp->Asl.Value.Integer) & 0x07); + + /* We will track all posible ArgXs */ + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) + { + if (i < Node->ArgCount) + { + /* Real Args are always "initialized" */ + + MethodArgs[i].Flags = ASL_ARG_INITIALIZED; + } + else + { + /* Other ArgXs can be used as locals */ + + MethodArgs[i].Flags = ASL_ARG_IS_LOCAL; + } + + MethodArgs[i].Op = Op; + } + } + } + /* * If this node is the actual declaration of a name * [such as the XXXX name in "Method (XXXX)"], @@ -512,10 +432,88 @@ XfNamespaceLocateBegin ( return_ACPI_STATUS (AE_OK); } - /* We are only interested in opcodes that have an associated name */ - OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); + /* Check method LocalX variables */ + + if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE) + { + /* Find parent method Op */ + + NextOp = XfGetParentMethod (Op); + if (!NextOp) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get method node */ + + Node = NextOp->Asl.Node; + + RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */ + MethodLocals = Node->MethodLocals; + + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + /* Local is being initialized */ + + MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED; + MethodLocals[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* Mark this Local as referenced */ + + MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED; + MethodLocals[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* Check method ArgX variables */ + + if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT) + { + /* Find parent method Op */ + + NextOp = XfGetParentMethod (Op); + if (!NextOp) + { + return_ACPI_STATUS (AE_OK); + } + + /* Get method node */ + + Node = NextOp->Asl.Node; + + /* Get Arg # */ + + RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */ + MethodArgs = Node->MethodArgs; + + if (Op->Asl.CompileFlags & NODE_IS_TARGET) + { + /* Arg is being initialized */ + + MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED; + MethodArgs[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* Mark this Arg as referenced */ + + MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED; + MethodArgs[RegisterNumber].Op = Op; + + return_ACPI_STATUS (AE_OK); + } + + /* + * After method ArgX and LocalX, we are only interested in opcodes + * that have an associated name + */ if ((!(OpInfo->Flags & AML_NAMED)) && (!(OpInfo->Flags & AML_CREATE)) && (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) && @@ -1094,3 +1092,178 @@ XfNamespaceLocateEnd ( return_ACPI_STATUS (AE_OK); } + + +#ifdef __UNDER_DEVELOPMENT +/******************************************************************************* + * + * FUNCTION: XfIsObjectParental + * + * PARAMETERS: ChildOp - Op to be checked + * PossibleParentOp - Determine if this op is in the family + * + * RETURN: TRUE if ChildOp is a descendent of PossibleParentOp + * + * DESCRIPTION: Determine if an Op is a descendent of another Op. Used to + * detect if a method is declared within another method. + * + ******************************************************************************/ + +static BOOLEAN +XfIsObjectParental ( + ACPI_PARSE_OBJECT *ChildOp, + ACPI_PARSE_OBJECT *PossibleParentOp) +{ + ACPI_PARSE_OBJECT *ParentOp; + + + /* Search upwards through the tree for possible parent */ + + ParentOp = ChildOp; + while (ParentOp) + { + if (ParentOp == PossibleParentOp) + { + return (TRUE); + } + + ParentOp = ParentOp->Asl.Parent; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: XfGetParentMethod + * + * PARAMETERS: Op - Op to be checked + * + * RETURN: Op for parent method. NULL if object is not within a method. + * + * DESCRIPTION: Determine if an object is within a control method. Used to + * implement special rules for named references from within a + * control method. + * + * NOTE: It would be better to have the parser set a flag in the Op if possible. + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +XfGetParentMethod ( + ACPI_PARSE_OBJECT *Op) +{ + ACPI_PARSE_OBJECT *ParentOp; + + + if (!Op) + { + return (NULL); + } + + if (Op->Asl.ParseOpcode == PARSEOP_METHOD) + { + return (NULL); + } + + /* Walk upwards through the parse tree, up to the root if necessary */ + + ParentOp = Op; + while (ParentOp) + { + if (ParentOp->Asl.ParseOpcode == PARSEOP_METHOD) + { + return (ParentOp); + } + + ParentOp = ParentOp->Asl.Parent; + } + + /* Object is not within a method */ + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: XfCheckIllegalReference + * + * PARAMETERS: Op - Op referring to the target + * TargetNode - Target of the reference + * + * RETURN: None. Emits error message for an illegal reference + * + * DESCRIPTION: Determine if a named reference is legal. A "named" reference + * is something like: Store(ABCD, ...), where ABCD is an AML + * Nameseg or Namepath. + * + * NOTE: Caller must ensure that the name Op is in fact a reference, and not + * an actual name declaration (creation of a named object). + * + ******************************************************************************/ + +static void +XfCheckIllegalReference ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE *TargetNode) +{ + ACPI_PARSE_OBJECT *MethodOp1; + ACPI_PARSE_OBJECT *MethodOp2; + ACPI_PARSE_OBJECT *TargetOp; + + + /* + * Check for an illegal reference to a named object: + * + * 1) References from one control method to another, non-parent + * method are not allowed, they will fail at runtime. + * + * 2) Forward references within a control method are not allowed. + * AML interpreters use a one-pass parse of control methods + * so these forward references will fail at runtime. + */ + TargetOp = TargetNode->Op; + + MethodOp1 = XfGetParentMethod (Op); + MethodOp2 = XfGetParentMethod (TargetOp); + + /* Are both objects within control method(s)? */ + + if (!MethodOp1 || !MethodOp2) + { + return; + } + + /* Objects not in the same method? */ + + if (MethodOp1 != MethodOp2) + { + /* + * 1) Cross-method named reference + * + * This is OK if and only if the target reference is within in a + * method that is a parent of current method + */ + if (!XfIsObjectParental (MethodOp1, MethodOp2)) + { + AslError (ASL_ERROR, ASL_MSG_ILLEGAL_METHOD_REF, Op, + Op->Asl.ExternalName); + } + } + + /* + * 2) Both reference and target are in the same method. Check if this is + * an (illegal) forward reference by examining the exact source code + * location of each (the referenced object and the object declaration). + * This is a bit nasty, yet effective. + */ + else if (Op->Asl.LogicalByteOffset < TargetOp->Asl.LogicalByteOffset) + { + AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op, + Op->Asl.ExternalName); + } + +} +#endif -- cgit v1.2.3