コード例 #1
0
        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;
            }
        }
コード例 #2
0
        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;
        }