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(); }
private TypeDefDeclaration CreateContainingType() { string uniqueName = this.module.Types.GetUniqueName( DebuggerSpecialNames.GetDeclarationSpecialName("LoggingImplementationDetails{0}")); TypeDefDeclaration logCategoriesType = new TypeDefDeclaration { Name = uniqueName, Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.Abstract, BaseType = ((IType)this.module.Cache.GetType("System.Object, mscorlib")) }; this.module.Types.Add(logCategoriesType); // Add [CompilerGenerated] and [DebuggerNonUserCode] to the type this.weavingHelper.AddCompilerGeneratedAttribute(logCategoriesType.CustomAttributes); this.weavingHelper.AddDebuggerNonUserCodeAttribute(logCategoriesType.CustomAttributes); MethodDefDeclaration staticConstructor = new MethodDefDeclaration { Name = ".cctor", Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, }; logCategoriesType.Methods.Add(staticConstructor); staticConstructor.ReturnParameter = new ParameterDeclaration { Attributes = ParameterAttributes.Retval, ParameterType = this.module.Cache.GetIntrinsic(IntrinsicType.Void) }; this.constructorBlock = staticConstructor.MethodBody.RootInstructionBlock = staticConstructor.MethodBody.CreateInstructionBlock(); this.returnSequence = staticConstructor.MethodBody.RootInstructionBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(this.returnSequence); this.writer.EmitInstruction(OpCodeNumber.Ret); this.writer.DetachInstructionSequence(); return(logCategoriesType); }
/// <summary> /// Creates a new method body and assigns it to <paramref name="hostMethod"/>. The method body looks as described in <see cref="CreatedEmptyMethod"/>. /// </summary> /// <param name="instructionWriter">A <b>detached</b> instruction writer.</param> /// <param name="hostMethod">The method without body. The body will be assigned to this method.</param> /// <returns>References to points in the method body.</returns> public static CreatedEmptyMethod CreateModifiableMethodBody(InstructionWriter instructionWriter, MethodDefDeclaration hostMethod) { // Create a new method body to host the pipeline. hostMethod.MethodBody = new MethodBodyDeclaration(); InstructionBlock rootInstructionBlock = hostMethod.MethodBody.RootInstructionBlock = hostMethod.MethodBody.CreateInstructionBlock(); InstructionBlock sequencePointBlock = rootInstructionBlock.AddChildBlock(); InstructionSequence sequencePointSequence = sequencePointBlock.AddInstructionSequence(); instructionWriter.AttachInstructionSequence(sequencePointSequence); instructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); instructionWriter.EmitInstruction(OpCodeNumber.Nop); instructionWriter.DetachInstructionSequence(); InstructionBlock implementationBlock = rootInstructionBlock.AddChildBlock(); InstructionBlock returnBlock = rootInstructionBlock.AddChildBlock(); InstructionSequence returnSequence = returnBlock.AddInstructionSequence(); instructionWriter.AttachInstructionSequence(returnSequence); instructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); LocalVariableSymbol returnVariable; if (!hostMethod.ReturnParameter.ParameterType.IsIntrinsic(IntrinsicType.Void)) { hostMethod.MethodBody.InitLocalVariables = true; returnVariable = rootInstructionBlock.DefineLocalVariable( hostMethod.ReturnParameter.ParameterType, DebuggerSpecialNames.GetVariableSpecialName(hostMethod.Domain, "returnValue", DebuggerSpecialVariableKind.ReturnValue) ); instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, returnVariable); } else { returnVariable = null; } instructionWriter.EmitInstruction(OpCodeNumber.Ret); instructionWriter.DetachInstructionSequence(); return(new CreatedEmptyMethod(hostMethod, implementationBlock, returnVariable, returnSequence)); }
private void EmitMessage(InstructionBlock block, InstructionWriter writer, LogLevel logLevel, string messageFormatString, int[] arguments, ITypeSignature exceptionType = null) { 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); LocalVariableSymbol exceptionLocal = null; if (exceptionType != null) { exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable( exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex")); } 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); Action <InstructionWriter> getExceptionAction = exceptionLocal != null ? (Action <InstructionWriter>)(w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal)) : null; builder.EmitWrite(writer, messageFormatString, exceptionType == null ? arguments.Length : arguments.Length + 1, logLevel, getExceptionAction, (i, instructionWriter) => { if (i < arguments.Length) { 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).GetNakedType(TypeNakingOptions.IgnoreManagedPointers)); } } else { //Emit exception parameter instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal); } }, useWrapper); if (exceptionType == null) { writer.DetachInstructionSequence(); } }