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()); }
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); }
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); }
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); }
public void Emit(InstructionWriter writer, InstructionBlock block, TypeInitializationClientScopes scope) { InstructionSequence sequence = block.AddInstructionSequence(); writer.AttachInstructionSequence(sequence); writer.EmitInstructionMethod(OpCodeNumber.Call, attachMethod); writer.DetachInstructionSequence(); }
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); } }
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(); } }
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); }); }
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); }
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(); }
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); }
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); }
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); }
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(); } }
/// <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); }
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"); } }
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); }
private void RaisePropertyChangingEvent(InstructionBlock block, InstructionWriter writer) { var invokerMethod = FindOnPropertyChangingWithStringParameter(); CallEventInvokerMethod(invokerMethod, block,writer); }
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); }
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(); } }