private void UpdateLocalVariablesOnExit(MethodDefinition method, List <Instruction> instructions, ILProcessor processor) { // evaluation stack: bottom if (context.ReturnVariableIndex >= 0) { var returnVariableIndex = context.ReturnVariableIndex; context.ReturnVariableIndex = method.Body.Variables.Count; method.Body.Variables.Add(new VariableDefinition(context.BaseReference.Return.ReadOnlyTypeReference)); if (context.ReturnValueVariableIndex >= 0) { // hasExceptionIndex must have been initialized in this branch, according to need parameter rules context.ReturnFinallySwitchableSection.StartIndex = instructions.Count; // evaluation stack after the following statement: bottom->IReturnBuilder instructions.Add(processor.Create(OpCodes.Ldloc, returnVariableIndex)); // evaluation stack after the following statement: bottom->IReturnBuilder-><has exception> instructions.Add(processor.Create(OpCodes.Ldloc, context.HasExceptionVariableIndex)); instructions.Add(processor.Create(OpCodes.Ldc_I4_0)); // evaluation stack after the following statement: bottom->IReturnBuilder-><has return> instructions.Add(processor.Create(OpCodes.Ceq)); // evaluation stack after the following statement: bottom instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Return.HasReturnSetter)); // evaluation stack after the following statement: bottom->IReturnBuilder-><has exception> instructions.Add(processor.Create(OpCodes.Ldloc, context.HasExceptionVariableIndex)); // later, insert if start statement here var ifStartIndex = instructions.Count; // evaluation stack after the following statement: bottom instructions.Add(null); // evaluation stack after the following statement: bottom->IReturnBuilder instructions.Add(processor.Create(OpCodes.Ldloc, returnVariableIndex)); // evaluation stack after the following statement: bottom->IReturnBuilder-><return value> instructions.Add(processor.Create(OpCodes.Ldloc, context.ReturnValueVariableIndex)); // insert indirect load instruction if (method.ReturnType.IsByReference && method.ReturnType is TypeSpecification) { instructions.Add(processor.CreateIndirectLoadInstruction(method.ReturnType)); } // insert box instruction if (method.ReturnType.IsValueType) { instructions.Add(processor.CreateBoxValueTypeInstruction(method.ReturnType)); } // evaluation stack after the following statement: bottom instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Return.ValueSetter)); var ifEndInstruction = processor.Create(OpCodes.Ldloc, returnVariableIndex); // evaluation stack after the following statement: bottom->IReturnBuilder instructions.Add(ifEndInstruction); // fill back if start instruction, BrTrue.S should be safe here, there aren't enough instructions to exceed offset of 127 instructions[ifStartIndex] = processor.Create(OpCodes.Brtrue_S, ifEndInstruction); } else { // in this branch, the method must return null, according to need parameter rule context.ReturnFinallySwitchableSection.StartIndex = instructions.Count; // evaluation stack after the following statement: bottom->IReturnBuilder instructions.Add(processor.Create(OpCodes.Ldloc, returnVariableIndex)); // evaluation stack after the following statement: bottom->IReturnBuilder->IReturnBuilder instructions.Add(processor.Create(OpCodes.Dup)); // evaluation stack after the following statement: bottom->IReturnBuilder->IReturnBuilder->false instructions.Add(processor.Create(OpCodes.Ldc_I4_0)); // evaluation stack after the following statement: bottom->IReturnBuilder instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Return.HasReturnSetter)); } // evaluation stack after the following statement: bottom->IReturn instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Return.BuildMethod)); instructions.Add(processor.Create(OpCodes.Stloc, context.ReturnVariableIndex)); context.ReturnFinallySwitchableSection.EndIndex = instructions.Count; } }
private void AddExecutionVariable(MethodDefinition method, List <Instruction> instructions, ILProcessor processor) { // evaluation stack: bottom method.Body.Variables.Add(new VariableDefinition(context.BaseReference.Execution.TypeReference)); context.ExecutionVariableSwitchableSection.StartIndex = instructions.Count; instructions.Add(processor.Create(OpCodes.Ldstr, method.Module.Assembly.FullName)); instructions.Add(processor.Create(OpCodes.Ldstr, method.DeclaringType.Namespace)); instructions.Add(processor.Create(OpCodes.Ldstr, method.DeclaringType.FullName)); instructions.Add(processor.Create(OpCodes.Ldstr, method.DeclaringType.Name)); if (method.HasThis) { instructions.Add(processor.Create(OpCodes.Ldarg_0)); instructions.Add(processor.Create(OpCodes.Callvirt, context.GetMethodReference(getHashCodeMethod))); } else { instructions.Add(processor.Create(OpCodes.Ldc_I4_0)); } instructions.Add(processor.Create(OpCodes.Ldstr, method.FullName)); instructions.Add(processor.Create(OpCodes.Ldstr, method.Name)); instructions.Add(processor.Create(OpCodes.Ldstr, method.ReturnType.FullName)); // evaluation stack after the following statement: bottom->ICanAddParameters instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeExecutionMethod)); if (method.HasParameters) { foreach (var parameter in method.Parameters) { // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters instructions.Add(processor.Create(OpCodes.Dup)); instructions.Add(processor.Create(OpCodes.Ldstr, parameter.Name)); instructions.Add(processor.Create(OpCodes.Ldstr, parameter.ParameterType.FullName)); instructions.Add(processor.Create(OpCodes.Ldc_I4, parameter.Sequence)); instructions.Add(processor.Create(OpCodes.Ldarg, parameter.Sequence)); // insert indirect load instruction if (parameter.ParameterType.IsByReference && parameter.ParameterType is TypeSpecification) { instructions.Add(processor.CreateIndirectLoadInstruction(parameter.ParameterType)); } // insert box instruction if (parameter.ParameterType.IsValueType) { instructions.Add(processor.CreateBoxValueTypeInstruction(parameter.ParameterType)); } // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeParameterMethod)); if (parameter.HasCustomAttributes) { for (var i = 0; i < parameter.CustomAttributes.Count; i++) { var attribute = parameter.CustomAttributes[i]; // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute instructions.Add(processor.Create(OpCodes.Dup)); instructions.Add(processor.Create(OpCodes.Ldstr, attribute.AttributeType.FullName)); instructions.Add(processor.Create(OpCodes.Ldc_I4, i)); // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeCustomAttributeMethod)); if (attribute.HasProperties) { for (var j = 0; j < attribute.Properties.Count; j++) { var property = attribute.Properties[j]; if (IlUtilities.CustomAttributePropertyTypeIsSupported(property.Argument)) { // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty->ICanAddAttributeProperty instructions.Add(processor.Create(OpCodes.Dup)); instructions.Add(processor.Create(OpCodes.Ldstr, property.Name)); instructions.Add(processor.Create(OpCodes.Ldstr, property.Argument.Type.FullName)); instructions.Add(processor.Create(OpCodes.Ldc_I4, j)); instructions.Add(processor.CreateLoadCustomAttributePropertyValueInstruction(property.Argument)); if (property.Argument.Type.IsValueType) { instructions.Add(processor.CreateBoxValueTypeInstruction(property.Argument.Type)); } // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty->ICanAddAttributeProperty->IAttributeProperty instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeAttributePropertyMethod)); // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.CustomAttribute.AddAttributePropertyMethod)); } } } // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICustomAttribute instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.CustomAttribute.BuildMethod)); // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Parameter.AddCustomAttributeMethod)); } } // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->IParameter instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Parameter.BuildMethod)); // evaluation stack after the following statement: bottom->ICanAddParameters instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Execution.AddParameterMethod)); } } // evaluation stack after the following statement: bottom->IMethodExecution instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Execution.BuildMethod)); context.ExecutionVariableIndex = method.Body.Variables.Count; method.Body.Variables.Add(new VariableDefinition(context.BaseReference.Execution.ReadOnlyTypeReference)); instructions.Add(processor.Create(OpCodes.Stloc, context.ExecutionVariableIndex)); // evaluation stack after the following statement: bottom context.ExecutionVariableSwitchableSection.EndIndex = instructions.Count; }