Beispiel #1
0
        /// <summary>
        /// Generate the code which has to be inserted at the place of the filter specified by the visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            MethodReference methodToCall;

            // Get JoinPointContext
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            // Get the methodReference
            MethodReference methodReference = (MethodReference)originalCall;
            TypeDefinition  parentType      = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);

            // Get method to call
            methodToCall = GetMethodToCall(visitor, filterAction, parentType);

            if (methodToCall == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.AdviceMethodNotFound, getSelector(filterAction), getTarget(filterAction)));
            }

            // Set JoinPointContext
            WeaveStrategyUtilities.SetJoinPointContext(visitor, methodReference, filterAction);

            // Check if it is an innercall and set innercall context:
            if (getTarget(filterAction).Equals(FilterAction.InnerTarget))
            {
                WeaveStrategyUtilities.SetInnerCall(visitor, methodToCall);
            }

            // Do the advice-call
            AdviceActionWeaveStrategy.CallAdvice(visitor, filterAction, parentType, methodToCall, jpcVar);

            // Add nop to enable debugging
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Nop));
        }
Beispiel #2
0
        public static void SetJoinPointContext(
            ICecilInliningInstructionVisitor visitor,
            MethodReference originalCall, FilterAction filterAction)
        {
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            // Store current target
            if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                filterAction.Target.Equals(FilterAction.SelfTarget))
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextGetStartTarget)));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextSetCurrentTarget)));
            }
            else if (visitor.Method.HasThis)
            {
                TypeDefinition  parentType = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);
                FieldDefinition field      = parentType.Fields.GetField(filterAction.Target);
                if (field == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.FieldNotFound, filterAction.Target));
                }
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, field));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextSetCurrentTarget)));
            }
            else
            {
                // set to null for static methods
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                               CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                    CachedMethodDefinition.JoinPointContextSetCurrentTarget)));
            }

            // store current selector
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldstr, filterAction.Selector));
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
                                                           CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
                                                                                                CachedMethodDefinition.JoinPointContextSetCurrentSelector)));


            // Store substitution target
            //if (filterAction.SubstitutionTarget.Equals(FilterAction.InnerTarget) ||
            //    filterAction.SubstitutionTarget.Equals(FilterAction.SelfTarget))
            //{
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextGetStartTarget)));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextGetSubstitutionTarget)));
            //}
            //else if (visitor.Method.HasThis)
            //{
            //    TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);
            //    FieldDefinition field = parentType.Fields.GetField(filterAction.SubstitutionTarget);
            //    if (field == null)
            //    {
            //        throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
            //            Properties.Resources.FieldNotFound, filterAction.SubstitutionTarget));
            //    }
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, field));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextSetSubstitutionTarget)));
            //}
            //else
            //{
            //    // set to null for static methods
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
            //    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //        CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //            CachedMethodDefinition.JoinPointContextSetSubstitutionTarget)));
            //}

            // store substitution selector
            // TODO no longer relevant
            //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldstr, filterAction.SubstitutionSelector));
            //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt,
            //	CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition,
            //		CachedMethodDefinition.JoinPointContextSetSubstitutionSelector)));
        }
Beispiel #3
0
        /// <summary>
        /// Visits the condition literal.
        /// </summary>
        /// <remarks>
        /// Generate a call to a condition. This is a call to a boolean method.
        /// </remarks>
        /// <param name="conditionLiteral">The condition literal.</param>
        public void VisitConditionLiteral(ConditionLiteral conditionLiteral)
        {
            // Get the condition
            Condition con = GetConditionByName(conditionLiteral.Name);

            if (con == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.ConditionNotFound, conditionLiteral.Name));
            }

            // Get the parenttype
            TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(_visitor.Method.DeclaringType);

            // Get the method
            MethodReference method;
            FieldDefinition target = null;

            // Check if this is an inner or self target.
            if (con.Reference.Target != null &&
                (con.Reference.Target.Equals(Reference.InnerTarget) ||
                 con.Reference.Target.Equals(Reference.SelfTarget)
                ))
            {
                method = CecilUtilities.ResolveMethod(
                    con.Reference.Selector, WeaveType.Name,
                    con.Reference.Assembly, String.Empty);
            }
            else if (con.Reference.Target != null &&
                     (IsInternal(con.Reference.Target) || IsExternal(con.Reference.Target))
                     )
            {
                if (!Method.HasThis)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.StaticReferenceInternalExternal,
                                                              Method.Name,
                                                              Method.DeclaringType.FullName));
                }

                target = parentType.Fields.GetField(con.Reference.Target);

                TypeDefinition   fieldType = CecilUtilities.ResolveTypeDefinition(target.FieldType);
                MethodDefinition md        = CecilUtilities.ResolveMethod(fieldType, con.Reference.Selector, new Type[0]);

                // If method with no parameters cannot be found, try to find method with JPC context as parameter
                if (md == null)
                {
                    md = CecilUtilities.ResolveMethod(fieldType, con.Reference.Selector, m_JpcTypes);
                }

                if (md == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.MethodNotFound2, con.Reference.Selector, con.Reference.Target, fieldType.FullName));
                }

                method = _visitor.TargetAssemblyDefinition.MainModule.Import(md);
            }
            else
            {
                method = CecilUtilities.ResolveMethod(
                    con.Reference.Selector,
                    con.Reference.FullTypeName,
                    con.Reference.Assembly, String.Empty);
            }

            // If we could not find the condition method, throw an exception
            if (method == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.MethodNotFound,
                                                          con.Reference.Selector,
                                                          con.Reference.FullTypeName,
                                                          con.Reference.Assembly));
            }

            // If it is an inner or self call, we set the InnerCall context
            if (con.Reference.Target != null &&
                (con.Reference.Target.Equals(Reference.InnerTarget) ||
                 con.Reference.Target.Equals(Reference.SelfTarget)
                ))
            {
                // Set innercall context
                if (con.Reference.InnerCallContext >= 0)
                {
                    // Load the this parameter
                    if (!Method.HasThis)
                    {
                        Instructions.Add(Worker.Create(OpCodes.Ldnull));
                    }
                    else
                    {
                        Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This));
                    }

                    // Load the methodId
                    Instructions.Add(Worker.Create(OpCodes.Ldc_I4, con.Reference.InnerCallContext));

                    // Call the SetInnerCall
                    Instructions.Add(Worker.Create(OpCodes.Call,
                                                   CreateMethodReference(typeof(FilterContext).GetMethod("SetInnerCall",
                                                                                                         new Type[] { typeof(object), typeof(int) }))));
                }

                // Load the this pointer
                Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This));
            }
            // internal/external and not static:
            else if (target != null && method.HasThis)
            {
                // Load the this pointer
                Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This));

                // Load the field
                Instructions.Add(Worker.Create(OpCodes.Ldfld, target));
            }
            // else do nothing, because of static call

            // Convert to a method definition so we can inspect the custom attributes
            MethodDefinition methodDef = (MethodDefinition)method;

            if (methodDef != null)
            {
                // Find a custom attribute to use
                foreach (CustomAttribute ca in methodDef.CustomAttributes)
                {
                    // Retrieve the type name of the custom attribute
                    String typeName = ca.Constructor.DeclaringType.ToString();

                    // Check if the custom attribute is called ConditionParameter so we do not activate all kinds of attributes
                    if (typeName.Contains(ConditionParameterName))
                    {
                        // Resolve the CP
                        ConditionParameterAttribute cpa = ResolveConditionParameter(typeName);

                        // Do we have a CPA?
                        if (cpa != null)
                        {
                            // Check if the condition is valid for this code generation
                            if (cpa.IsValidCondition(methodDef))
                            {
                                // Generate the code needed for this condition
                                cpa.Generate(_visitor, Method, methodDef);
                            }
                            else
                            {
                                // Throw an exception since the condition is not valid. We cannot create valid code for this.
                                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                                          Properties.Resources.ConditionParameterInvalid,
                                                                          typeName, methodDef.ToString(), cpa.RequiredCondition));
                            }
                        }
                        else
                        {
                            // Throw an exception, we cannot create the custom attribute
                            throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                                      Properties.Resources.ConditionParameterNotFound,
                                                                      typeName));
                        }

                        // Quit the for loop. If there are more custom attributes, we simply skip them.
                        break;
                    }
                }
            }

            // Check if we have to add the JPC
            // Legacy code, should be able to do this using the ConditionParameter?
            if (method.Parameters.Count == 1)
            {
                if (method.Parameters[0].ParameterType.FullName.Equals(typeof(JoinPointContext).FullName))
                {
                    VariableDefinition jpcVar = _visitor.CreateJoinPointContextLocal();
                    Instructions.Add(Worker.Create(OpCodes.Ldloc, jpcVar));
                }
            }

            // Create a call instruction
            Instructions.Add(Worker.Create(OpCodes.Call, TargetAssemblyDefinition.MainModule.Import(method)));
        }
Beispiel #4
0
        /// <summary>
        /// Generate the code which has to be inserted at the place of the filter specified by the visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // Get JoinPointContext
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            FieldDefinition target = null;

            // Get the methodReference
            MethodReference methodReference = null;

            TypeDefinition parentTypeDefinition = (TypeDefinition)(visitor.Method.DeclaringType);
            TypeReference  parentTypeReference  = visitor.Method.DeclaringType;

            if (parentTypeReference.GenericParameters.Count > 0)
            {
                GenericInstanceType git = new GenericInstanceType(visitor.Method.DeclaringType);

                foreach (GenericParameter gp in originalCall.DeclaringType.GenericParameters)
                {
                    git.GenericArguments.Add(gp);
                }

                parentTypeReference = git;
            }

            // Get the called method
            if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                filterAction.Target.Equals(FilterAction.SelfTarget))
            {
                if (filterAction.Selector.Equals(originalCall.Name))
                {
                    if (parentTypeReference is GenericInstanceType)
                    {
                        methodReference = new MethodReference(originalCall.Name,
                                                              parentTypeReference, originalCall.ReturnType.ReturnType,
                                                              originalCall.HasThis, originalCall.ExplicitThis,
                                                              originalCall.CallingConvention);
                        methodReference.DeclaringType = parentTypeReference;

                        foreach (ParameterDefinition param in originalCall.Parameters)
                        {
                            methodReference.Parameters.Add(param);
                        }

                        methodReference = visitor.TargetAssemblyDefinition.MainModule.Import(methodReference, parentTypeDefinition);

                        /* This piece of code must solve the following problem:
                         *
                         * class<T> Test
                         * {
                         *    void Func(T a)
                         *    {
                         *       // inner call
                         *       Test<T>.Func(a);
                         *    }
                         * }
                         *
                         * Resolving Test<T> to a GenericInstanceType is no problem
                         * The methodReference must use the GenericInstanceType as its base type
                         * Import the new methodReference before use.
                         */
                    }
                    else
                    {
                        methodReference = originalCall;
                    }
                }
                else
                {
                    methodReference = CecilUtilities.ResolveMethod(parentTypeDefinition,
                                                                   filterAction.Selector, originalCall);
                }
            }
            else
            {
                target = parentTypeDefinition.Fields.GetField(filterAction.Target);
                if (target == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.FieldNotFound, filterAction.Target));
                }

                TypeDefinition   fieldType = CecilUtilities.ResolveTypeDefinition(target.FieldType);
                MethodDefinition md        = CecilUtilities.ResolveMethod(fieldType,
                                                                          filterAction.Selector, originalCall);

                if (md == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              "Method {0} not found in {1}", filterAction.Selector, fieldType.FullName));
                }

                methodReference = visitor.TargetAssemblyDefinition.MainModule.Import(md);
            }

            // If there is no method reference, then we cannot dispatch. Raise an exception.
            if (methodReference == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.MethodNotFound, parentTypeReference.ToString(), filterAction.Selector));
            }


            // Check if it is an innercall and set innercall context:
            if (filterAction.Target.Equals(FilterAction.InnerTarget))
            {
                WeaveStrategyUtilities.SetInnerCall(visitor, methodReference);
            }


            // Generic arguments; add the generic parameters as generic argument to a GenericInstanceMethod
            if (originalCall.GenericParameters.Count > 0)
            {
                // Original call has generics, so add to the new memberreference
                GenericInstanceMethod gim = new GenericInstanceMethod(methodReference);
                foreach (GenericParameter gp in originalCall.GenericParameters)
                {
                    gim.GenericArguments.Add(gp);
                }
                methodReference = gim;
            }

            // Place the arguments on the stack first

            // Place target on the stack
            if (methodReference.HasThis)
            {
                if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                    filterAction.Target.Equals(FilterAction.SelfTarget))
                {
                    WeaveStrategyUtilities.LoadSelfObject(visitor, jpcVar);
                }
                else
                {
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, target));
                }
            }

            // Place arguments on the stack
            WeaveStrategyUtilities.LoadArguments(visitor, originalCall, jpcVar);

            // Call the method
            if (filterAction.Target.Equals(FilterAction.InnerTarget) &&
                filterAction.Selector.Equals(originalCall.Name))
            {
                // Because it is an inner call targeting the method itself, we must call the method
                // in the class itself. Therefore we do a Call instead of a Callvirt, to prevent that
                // the call is dispatched to an overriding method in a subclass.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodReference));
            }
            else if (visitor.CalledMethod.HasThis)
            {
                // Because we dispatch to another method than the original called method, we do a Callvirt
                // so that an overriding method in a subclass may be called.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodReference));
            }
            else
            {
                // static method cannot be called with Callvirt.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodReference));
            }

            // Store the return value:
            WeaveStrategyUtilities.StoreReturnValue(visitor, originalCall, jpcVar);

            // Restore arguments:
            WeaveStrategyUtilities.RestoreArguments(visitor, originalCall, jpcVar);
        }
Beispiel #5
0
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // The method we have to call, an Execute(JoinPointContext) function.
            MethodReference methodToCall;

            // Create FilterAction object:
            FilterActionElement filterActionElement;

            filterActionElement = DefaultWeaveStrategy.GetFilterActionElement(visitor.WeaveConfiguration.FilterActions, filterAction.FullName);

            if (filterActionElement == null)
            {
                throw new ILWeaverException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.CouldNotResolveFilterAction, filterAction.FullName));
            }

            // Get JoinPointContext
            VariableDefinition jpcVar = null;

            if (filterActionElement.CreateJPC)
            {
                jpcVar = visitor.CreateJoinPointContextLocal();
            }

            // Get the methodReference
            MethodReference methodReference = (MethodReference)originalCall;

            // TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(methodReference.DeclaringType);

            // Set JoinPointContext
            if (filterActionElement.CreateJPC)
            {
                WeaveStrategyUtilities.SetJoinPointContext(visitor, methodReference, filterAction);
            }

            TypeReference typeRef =
                CecilUtilities.ResolveType(filterAction.FullName, filterActionElement.Assembly, null);
            TypeDefinition typeDef =
                CecilUtilities.ResolveTypeDefinition(typeRef);
            MethodReference constructor = typeDef.Constructors.GetConstructor(false, new Type[0]);

            if (constructor == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.TypeNotFound, filterAction.FullName));
            }

            constructor = visitor.TargetAssemblyDefinition.MainModule.Import(constructor);
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Newobj, constructor));

            // Get method to call
            methodToCall = CecilUtilities.ResolveMethod(typeDef, "Execute", new Type[] { typeof(JoinPointContext) });

            // Check for null value
            if (methodToCall == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.AdviceMethodNotFound, "Execute", filterAction.FullName));
            }

            methodToCall = visitor.TargetAssemblyDefinition.MainModule.Import(methodToCall);

            // Load the JoinPointObject as the parameter if required
            if (filterActionElement.CreateJPC)
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            }
            else
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
            }

            // Do the call
            // We can safely emit a callvirt here. The JITter will make the right call.
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodToCall));
        }