public void FillInStaticConstructor(bool createTemporaryAssemblies, string[] preloadOrder, string resourcesHash, Checksums checksums)
        {
            var loaderMethod         = info.StaticConstructorMethod;
            InstructionReader reader = loaderMethod.MethodBody.CreateInstructionReader();

            reader.EnterInstructionBlock(loaderMethod.MethodBody.RootInstructionBlock);
            reader.EnterInstructionSequence(loaderMethod.MethodBody.RootInstructionBlock.LastInstructionSequence);
            while (reader.ReadInstruction())
            {
                if (reader.CurrentInstruction.OpCodeNumber == OpCodeNumber.Ret)
                {
                    break;
                }
            }
            Console.WriteLine(reader.CurrentInstruction);
            reader.CurrentInstructionSequence.SplitAroundReaderPosition(reader, out _, out _);
            var newSequence =
                reader.CurrentInstructionBlock.AddInstructionSequence(null, NodePosition.Before,
                                                                      reader.CurrentInstructionSequence);

            InstructionWriter writer = InstructionWriter.GetInstance();

            writer.AttachInstructionSequence(newSequence);
            var orderedResources = preloadOrder
                                   .Join(this.manifest.Resources, p => p.ToLowerInvariant(),
                                         r =>
            {
                var parts = r.Name.Split('.');
                GetNameAndExt(parts, out var name, out _);
                return(name);
            }, (s, r) => r)
        private static void InjectCustomMethods(TypeDefDeclaration enhancedType, InstructionWriter writer,
                                                CreatedEmptyMethod methodBody)
        {
            // Custom equality methods.
            foreach (var customEqualsMethod in enhancedType.Methods)
            {
                if (customEqualsMethod.CustomAttributes.GetOneByType(
                        "PostSharp.Community.StructuralEquality.AdditionalEqualsMethodAttribute") != null)
                {
                    if (customEqualsMethod.IsStatic ||
                        !customEqualsMethod.ReturnParameter.ParameterType.IsIntrinsic(IntrinsicType.Boolean) ||
                        customEqualsMethod.Parameters.Count != 1 ||
                        !customEqualsMethod.Parameters[0].ParameterType.GetTypeDefinition().Equals(enhancedType)
                        )
                    {
                        CustomMethodSignatureError(enhancedType, customEqualsMethod);
                    }

                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                    writer.EmitInstructionMethod(OpCodeNumber.Call, customEqualsMethod.GetCanonicalGenericInstance());
                    writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, methodBody.ReturnSequence);
                }
            }
        }
        public static string Format(MethodData data, bool inlineExceptionHandlers = false)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            var sections    = inlineExceptionHandlers ? BuildSections(data) : null;
            var builder     = new StringBuilder();
            var jumpTargets = CollectJumpTargets(data, sections == null);

            WriteHeader(data, builder);

            var writer = new InstructionWriter(builder, jumpTargets, data.Instructions);

            if (sections != null)
            {
                writer.WriteInstructions(sections);
            }
            else
            {
                writer.WriteInstructions();
                WriteExceptionHandlers(data, builder);
            }

            return(builder.ToString());
        }
示例#4
0
            public void EmitGetIsEnabled(InstructionWriter writer, LogSeverity logSeverity)
            {
                writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.loggerField);

                switch (logSeverity)
                {
                case LogSeverity.Trace:
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.getIsTraceEnabledMethod);
                    break;

                case LogSeverity.Info:
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.getIsInfoEnabledMethod);
                    break;

                case LogSeverity.Warning:
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.getIsWarnEnabledMethod);
                    break;

                case LogSeverity.Error:
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.getIsErrorEnabledMethod);
                    break;

                case LogSeverity.Fatal:
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.getIsFatalEnabledMethod);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("logSeverity");
                }
            }
                private void EmitMessage(InstructionBlock block, InstructionWriter writer, MethodDefDeclaration targetMethod, string messageFormatString)
                {
                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);

                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);

                    writer.AttachInstructionSequence(sequence);

                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, LogSeverity.Trace);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    int  parameterCount = Context.MethodMapping.MethodSignature.ParameterCount;
                    bool hasThis        = Context.MethodMapping.MethodSignature.CallingConvention == CallingConvention.HasThis;

                    builder.EmitWrite(writer, block, messageFormatString, parameterCount, LogSeverity.Trace, null,
                                      (i, instructionWriter) =>
                    {
                        instructionWriter.EmitInstructionInt16(OpCodeNumber.Ldarg, (short)(hasThis ? i + 1 : i));
                        instructionWriter.EmitConvertToObject(
                            this.Context.MethodMapping.MethodSignature.GetParameterType(i));
                    });

                    writer.DetachInstructionSequence();
                }
        protected override void Weave(WeavingContext context, InstructionWriter writer)
        {
            var loggerField = GetLoggerField(context, true);
            writer.EmitInstructionField(OpCodeNumber.Ldsfld, loggerField);

            writer.EmitInstructionMethod(OpCodeNumber.Call, GetLoggerMethod(context.Method.Module));
        }
 public static void RedirectBranchInstructions(this InstructionBlock block, InstructionReader reader, InstructionWriter writer, InstructionSequence branchTargetSequence, Predicate<Instruction> predicate)
 {
     if (block.HasChildrenBlocks) {
         for (InstructionBlock block1 = block.FirstChildBlock; block1 != null; block1 = block1.NextSiblingBlock) {
             if (!block1.HasExceptionHandlers)
                 RedirectBranchInstructions(block1, reader, writer, branchTargetSequence, predicate);
         }
     }
     reader.JumpToInstructionBlock(block);
     if (block.HasInstructionSequences) {
         for (InstructionSequence sequence = block.FirstInstructionSequence; sequence != null; sequence = sequence.NextSiblingSequence) {
             bool commit = false;
             writer.AttachInstructionSequence(sequence);
             reader.EnterInstructionSequence(sequence);
             while (reader.ReadInstruction()) {
                 var opCode = reader.CurrentInstruction.OpCodeNumber;
                 var opCodeInfo = reader.CurrentInstruction.OpCodeInfo;
                 if ((opCodeInfo.FlowControl == FlowControl.Branch
                     || opCodeInfo.FlowControl == FlowControl.Cond_Branch)
                     && (predicate == null || predicate(reader.CurrentInstruction))) {
                     commit = true;
                     writer.EmitBranchingInstruction(opCode, branchTargetSequence);
                 } else {
                     reader.CurrentInstruction.Write(writer);
                 }
             }
             reader.LeaveInstructionSequence();
             writer.DetachInstructionSequence(commit);
         }
     }
     reader.LeaveInstructionBlock();
 }
        public void EmitFormatArguments(InstructionWriter writer, string format, int argumentsCount, Action <int, InstructionWriter> loadArgumentAction)
        {
            if (argumentsCount == 0)
            {
                throw new ArgumentOutOfRangeException("argumentsCount");
            }

            IMethod formatMethod;
            bool    createArgsArray = false;

            switch (argumentsCount)
            {
            case 1:
                formatMethod = this.format1Method;
                break;

            case 2:
                formatMethod = this.format2Method;
                break;

            case 3:
                formatMethod = this.format3Method;
                break;

            default:
                formatMethod    = this.formatArrayMethod;
                createArgsArray = true;
                break;
            }

            writer.EmitInstructionString(OpCodeNumber.Ldstr, format);

            if (createArgsArray)
            {
                writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, argumentsCount);
                writer.EmitInstructionType(OpCodeNumber.Newarr,
                                           this.module.Cache.GetIntrinsicBoxedType(IntrinsicType.Object));
            }

            for (int i = 0; i < argumentsCount; i++)
            {
                if (createArgsArray)
                {
                    writer.EmitInstruction(OpCodeNumber.Dup);
                    writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i);
                }

                if (loadArgumentAction != null)
                {
                    loadArgumentAction(i, writer);
                }

                if (createArgsArray)
                {
                    writer.EmitInstruction(OpCodeNumber.Stelem_Ref);
                }
            }

            writer.EmitInstructionMethod(OpCodeNumber.Call, formatMethod);
        }
        private static void AddHelloWorldToMethod(MethodDefDeclaration targetMethod, IMethod consoleWriteLine)
        {
            // Removes the original code from the method body. Without this, you would get exceptions:
            InstructionBlock originalCode = targetMethod.MethodBody.RootInstructionBlock;

            originalCode.Detach();

            // Replaces the method body's content:
            InstructionBlock root = targetMethod.MethodBody.CreateInstructionBlock();

            targetMethod.MethodBody.RootInstructionBlock = root;

            InstructionBlock    helloWorldBlock    = root.AddChildBlock();
            InstructionSequence helloWorldSequence = helloWorldBlock.AddInstructionSequence();

            using (var writer = InstructionWriter.GetInstance())
            {
                // Add instructions to the beginning of the method body:
                writer.AttachInstructionSequence(helloWorldSequence);

                // Say that what follows is compiler-generated code:
                writer.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);

                // Emit a call to Console.WriteLine("Hello, world!"):
                writer.EmitInstructionString(OpCodeNumber.Ldstr, "Hello, world!");
                writer.EmitInstructionMethod(OpCodeNumber.Call, consoleWriteLine);

                writer.DetachInstructionSequence();
            }

            // Re-adding the original code at the end:
            root.AddChildBlock(originalCode);
        }
示例#10
0
        private void AddCollectionLoop(LocalVariableSymbol resultVariable, InstructionWriter t,
                                       LocalVariableSymbol enumeratorVariable, LocalVariableSymbol currentVariable)
        {
            t.WhileNotZero(
                c =>
            {
                c.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, enumeratorVariable);
                c.EmitInstructionMethod(OpCodeNumber.Callvirt, MoveNext);
            },
                b =>
            {
                b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable);
                b.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber);
                b.EmitInstruction(OpCodeNumber.Mul);

                b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, enumeratorVariable);
                b.EmitInstructionMethod(OpCodeNumber.Callvirt, GetCurrent);
                b.EmitInstructionLocalVariable(OpCodeNumber.Stloc, currentVariable);

                b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, currentVariable);

                b.IfNotZero(
                    bt =>
                {
                    bt.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, currentVariable);
                    bt.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode);
                },
                    et => { et.EmitInstruction(OpCodeNumber.Ldc_I4_0); });

                b.EmitInstruction(OpCodeNumber.Xor);
                b.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable);
            });
        }
                protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer)
                {
                    int[]  argumentsIndex;
                    string messageFormatString = this.argumentsFormatter.CreateMessageArguments(this.options.OnSuccessOptions, false, out argumentsIndex);

                    this.EmitMessage(block, writer, this.options.OnSuccessLevel, "Leaving: " + messageFormatString, argumentsIndex);
                }
示例#12
0
        private void AddCustomLogicCall(TypeDefDeclaration enhancedType, InstructionWriter writer,
                                        MethodDefDeclaration customMethod)
        {
            var parameters = customMethod.Parameters;

            if (parameters.Count != 0)
            {
                Message.Write(enhancedType, SeverityType.Error, "EQU1", "The signature of a method annotated with ["
                              + nameof(AdditionalGetHashCodeMethodAttribute) +
                              "] must be 'int MethodName()'. It can't have parameters.");
                writer.EmitInstruction(OpCodeNumber.Ldc_I4_0);
                return;
            }

            if (!customMethod.ReturnParameter.ParameterType.IsIntrinsic(IntrinsicType.Int32))
            {
                Message.Write(enhancedType, SeverityType.Error, "EQU2", "The signature of a method annotated with ["
                              + nameof(AdditionalGetHashCodeMethodAttribute) +
                              "] must be 'int MethodName()'. Its return type must be 'int'.");
                writer.EmitInstruction(OpCodeNumber.Ldc_I4_0);
                return;
            }

            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            writer.EmitInstructionMethod(
                enhancedType.IsValueTypeSafe() == true ? OpCodeNumber.Call : OpCodeNumber.Callvirt,
                customMethod.GetCanonicalGenericInstance());
        }
            public void EmitGetIsEnabled(InstructionWriter writer, LogLevel logLevel)
            {
                writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.loggerField);
                LoggerMethods loggerMethods = this.parent.GetLoggerMethods(logLevel);

                writer.EmitInstructionMethod(OpCodeNumber.Callvirt, loggerMethods.IsLoggingEnabledMethod);
            }
示例#14
0
        public void Emit(InstructionWriter writer, InstructionBlock block, TypeInitializationClientScopes scope)
        {
            InstructionSequence sequence = block.AddInstructionSequence();

            writer.AttachInstructionSequence(sequence);
            writer.EmitInstructionMethod(OpCodeNumber.Call, attachMethod);
            writer.DetachInstructionSequence();
        }
示例#15
0
        private void AddFieldCode(FieldDefDeclaration field, bool isFirst, InstructionWriter writer,
                                  LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType)
        {
            bool isCollection;
            var  propType           = field.FieldType;
            bool isValueType        = propType.IsValueTypeSafe() == true;
            bool isGenericParameter = false;

            if (propType.TypeSignatureElementKind == TypeSignatureElementKind.GenericParameter ||
                propType.TypeSignatureElementKind == TypeSignatureElementKind.GenericParameterReference)
            {
                // TODO what does this mean?
                // maybe something else also needs to be checked?
                isCollection       = false;
                isGenericParameter = true;
            }
            else
            {
                isCollection = propType.IsCollection() ||
                               propType.TypeSignatureElementKind == TypeSignatureElementKind.Array;
            }

            AddMultiplicityByMagicNumber(isFirst, writer, resultVariable, isCollection);

            if (propType.GetReflectionName().StartsWith("System.Nullable"))
            {
                AddNullableProperty(field, writer);
            }
            else if (isCollection && propType.GetReflectionName() != "System.String")
            {
                AddCollectionCode(field, writer, resultVariable, method, enhancedType);
            }
            else if (isValueType || isGenericParameter)
            {
                LoadVariable(field, writer);
                if (propType.GetReflectionName() != "System.Int32")
                {
                    writer.EmitInstructionType(OpCodeNumber.Box, propType);
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode);
                }
            }
            else
            {
                LoadVariable(field, writer);
                AddNormalCode(field, writer, enhancedType);
            }

            if (!isFirst && !isCollection)
            {
                writer.EmitInstruction(OpCodeNumber.Xor);
            }

            if (!isCollection)
            {
                writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable);
            }
        }
示例#16
0
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            InstructionWriter iw = context.InstructionWriter;

            iw.AttachInstructionSequence(block.AddInstructionSequence());
            iw.EmitInstructionMethod(OpCodeNumber.Call, methodToCall);
            iw.DetachInstructionSequence();
            ReplacedAtLeastOneCall = true;
        }
        private void InjectEqualsObject(TypeDefDeclaration enhancedType, StructuralEqualityAttribute config,
                                        MethodDefDeclaration typedEqualsMethod)
        {
            var existingMethod = enhancedType.Methods.FirstOrDefault <IMethod>(declaration =>
            {
                return(declaration.Name == "Equals" &&
                       declaration.IsPublic() &&
                       !declaration.IsStatic &&
                       declaration.ParameterCount == 1 &&
                       declaration.GetParameterType(0).Equals(this.objectType));
            });

            if (existingMethod != null)
            {
                return;
            }

            // public virtual bool Equals( object other )
            var equalsDeclaration = new MethodDefDeclaration
            {
                Name              = "Equals",
                Attributes        = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                CallingConvention = CallingConvention.HasThis
            };

            enhancedType.Methods.Add(equalsDeclaration);
            equalsDeclaration.Parameters.Add(new ParameterDeclaration(0, "other", this.objectType));
            equalsDeclaration.ReturnParameter = ParameterDeclaration.CreateReturnParameter(this.booleanType);
            CompilerGeneratedAttributeHelper.AddCompilerGeneratedAttribute(equalsDeclaration);

            using (var writer = InstructionWriter.GetInstance())
            {
                var methodBody = MethodBodyCreator.CreateModifiableMethodBody(writer, equalsDeclaration);

                writer.AttachInstructionSequence(methodBody.PrincipalBlock.AddInstructionSequence());

                writer.EmitInstruction(OpCodeNumber.Ldc_I4_0);
                writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable);

                this.InjectReferenceEquals(writer, methodBody, enhancedType);

                var genericTypeInstance = enhancedType.GetCanonicalGenericInstance();

                this.EmitTypeCheck(enhancedType, config, writer, genericTypeInstance, methodBody);
                if (enhancedType.IsValueTypeSafe() == true)
                {
                    this.EmitEqualsObjectOfValueType(writer, genericTypeInstance, typedEqualsMethod, methodBody);
                }
                else
                {
                    this.EmitEqualsObjectOfReferenceType(writer, genericTypeInstance, typedEqualsMethod, methodBody);
                }

                writer.DetachInstructionSequence();
            }
        }
示例#18
0
 private void AddNormalCode(FieldDefDeclaration field, InstructionWriter writer, TypeDefDeclaration enhancedType)
 {
     writer.IfNotZero(
         thenw =>
     {
         LoadVariable(field, thenw);
         thenw.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode);
     },
         elsew => { elsew.EmitInstruction(OpCodeNumber.Ldc_I4_0); });
 }
示例#19
0
 private void AddMultiplicityByMagicNumber(bool isFirst, InstructionWriter writer,
                                           LocalVariableSymbol resultVariable, bool isCollection)
 {
     if (!isFirst && !isCollection)
     {
         writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable);
         writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber);
         writer.EmitInstruction(OpCodeNumber.Mul);
     }
 }
        private void InjectExactlyOfType(InstructionWriter writer, ITypeSignature genericTypeInstance)
        {
            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            writer.EmitInstructionMethod(OpCodeNumber.Call, this.getTypeMethod);

            writer.EmitInstructionType(OpCodeNumber.Ldtoken, genericTypeInstance);
            writer.EmitInstructionMethod(OpCodeNumber.Call, this.getTypeFromHandleMethod);

            writer.EmitInstruction(OpCodeNumber.Ceq);
        }
示例#21
0
        void AddGetEnumerator(InstructionWriter ins, LocalVariableSymbol variable, FieldDefDeclaration field)
        {
            if (field.FieldType.IsValueTypeSafe() == true)
            {
                ins.EmitInstructionType(OpCodeNumber.Box, field.FieldType);
            }

            ins.EmitInstructionMethod(OpCodeNumber.Callvirt, GetEnumerator);
            ins.EmitInstructionLocalVariable(OpCodeNumber.Stloc, variable);
        }
 protected override void ImplementOnEntry(InstructionBlock block, InstructionWriter writer)
 {
     foreach (var implementation in GetOnEntryImplementations()) {
         using (var factory = implementation.CreateExport()) {
             var instance = factory.Value;
             instance.Initialize(Context);
             instance.ImplementOnEntry(block, writer);
         }
     }
 }
        public void EmitFormatArguments(InstructionWriter writer, string format, int argumentsCount, Action<int, InstructionWriter> loadArgumentAction)
        {
            if (argumentsCount == 0) throw new ArgumentOutOfRangeException("argumentsCount");

            IMethod formatMethod;
            bool createArgsArray = false;

            switch (argumentsCount)
            {
                case 1:
                    formatMethod = this.format1Method;
                    break;
                case 2:
                    formatMethod = this.format2Method;
                    break;
                case 3:
                    formatMethod = this.format3Method;
                    break;
                default:
                    formatMethod = this.formatArrayMethod;
                    createArgsArray = true;
                    break;
            }

            writer.EmitInstructionString(OpCodeNumber.Ldstr, format);

            if (createArgsArray)
            {
                writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, argumentsCount);
                writer.EmitInstructionType(OpCodeNumber.Newarr,
                                           this.module.Cache.GetIntrinsicBoxedType(IntrinsicType.Object));
            }

            for (int i = 0; i < argumentsCount; i++)
            {
                if (createArgsArray)
                {
                    writer.EmitInstruction(OpCodeNumber.Dup);
                    writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i);
                }

                if (loadArgumentAction != null)
                {
                    loadArgumentAction(i, writer);
                }

                if (createArgsArray)
                {
                    writer.EmitInstruction(OpCodeNumber.Stelem_Ref);
                }
            }

            writer.EmitInstructionMethod(OpCodeNumber.Call, formatMethod);
        }
        private void EmitEqualsField(InstructionWriter writer, CreatedEmptyMethod methodBody,
                                     FieldDefDeclaration field)
        {
            ITypeSignature fieldType = field.FieldType;

            if ((fieldType.GetNakedType() is IntrinsicTypeSignature sig &&
                 sig.IntrinsicType != IntrinsicType.Object &&
                 sig.IntrinsicType != IntrinsicType.String
                 ) || fieldType.IsEnum())
            {
                this.EmitSimpleValueCheck(writer, methodBody, field);
            }
        private void EmitEqualsObjectOfReferenceType(InstructionWriter writer, IType genericTypeInstance,
                                                     MethodDefDeclaration typedEqualsMethod, CreatedEmptyMethod methodBody)
        {
            // Go to typed check.
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            writer.EmitInstructionType(OpCodeNumber.Castclass, genericTypeInstance);
            writer.EmitInstructionMethod(OpCodeNumber.Call, typedEqualsMethod.GetCanonicalGenericInstance());

            writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable);
            writer.EmitBranchingInstruction(OpCodeNumber.Br, methodBody.ReturnSequence);
        }
        private void EmitEqualsObjectOfValueType(InstructionWriter writer,
                                                 IType genericTypeInstance, MethodDefDeclaration typedEqualsMethod, CreatedEmptyMethod methodBody)
        {
            // return this.Equals((Typed)other);
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            writer.EmitInstructionType(OpCodeNumber.Unbox_Any, genericTypeInstance);
            writer.EmitInstructionMethod(OpCodeNumber.Call, typedEqualsMethod.GetCanonicalGenericInstance());

            writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable);
            writer.EmitBranchingInstruction(OpCodeNumber.Br, methodBody.ReturnSequence);
        }
                protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer)
                {
                    MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration;

                    if (targetMethod == null)
                    {
                        return;
                    }

                    string messageFormatString = this.CreateMessageFormatString(this.onSuccessOptions, targetMethod);

                    this.EmitMessage(block, writer, targetMethod, "Leaving: " + messageFormatString);
                }
        public static void AddPropertyGuard(PropertyDeclaration property, MethodBodyTransformationContext context, InstructionBlock block, InstructionWriter writer)
        {
            var propertyType = property.PropertyType;
            var methodBody = block.MethodBody;

            var sequence = block.AddInstructionSequence(null, NodePosition.After, null);
            if (sequence == null) return;

            var oldValueVariable =
                block.DefineLocalVariable(propertyType, string.Format("old{0}Value", property.Name));
            var assets = GetTransformationAssets(property.Module);

            writer.AttachInstructionSequence(sequence);
            var isLocationBinding = CheckIfIsLocationBinding(methodBody,assets);
            if (isLocationBinding) {
                writer.AssignValue_LocalVariable(oldValueVariable
                    , () => writer.Call_MethodOnTarget(property.GetGetter()
                        ,
                        () => {
                            //Load the instance parameter of the SetValue method
                            //and convert it to the type
                            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                            //writer.EmitInstructionLoadIndirect(Assets.ObjectTypeSignature);
                            writer.EmitInstructionType(OpCodeNumber.Ldobj, assets.ObjectTypeSignature);
                            writer.EmitConvertFromObject(property.Parent);
                        }
                    )
                );
                //On the location binding the value parameter is at psotion 3
                writer.EmitInstruction(OpCodeNumber.Ldarg_3);
            } else {
                writer.AssignValue_LocalVariable(oldValueVariable,
                                                    () => writer.Get_PropertyValue(property));
                //For a normal property the value parameter is at position 1
                writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            }
            if (propertyType.IsStruct()) {
                writer.EmitInstructionType(OpCodeNumber.Box, propertyType);
            }
            writer.Box_LocalVariableIfNeeded(oldValueVariable);
            var isPrimitive = propertyType.IsPrimitive();
            if (isPrimitive) {
                writer.Compare_Primitives();
            } else {
                //TODO: Try and use the equality operator when present
                writer.Compare_Objects(assets.ObjectEqualsMethod);
            }
            //writer.Leave_IfTrue(_context.LeaveBranchTarget);
            writer.Leave_IfTrue(context.LeaveBranchTarget);
            writer.DetachInstructionSequence();
        }
示例#29
0
            public void EmitWrite(InstructionWriter writer, InstructionBlock block, string messageFormattingString,
                                  int argumentsCount, LogSeverity logSeverity, Action <InstructionWriter> getExceptionAction,
                                  Action <int, InstructionWriter> loadArgumentAction)
            {
                IMethod method;

                switch (logSeverity)
                {
                case LogSeverity.Trace:
                    method = this.parent.writeDebugMethod;
                    break;

                case LogSeverity.Info:
                    method = this.parent.writeInfoMethod;
                    break;

                case LogSeverity.Warning:
                    method = this.parent.writeWarnMethod;
                    break;

                case LogSeverity.Error:
                    method = this.parent.writeErrorMethod;
                    break;

                case LogSeverity.Fatal:
                    method = this.parent.writeFatalMethod;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("logSeverity");
                }

                if (getExceptionAction != null)
                {
                    getExceptionAction(writer);
                }

                writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.loggerField);

                if (argumentsCount > 0)
                {
                    this.parent.formatWriter.EmitFormatArguments(writer, messageFormattingString, argumentsCount, loadArgumentAction);
                }
                else
                {
                    writer.EmitInstructionString(OpCodeNumber.Ldstr, messageFormattingString);
                }

                writer.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
            }
示例#30
0
 private void AddCollectionCode(FieldDefDeclaration field, InstructionWriter writer,
                                LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType)
 {
     if (field.FieldType.IsValueTypeSafe() == true)
     {
         AddCollectionCodeInternal(field, resultVariable, method, enhancedType, writer);
     }
     else
     {
         LoadVariable(field, writer);
         writer.IfNotZero(
             thenw => { AddCollectionCodeInternal(field, resultVariable, method, enhancedType, thenw); },
             elsew => { });
     }
 }
        private void InjectExactlyTheSameTypeAsThis(InstructionWriter writer, ITypeSignature enhancedType, ITypeSignature genericTypeInstance)
        {
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            if (enhancedType.IsValueTypeSafe() == true)
            {
                writer.EmitInstructionType(OpCodeNumber.Ldobj, genericTypeInstance);
                writer.EmitInstructionType(OpCodeNumber.Box, genericTypeInstance);
            }

            writer.EmitInstructionMethod(OpCodeNumber.Call, this.getTypeMethod);

            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.getTypeMethod);

            writer.EmitInstruction(OpCodeNumber.Ceq);
        }
示例#32
0
        private static InstructionSequence EmitLevelTest(WeavingContext context, InstructionWriter writer, string logLevel)
        {
            var loggerField = GetLoggerField(context, true);
            writer.EmitInstructionField(OpCodeNumber.Ldsfld, loggerField);

            // If level is enabled
            var systemIsLevelEnabled = typeof(ILog).GetProperty("Is" + logLevel + "Enabled").GetGetMethod();
            var isLevelEnabled = context.Method.Module.FindMethod(systemIsLevelEnabled, BindingOptions.Default);
            writer.EmitInstructionMethod(OpCodeNumber.Callvirt, isLevelEnabled);

            var branchTarget = context.Method.MethodBody.CreateInstructionSequence();
            writer.CurrentInstructionSequence.ParentInstructionBlock.AddInstructionSequence(branchTarget, NodePosition.After, writer.CurrentInstructionSequence);

            writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, branchTarget);
            return branchTarget;
        }
            public void EmitWrite(InstructionWriter writer, string messageFormattingString, int argumentsCount, LogLevel logLevel,
                                  Action <InstructionWriter> getExceptionAction, Action <int, InstructionWriter> loadArgumentAction, bool useWrapper)
            {
                bool    createArgsArray;
                IMethod method = this.GetLoggerMethod(logLevel, argumentsCount, out createArgsArray);

                if (getExceptionAction != null)
                {
                    getExceptionAction(writer);
                }

                writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.loggerField);
                writer.EmitInstructionString(OpCodeNumber.Ldstr, messageFormattingString);

                if (createArgsArray)
                {
                    writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, argumentsCount);
                    writer.EmitInstructionType(OpCodeNumber.Newarr,
                                               this.parent.module.Cache.GetIntrinsicBoxedType(IntrinsicType.Object));
                }

                for (int i = 0; i < argumentsCount; i++)
                {
                    if (createArgsArray)
                    {
                        writer.EmitInstruction(OpCodeNumber.Dup);
                        writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i);
                    }

                    if (loadArgumentAction != null)
                    {
                        loadArgumentAction(i, writer);
                    }

                    if (createArgsArray)
                    {
                        writer.EmitInstruction(OpCodeNumber.Stelem_Ref);
                    }
                }

                if (useWrapper)
                {
                    method = this.parent.loggingImplementation.GetWriteWrapperMethod(method);
                }

                writer.EmitInstructionMethod(method.IsVirtual ? OpCodeNumber.Callvirt : OpCodeNumber.Call, method);
            }
示例#34
0
        private void ReplaceOperator(TypeDefDeclaration enhancedType, MethodDefDeclaration equalityMethodDef,
                                     bool negate)
        {
            InstructionBlock originalCode = equalityMethodDef.MethodBody.RootInstructionBlock;

            originalCode.Detach();

            InstructionBlock root = equalityMethodDef.MethodBody.CreateInstructionBlock();

            equalityMethodDef.MethodBody.RootInstructionBlock = root;
            var newSequence = root.AddInstructionSequence();

            using (var writer = InstructionWriter.GetInstance())
            {
                writer.AttachInstructionSequence(newSequence);

                if (enhancedType.IsValueType())
                {
                    var canonicalType = enhancedType.GetCanonicalGenericInstance();
                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstructionType(OpCodeNumber.Box, canonicalType);
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                    writer.EmitInstructionType(OpCodeNumber.Box, canonicalType);
                }
                else
                {
                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                }

                writer.EmitInstructionMethod(OpCodeNumber.Call, this.staticEqualsMethod);

                if (negate)
                {
                    writer.EmitInstruction(OpCodeNumber.Ldc_I4_0);
                    writer.EmitInstruction(OpCodeNumber.Ceq);
                }

                writer.EmitInstruction(OpCodeNumber.Ret);

                writer.DetachInstructionSequence();
            }
        }
示例#35
0
        /// <summary>
        /// Emits:
        /// <code>
        ///   brfalse elseBranch;
        ///   thenStatement();
        ///   br end;
        /// elseBranch:
        ///   elseStatement();
        /// end:
        /// </code>
        /// </summary>
        public static void IfNotZero(this InstructionWriter writer,
                                     Action <InstructionWriter> thenStatement,
                                     Action <InstructionWriter> elseStatement)
        {
            InstructionSequence elseSequence =
                writer.CurrentInstructionSequence.ParentInstructionBlock.AddInstructionSequence();
            InstructionSequence endSequence =
                writer.CurrentInstructionSequence.ParentInstructionBlock.AddInstructionSequence();

            writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, elseSequence);

            thenStatement(writer);
            writer.EmitBranchingInstruction(OpCodeNumber.Br, endSequence);
            writer.DetachInstructionSequence();
            writer.AttachInstructionSequence(elseSequence);
            elseStatement(writer);
            writer.EmitBranchingInstruction(OpCodeNumber.Br, endSequence);
            writer.DetachInstructionSequence();
            writer.AttachInstructionSequence(endSequence);
        }
示例#36
0
        protected override void Weave(WeavingContext context, InstructionWriter writer)
        {
            switch(context.JoinPoint.JoinPointKind)
            {
                case JoinPointKinds.BeforeMethodBody:
                    WeaveBeforeMethodBody(context, writer);
                    break;

                case JoinPointKinds.AfterMethodBodySuccess:
                    WeaveAfterMethodBodySuccess(context, writer);
                    break;

                case JoinPointKinds.AfterMethodBodyException:
                    WeaveAfterMethodBodyException(context, writer);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("context");
            }
        }
示例#37
0
        private void AddNullableProperty(FieldDefDeclaration field, InstructionWriter writer)
        {
            IMethodSignature getHasValue = new MethodSignature(field.Module, CallingConvention.HasThis,
                                                               field.Module.Cache.GetIntrinsic(IntrinsicType.Boolean), new List <ITypeSignature>(), 0);
            var hasValueMethod = field.FieldType.FindMethod("get_HasValue", getHasValue);

            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            writer.EmitInstructionField(OpCodeNumber.Ldflda, field.GetCanonicalGenericInstance());
            writer.EmitInstructionMethod(OpCodeNumber.Call,
                                         hasValueMethod.GetInstance(field.Module, hasValueMethod.GenericMap));

            writer.IfNotZero((then) =>
            {
                writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                writer.EmitInstructionField(OpCodeNumber.Ldfld, field.GetCanonicalGenericInstance());
                writer.EmitInstructionType(OpCodeNumber.Box, field.FieldType);
                writer.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode);
            },
                             (elseBranch) => { writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); });
        }
        protected override void Weave(WeavingContext context, InstructionWriter writer)
        {
            ITypeSignature declaringType = context.Method.DeclaringType;
            if (declaringType.IsGenericDefinition)
            {
                var canonicalType = GenericHelper.GetTypeCanonicalGenericInstance(declaringType.GetTypeDefinition(BindingOptions.RequireGenericDefinition));
                var genericContext = canonicalType.GetGenericContext(GenericContextOptions.ResolveGenericParameterDefinitions);
                declaringType = canonicalType.MapGenericArguments(genericContext);
            }
            writer.EmitInstructionType(OpCodeNumber.Ldtoken, declaringType);

            var typeGetType = typeof(Type).GetMethod("GetTypeFromHandle");
            writer.EmitInstructionMethod(OpCodeNumber.Call, context.Method.Module.FindMethod(typeGetType, BindingOptions.Default));

            var getLogger = context.Method.Module.FindMethod(typeof(LogManager).GetMethod("GetLogger", new[] { typeof(Type) }), BindingOptions.Default);
            writer.EmitInstructionMethod(OpCodeNumber.Call, getLogger);

            var loggerField = GetLoggerField(context, false);
            writer.EmitInstructionField(OpCodeNumber.Stsfld, loggerField);
        }
            public void EmitWrite(InstructionWriter writer, string messageFormattingString, int argumentsCount, LogLevel logLevel, Action<InstructionWriter> getExceptionAction, Action<int, InstructionWriter> loadArgumentAction, bool useWrapper)
            {
                bool createArgsArray;
                IMethod method = this.GetLoggerMethod(logLevel, argumentsCount, out createArgsArray);

                if (getExceptionAction != null)
                {
                    getExceptionAction(writer);
                }

                writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.loggerField);
                writer.EmitInstructionString(OpCodeNumber.Ldstr, messageFormattingString);

                if (createArgsArray)
                {
                    writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, argumentsCount);
                    writer.EmitInstructionType(OpCodeNumber.Newarr,
                                               this.parent.module.Cache.GetIntrinsicBoxedType(IntrinsicType.Object));
                }

                for (int i = 0; i < argumentsCount; i++)
                {
                    if (createArgsArray)
                    {
                        writer.EmitInstruction(OpCodeNumber.Dup);
                        writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i);
                    }

                    if (loadArgumentAction != null)
                    {
                        loadArgumentAction(i, writer);
                    }

                    if (createArgsArray)
                    {
                        writer.EmitInstruction(OpCodeNumber.Stelem_Ref);
                    }
                }

                if (useWrapper)
                {
                    method = this.parent.loggingImplementation.GetWriteWrapperMethod(method);
                }

                writer.EmitInstructionMethod(method.IsVirtual ? OpCodeNumber.Callvirt : OpCodeNumber.Call, method);
            }
 public void EmitGetIsEnabled(InstructionWriter writer, LogLevel logLevel)
 {
     writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.loggerField);
     LoggerMethods loggerMethods = this.parent.GetLoggerMethods(logLevel);
     writer.EmitInstructionMethod(OpCodeNumber.Callvirt, loggerMethods.IsLoggingEnabledMethod);
 }
 private void RaisePropertyChangingEvent(InstructionBlock block, InstructionWriter writer)
 {
     var invokerMethod = FindOnPropertyChangingWithStringParameter();
     CallEventInvokerMethod(invokerMethod, block,writer);
 }
                private void EmitMessage(InstructionBlock block, InstructionWriter writer, MethodDefDeclaration targetMethod, string messageFormatString)
                {
                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);

                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);
                    writer.AttachInstructionSequence(sequence);

                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, LogSeverity.Trace);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    int parameterCount = Context.MethodMapping.MethodSignature.ParameterCount;
                    bool hasThis = Context.MethodMapping.MethodSignature.CallingConvention == CallingConvention.HasThis;

                    builder.EmitWrite(writer, block, messageFormatString, parameterCount, LogSeverity.Trace, null,
                                      (i, instructionWriter) =>
                                      {
                                          instructionWriter.EmitInstructionInt16(OpCodeNumber.Ldarg, (short)(hasThis ? i + 1 : i));
                                          instructionWriter.EmitConvertToObject(
                                              this.Context.MethodMapping.MethodSignature.GetParameterType(i));
                                      });

                    writer.DetachInstructionSequence();
                }
        public static void ImplementRemoveOn(
            this EventDeclaration theEvent,
            TypeDefDeclaration type,
            IField field,
            WeavingHelper weavingHelper = null,
            MethodAttributes methodAttributes =
                MethodAttributes.Public | MethodAttributes.HideBySig
                | MethodAttributes.Virtual | MethodAttributes.Final 
                | MethodAttributes.NewSlot | MethodAttributes.SpecialName)
        {
            var module = type.Module;
            weavingHelper = weavingHelper ?? new WeavingHelper(module);
            var pEWeavingHelper = module.Cache.GetItem(() => new PostEdgeWeaverAssets(module));

            var method = new MethodDefDeclaration {
                Attributes = methodAttributes,
                Name = "remove_" + theEvent.Name,
                CallingConvention = CallingConvention.HasThis
            };
            type.Methods.Add(method);
            weavingHelper.AddCompilerGeneratedAttribute(method.CustomAttributes);
            var parameter = new ParameterDeclaration {
                Name = "value",
                ParameterType = theEvent.EventType,
            };
            method.Parameters.Add(parameter);

            var methodBody = new MethodBodyDeclaration();
            methodBody.EnsureWritableLocalVariables();
            var instructionBlock = methodBody.CreateInstructionBlock();
            var initSequence = methodBody.CreateInstructionSequence();
            var loopSequence = methodBody.CreateInstructionSequence();
            var endSequence = methodBody.CreateInstructionSequence();
            instructionBlock.AddInstructionSequence(initSequence, NodePosition.After, null);
            instructionBlock.AddInstructionSequence(loopSequence, NodePosition.After, initSequence);
            instructionBlock.AddInstructionSequence(endSequence, NodePosition.After, loopSequence);
            methodBody.RootInstructionBlock = instructionBlock;
            method.MethodBody = methodBody;
            methodBody.CreateLocalVariable(theEvent.EventType);
            methodBody.CreateLocalVariable(theEvent.EventType);
            methodBody.CreateLocalVariable(theEvent.EventType);
            methodBody.CreateLocalVariable(module.Cache.GetIntrinsic(typeof(bool)));

            var writer = new InstructionWriter();
            //Initialize
            writer.AttachInstructionSequence(initSequence);

            //PropertyChangedHandler handler = this.PropertyChanged
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);           //Get the this pointer
            writer.EmitInstructionField(OpCodeNumber.Ldfld, field); //Get the event's field
            writer.EmitInstruction(OpCodeNumber.Stloc_0);           //store into the first local variable
            writer.DetachInstructionSequence();

            //Loop
            //do {
            writer.AttachInstructionSequence(loopSequence);

            //PropertyChangedHandler handler2 = handler;
            writer.EmitInstruction(OpCodeNumber.Ldloc_0);
            writer.EmitInstruction(OpCodeNumber.Stloc_1);

            //PropertyChangedHandler handler3 = System.Delegate.Remove(handler2, value)
            writer.EmitInstruction(OpCodeNumber.Ldloc_1);
            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            writer.EmitInstructionMethod(OpCodeNumber.Call, pEWeavingHelper.DelegateRemoveMethod);
            writer.EmitInstructionType(OpCodeNumber.Castclass, theEvent.EventType);
            writer.EmitInstruction(OpCodeNumber.Stloc_2);

            //handler = System.Threading.Interlocked.CompareExchnage<PropertyChangedEventHandler>(ref this.PropertyChtyChanged, handler3, handler2);
            var compareExchangeMethodT = pEWeavingHelper.CompareExchangeMethod;
            var compareExchangeMethod = compareExchangeMethodT.GetGenericInstance(module, theEvent.EventType);
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);           //Load this
            writer.EmitInstructionField(OpCodeNumber.Ldflda, field);
            writer.EmitInstruction(OpCodeNumber.Ldloc_2);
            writer.EmitInstruction(OpCodeNumber.Ldloc_1);
            writer.EmitInstructionMethod(OpCodeNumber.Call, compareExchangeMethod);
            writer.EmitInstruction(OpCodeNumber.Stloc_0);

            //flag = handler != handler2;
            writer.EmitInstruction(OpCodeNumber.Ldloc_0);
            writer.EmitInstruction(OpCodeNumber.Ldloc_1);
            writer.EmitInstruction(OpCodeNumber.Ceq);
            writer.EmitInstruction(OpCodeNumber.Ldc_I4_0);
            writer.EmitInstruction(OpCodeNumber.Ceq);
            writer.EmitInstruction(OpCodeNumber.Stloc_3);

            //} while (flag);
            writer.EmitInstruction(OpCodeNumber.Ldloc_3);
            writer.EmitBranchingInstruction(OpCodeNumber.Brtrue_S, loopSequence);

            writer.DetachInstructionSequence();

            //End
            writer.AttachInstructionSequence(endSequence);
            writer.EmitInstruction(OpCodeNumber.Ret);               //Exit the method
            writer.DetachInstructionSequence();

            theEvent.Members.Add(new MethodSemanticDeclaration(MethodSemantics.RemoveOn, method));
        }
 protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer)
 {
     RaisePropertyChangedEvent(block, writer);
 }
 protected override void ImplementOnExit(InstructionBlock block, InstructionWriter writer)
 {
 }
 protected override void ImplementOnEntry(InstructionBlock block, InstructionWriter writer)
 {
     //TODO: Move the equality guard creation code to here... we can then greatly refactor the code
     AddGuard(block, writer);
     RaisePropertyChangingEvent(block,writer);
 }
 protected override void ImplementOnException(InstructionBlock block, ITypeSignature exceptionType, InstructionWriter writer)
 {
 }
                private void EmitMessage(InstructionBlock block, InstructionWriter writer, LogLevel logLevel, string messageFormatString, int[] arguments)
                {
                    MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration;
                    if (targetMethod == null)
                    {
                        return;
                    }

                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);

                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);
                    writer.AttachInstructionSequence(sequence);

                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, logLevel);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    bool useWrapper = ShouldUseWrapper(targetMethod);

                    builder.EmitWrite(writer, messageFormatString, arguments.Length, logLevel, null, (i, instructionWriter) =>
                    {
                        int index = arguments[i];
                        if (index == MessageArgumentsFormatter.ThisArgumentPosition)
                        {
                            this.methodMappingWriter.EmitLoadInstance(false, instructionWriter);
                        }
                        else if (index == MessageArgumentsFormatter.ReturnParameterPosition)
                        {
                            instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, Context.ReturnValueVariable);
                            instructionWriter.EmitConvertToObject(Context.MethodMapping.MethodSignature.ReturnType);
                        }
                        else
                        {
                            this.methodMappingWriter.EmitLoadArgument(index, instructionWriter);

                            instructionWriter.EmitConvertToObject(this.methodMappingWriter.MethodMapping.MethodSignature.GetParameterType(index));
                        }
                    }, useWrapper);

                    writer.DetachInstructionSequence();
                }
            public void EmitWrite(InstructionWriter writer, string messageFormattingString, int argumentsCount, LogLevel logLevel, 
                Action<InstructionWriter> getExceptionAction, Action<int, InstructionWriter> loadArgumentAction, bool useWrapper)
            {
                bool createArgsArray = argumentsCount > 0;

                IMethod method;

                switch (logLevel)
                {
                    case LogLevel.Debug:
                        method = createArgsArray
                                     ? this.parent.loggingImplementation.GetTraceStringFormatMethod()
                                     : this.parent.writeLineString;
                        break;
                    case LogLevel.Info:
                        method = createArgsArray ? this.parent.traceInfoFormat : this.parent.traceInfoString;
                        break;
                    case LogLevel.Warning:
                        method = createArgsArray ? this.parent.traceWarningFormat : this.parent.traceWarningString;
                        break;
                    case LogLevel.Error:
                    case LogLevel.Fatal:
                        method = createArgsArray ? this.parent.traceErrorFormat : this.parent.traceErrorString;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException("logLevel");
                }

                if (getExceptionAction != null)
                {
                    getExceptionAction(writer);
                }
                writer.EmitInstructionString(OpCodeNumber.Ldstr, messageFormattingString);

                if (createArgsArray)
                {
                    writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, argumentsCount);
                    writer.EmitInstructionType(OpCodeNumber.Newarr,
                                               this.parent.module.Cache.GetIntrinsicBoxedType(IntrinsicType.Object));
                }

                for (int i = 0; i < argumentsCount; i++)
                {
                    if (createArgsArray)
                    {
                        writer.EmitInstruction(OpCodeNumber.Dup);
                        writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i);
                    }

                    if (loadArgumentAction != null)
                    {
                        loadArgumentAction(i, writer);
                    }

                    if (createArgsArray)
                    {
                        writer.EmitInstruction(OpCodeNumber.Stelem_Ref);
                    }
                }

                if (useWrapper)
                {
                    method = this.parent.loggingImplementation.GetWriteWrapperMethod(method);
                }

                writer.EmitInstructionMethod(OpCodeNumber.Call, method);
            }
 public void EmitGetIsEnabled(InstructionWriter writer, LogLevel logLevel)
 {
 }
        /// <summary>
        /// Emits the MSIL that calls the logging method with the specified format provider, message and arguments.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="log">Field that stores reference to the logger.</param>
        /// <param name="method">Logging method to use. The method must return no value and must take 3 arguments of types <see cref="IFormatProvider"/>, <see cref="string"/> and <see cref="Array"/> of <see cref="object"/>s.</param>
        /// <param name="formatProviderGetter">Getter of the property that returns the <see cref="IFormatProvider"/> instance.</param>
        /// <param name="formatString">Format string for the log.</param>
        /// <param name="args">Variable storing reference to array of arguments for placeholders used in the format string.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="formatProviderGetter"/>, <paramref name="formatString"/> or <paramref name="args"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLogProviderStringArgs(InstructionWriter emitter, FieldDefDeclaration log, IMethod method, IMethod formatProviderGetter, string formatString, LocalVariableSymbol args)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (log == null)
              {
            throw new ArgumentNullException("log");
              }
              if (method == null)
              {
            throw new ArgumentNullException("method");
              }
              if (formatProviderGetter == null)
              {
            throw new ArgumentNullException("formatProviderGetter");
              }
              if (args == null)
              {
            throw new ArgumentNullException("args");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(log));
              emitter.EmitInstructionMethod(OpCodeNumber.Call, formatProviderGetter);
              emitter.EmitInstructionString(OpCodeNumber.Ldstr, formatString);
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, args);
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
        }
 private void AddGuard(InstructionBlock block, InstructionWriter writer)
 {
     CommonWeavings.AddPropertyGuard(Property, Context, block, writer);
 }
                protected override void ImplementOnException(InstructionBlock block, ITypeSignature exceptionType, InstructionWriter writer)
                {
                    MethodDefDeclaration targetMethod = this.transformationInstance.AspectWeaverInstance.TargetElement as MethodDefDeclaration;
                    if (targetMethod == null)
                    {
                        return;
                    }

                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);
                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);
                    writer.AttachInstructionSequence(sequence);

                    LocalVariableSymbol exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable(
                        exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex"));

                    LogSeverity logSeverity = LogSeverity.Warning;
                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, logSeverity);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    builder.EmitWrite(writer, block, "An exception occurred:\n{0}", 1, logSeverity,
                                      w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal),
                                      (i, w) => w.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal));

                    writer.EmitInstruction(OpCodeNumber.Rethrow);
                    writer.DetachInstructionSequence();
                }
                protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer)
                {
                    int[] argumentsIndex;
                    string messageFormatString = this.argumentsFormatter.CreateMessageArguments(this.options.OnSuccessOptions, out argumentsIndex);

                    this.EmitMessage(block, writer, this.options.OnSuccessLevel, "Leaving: " + messageFormatString, argumentsIndex);
                }
                protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer)
                {
                    MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration;
                    if (targetMethod == null)
                    {
                        return;
                    }

                    string messageFormatString = this.CreateMessageFormatString(this.onSuccessOptions, targetMethod);

                    this.EmitMessage(block, writer, targetMethod, "Leaving: " + messageFormatString);
                }
        private void CallEventInvokerMethod(IMethod method, InstructionBlock block, InstructionWriter writer)
        {
            if (method == null) return;
            if (block.MethodBody.ContainsCallToMethod(method)) return;

            var sequence = block.AddInstructionSequence(null, NodePosition.After, null);
            writer.AttachInstructionSequence(sequence);
            //writer.EmitInstructionString();
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            writer.EmitInstructionString(OpCodeNumber.Ldstr, _transformationContext.Property.Name);
            //writer.EmitInstructionLocalVariable();
            if (method.IsVirtual) {
                writer.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
            } else {
                writer.EmitInstructionMethod(OpCodeNumber.Call, method);
            }
            writer.DetachInstructionSequence();
        }
        /// <summary>
        /// Emits the MSIL code that jumps to the specified label if logging is disabled.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="logLevelSupportItem">Item for the logging level.</param>
        /// <param name="perTypeLoggingData">Data for the type being woven.</param>
        /// <param name="afterLoggingSequence">Sequence to jump to if logging is disabled.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="logLevelSupportItem"/>, <paramref name="perTypeLoggingData"/> or <paramref name="afterLoggingSequence"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLoggingEnabledCheck(InstructionWriter emitter, LogLevelSupportItem logLevelSupportItem, PerTypeLoggingData perTypeLoggingData, InstructionSequence afterLoggingSequence)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (logLevelSupportItem == null)
              {
            throw new ArgumentNullException("logLevelSupportItem");
              }
              if (perTypeLoggingData == null)
              {
            throw new ArgumentNullException("perTypeLoggingData");
              }
              if (afterLoggingSequence == null)
              {
            throw new ArgumentNullException("afterLoggingSequence");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(perTypeLoggingData.Log));
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, logLevelSupportItem.IsLoggingEnabledGetter);
              emitter.EmitInstruction(OpCodeNumber.Ldc_I4_0);
              emitter.EmitInstruction(OpCodeNumber.Ceq);
              emitter.EmitBranchingInstruction(OpCodeNumber.Brtrue_S, afterLoggingSequence);
        }
        private static void ImplementSetter(
            PropertyDeclaration property,
            TypeDefDeclaration type,
            IField field,
            MethodAttributes methodAttributes,
            CustomAttributeDeclaration compilerGenerated)
        {
            // Implement setter
            var setter = new MethodDefDeclaration
            {
                Attributes = methodAttributes,
                Name = "set_" + property.Name,
                CallingConvention = CallingConvention.HasThis,
            };
            type.Methods.Add(setter);

            MarkCompilerGenerated(setter, compilerGenerated);
            setter.ReturnParameter = new ParameterDeclaration
            {
                ParameterType = type.Module.Cache.GetIntrinsic(IntrinsicType.Void),
                Attributes = ParameterAttributes.Retval
            };
            setter.Parameters.Add(new ParameterDeclaration(0, "value", property.PropertyType));

            var methodBody = new MethodBodyDeclaration();
            var sequence = methodBody.CreateInstructionSequence();
            var instructionBlock = methodBody.CreateInstructionBlock();
            instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null);
            methodBody.RootInstructionBlock = instructionBlock;
            setter.MethodBody = methodBody;

            var writer = new InstructionWriter();
            writer.AttachInstructionSequence(sequence);
            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            writer.EmitInstructionField(OpCodeNumber.Stfld, field);
            writer.EmitInstruction(OpCodeNumber.Ret);
            writer.DetachInstructionSequence();

            property.Members.Add(new MethodSemanticDeclaration(MethodSemantics.Setter, setter));
        }
        /// <summary>
        /// Emits the MSIL that calls the logging method with the specified message and exception.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="log">Field that stores reference to the logger.</param>
        /// <param name="method">Logging method to use. The method must return no value and must take 2 parameters of types <see cref="string"/> and <see cref="Exception"/>.</param>
        /// <param name="message">Message to log.</param>
        /// <param name="exception">Local variable where reference to the exception is stored.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="method"/>, <paramref name="message"/> or <paramref name="exception"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLogStringException(InstructionWriter emitter, FieldDefDeclaration log, IMethod method, string message, LocalVariableSymbol exception)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (log == null)
              {
            throw new ArgumentNullException("log");
              }
              if (method == null)
              {
            throw new ArgumentNullException("method");
              }
              if (message == null)
              {
            throw new ArgumentNullException("message");
              }
              if (exception == null)
              {
            throw new ArgumentNullException("exception");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(log));
              emitter.EmitInstructionString(OpCodeNumber.Ldstr, message);
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc_S, exception);
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
        }
            public override void Implement(TransformationContext context)
            {
                
                ModuleDeclaration module = this.AspectWeaver.Module;

                TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement;

                // Declare the method.
                MethodDefDeclaration methodDef = new MethodDefDeclaration
                {
                    Name = "AutoGeneratedValidate",
                    Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual),
                    CallingConvention = CallingConvention.HasThis
                };
                typeDef.Methods.Add(methodDef);
                methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute());

                // Define parameter.
                methodDef.ReturnParameter = new ParameterDeclaration
                {
                    ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void),
                    Attributes = ParameterAttributes.Retval
                };

                // Define the body
                MethodBodyDeclaration methodBody = new MethodBodyDeclaration();
                methodDef.MethodBody = methodBody;
                InstructionBlock instructionBlock = methodBody.CreateInstructionBlock();
                methodBody.RootInstructionBlock = instructionBlock;
                InstructionSequence sequence = methodBody.CreateInstructionSequence();
                instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null);

                using (InstructionWriter writer = new InstructionWriter())
                {
                    writer.AttachInstructionSequence( sequence );

                    // Find the base method.
                    IMethod baseValidateMethod = null;
                    IType baseTypeCursor = typeDef.BaseType;
                    MethodSignature methodSignature =
                        new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Void ),
                                             new ITypeSignature[0], 0 );

                    while ( baseValidateMethod == null )
                    {
                        TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition();

                        baseValidateMethod =
                            baseTypeCursorTypeDef.Methods.GetMethod( "AutoGeneratedValidate",
                                                                     methodSignature.Translate( baseTypeCursorTypeDef.Module ),
                                                                     BindingOptions.OnlyExisting |
                                                                     BindingOptions.DontThrowException );

                        baseTypeCursor = baseTypeCursorTypeDef.BaseType;
                    }

                    // TODO: support generic base types.

                    // Call the base method.
                    writer.EmitInstruction( OpCodeNumber.Ldarg_0 );
                    writer.EmitInstructionMethod( OpCodeNumber.Call, (IMethod) baseValidateMethod.Translate( typeDef.Module ) );

                    // Make an array with the boxed field values.
                    TypeValidationAspect aspect = (TypeValidationAspect) this.AspectWeaverInstance.Aspect;
                    LocalVariableSymbol fieldValuesArrayLocal = instructionBlock.DefineLocalVariable(
                        module.Cache.GetType( typeof(object[]) ), "fieldValues" );
                    writer.EmitInstructionInt32( OpCodeNumber.Ldc_I4, aspect.Validators.Count );
                    writer.EmitInstructionType( OpCodeNumber.Newarr, module.Cache.GetIntrinsic( IntrinsicType.Object ) );
                    writer.EmitInstructionLocalVariable( OpCodeNumber.Stloc, fieldValuesArrayLocal );

                    int i = 0;
                    foreach ( FieldValidationAttribute validator in aspect.Validators )
                    {
                        FieldDefDeclaration fieldDef = typeDef.Fields.GetByName( validator.TargetLocation.Name );
                        IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance( fieldDef );

                        writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, fieldValuesArrayLocal );
                        writer.EmitInstructionInt32( OpCodeNumber.Ldc_I4, i );
                        writer.EmitInstruction( OpCodeNumber.Ldarg_0 );
                        writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec );
                        writer.EmitConvertToObject( fieldSpec.FieldType );
                        writer.EmitInstruction( OpCodeNumber.Stelem_Ref );

                        i++;
                    }

                    // Get the validator method.
                    IMethod validateMethod = module.Cache.GetItem(
                        () => module.FindMethod(
                                  typeof(TypeValidationAspect).GetMethod( "Validate" ),
                                  BindingOptions.Default ) );

                    // Call the validator.
                    this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField( writer, null );
                    writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, fieldValuesArrayLocal );
                    writer.EmitInstructionMethod( OpCodeNumber.Callvirt, validateMethod );

                    writer.EmitInstruction( OpCodeNumber.Ret );
                    writer.DetachInstructionSequence();
                }
            }