public ParameterBuilder CreateParameterBuilder(ILConversion conversion, ConvertedRoutine routine, ConvertedRoutineParameter parameter) { ParameterBuilder builder = null; var attributes = GetParameterAttributes(parameter.ParameterDefinition); if (routine.IsConstructor()) { var constructor = (ConvertedEmittedConstructor)routine; builder = constructor.ConstructorBuilder.DefineParameter(parameter.Position, attributes, parameter.Name); } else { var method = (ConvertedBuiltMethod)routine; builder = method.MethodBuilder.DefineParameter(parameter.Position, attributes, parameter.Name); } if ((attributes & ParameterAttributes.HasDefault) > 0) { builder.SetConstant(parameter.ParameterDefinition.Constant); } CustomAttributes.BuildCustomAttributes(conversion, parameter); return(builder); }
private bool EmitOpCodes(ILConversion conversion, ConvertedRoutine routine) { var methodDefinition = (MethodDefinition)routine.MethodReference; var bodyState = routine.EmitState.Body; if (bodyState.InstructionStream == null) { bodyState.InstructionStream = new ConvertedILStream { Buffer = new byte[methodDefinition.Body.CodeSize], ModuleBuilder = routine.DeclaringType.Module.ModuleBuilder }; } for (int iInstruction = bodyState.CurrentInstruction; iInstruction < methodDefinition.Body.Instructions.Count; bodyState.CurrentInstruction = ++iInstruction) { var instructionDefinition = methodDefinition.Body.Instructions[iInstruction]; if (!EmitOpCode(conversion, routine, methodDefinition, bodyState.InstructionStream, instructionDefinition)) { return(false); } } return(true); }
/// <summary> /// Gets an array of bytes that contain the serialized local variable structure (.locals structure) of a routine. /// </summary> /// <param name="conversion"></param> /// /// <param name="routine"></param> /// <returns></returns> public bool GetLocalSignature(ILConversion conversion, ConvertedRoutine routine) { var bodyEmitState = routine.EmitState.Body; if (bodyEmitState.SignatureHelper == null) { bodyEmitState.SignatureHelper = SignatureHelper.GetLocalVarSigHelper(routine.DeclaringType.Module.ModuleBuilder); } var localVariables = routine.Body.LocalVariables; if (localVariables != null) { for (int i = bodyEmitState.CurrentLocalVariable; i < localVariables.Length; bodyEmitState.CurrentLocalVariable = ++i) { var localVariable = localVariables[i]; if (localVariable.CustomModifiers != null && localVariable.CustomModifiers.Count > 0) { throw new Exception("Currently do not support emitted custom modifiers in local variables"); } bodyEmitState.SignatureHelper.AddArgument(localVariable.UnderlyingType, localVariable.IsPinned); } } bodyEmitState.LocalSignature = bodyEmitState.SignatureHelper.GetSignature(); return(true); //var e01dLocalSignature = Signatures.GetLocalSignature(conversion, convertedConstructor); //foreach (var local in routine.Body.LocalVariables) //{ //var type = ResolveType(local.Type); //if (local.IsReference) //{ // type = type.MakeByRefType(); //} //if (local.CustomModifiers.Any()) //{ // if (local.IsPinned) // { // throw new NotSupportedException("Ref.Emit limitation"); // } // Type[] reqMods, optMods; // ResolveCustomModifiers(local.CustomModifiers, out reqMods, out optMods); // sigHelper.AddArgument(type, reqMods, optMods); //} //else //{ // sigHelper.AddArgument(type, local.IsPinned); //} //localCount++; //} }
public void CreateParameterBuilders(ILConversion conversion, ConvertedRoutine routine) { for (int i = 0; i < routine.Parameters.All.Count; i++) { var parameter = (ConvertedRoutineParameter)routine.Parameters.All[i]; parameter.Builder = CreateParameterBuilder(conversion, routine, parameter); } }
public MethodInfo GetMethodInfoOrThrow(ILConversion conversion, ConvertedTypeDefinitionMask_I typeBeingBuilt, ConvertedRoutine methodBeingBuilt, BoundTypeDefinitionMask_I methodReferenceDeclaringType, MethodReference methodReference) { //var declaringType = Execution.Types.Ensuring.EnsureBound(conversion.Model, methodReference.DeclaringType); if (!(methodReferenceDeclaringType is BoundTypeDefinitionWithMethodsMask_I declaringTypeWithMethods)) { throw new System.Exception("Expected a type with methods declared."); } var methodInfo = GetMethodOrThrow_Internal(conversion, typeBeingBuilt, declaringTypeWithMethods, methodReference); if (methodInfo == null) { throw new System.Exception("Could not locate a MethodInfo."); } if (!methodReference.IsGenericInstance) { return(methodInfo); } if (!methodInfo.IsGenericMethod) { throw new System.Exception("Did not find a generic method"); } var genericInstanceMethod = (GenericInstanceMethod)methodReference; var typeArguments = new Type[genericInstanceMethod.GenericArguments.Count]; for (var i = 0; i < typeArguments.Length; i++) { var typeArgumentReference = genericInstanceMethod.GenericArguments[i]; var semanticTypeNode = Execution.Types.Ensuring.Ensure(new ExecutionEnsureContext() { Conversion = conversion, RuntimicSystem = conversion.RuntimicSystem, TypeReference = typeArgumentReference, MethodReference = methodBeingBuilt.MethodReference }); typeArguments[i] = semanticTypeNode.Type.UnderlyingType; } return(methodInfo.MakeGenericMethod(typeArguments)); }
public Type SetReturnType(ILConversion conversion, ConvertedRoutine routine) { var methodDefinition = routine.MethodReference; if (methodDefinition.ReturnType == null) { return(null); } var bound = Execution.Types.Ensuring.EnsureBound(conversion, methodDefinition.ReturnType); routine.ReturnType = bound; return(bound.UnderlyingType); }
private void CreateTokenFixups(ILConversion conversion, ConvertedRoutine convertedConstructor) { var bodyState = convertedConstructor.EmitState.Body; var ilInstructionStream = bodyState.InstructionStream; var tokenFixups = new int[ilInstructionStream.FixupCount]; if (ilInstructionStream.Fixups != null) { Array.Copy(ilInstructionStream.Fixups, 0, tokenFixups, 0, ilInstructionStream.FixupCount); } bodyState.TokenFixups = tokenFixups; }
public bool GetExceptionHandlerList(ILConversion conversion, ConvertedRoutine convertedRoutine) { var methodDefinition = (MethodDefinition)convertedRoutine.MethodReference; var moduleBuilder = convertedRoutine.DeclaringType.Module.ModuleBuilder; var regions = methodDefinition.Body.ExceptionHandlers; var handlers = new ExceptionHandler[regions.Count]; var bodyEmitState = convertedRoutine.EmitState.Body; for (int i = bodyEmitState.CurrentExceptionHandler; i < regions.Count; bodyEmitState.CurrentExceptionHandler = ++i) { var info = regions[i]; int catchToken = 0; if (info.HandlerType == ExceptionHandlerType.Catch) { var boundType = Execution.Types.Ensuring.EnsureBound(conversion, info.CatchType); if ((boundType is ConvertedTypeDefinition_I convertedType) && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)convertedRoutine.DeclaringType, true)) { return(false); } catchToken = moduleBuilder.GetTypeToken(boundType.UnderlyingType).Token; if (catchToken == 0) { } } handlers[i] = new ExceptionHandler( tryOffset: info.TryStart.Offset, tryLength: info.TryEnd.Offset - info.TryStart.Offset, filterOffset: info.FilterStart?.Offset ?? 0, handlerOffset: info.HandlerStart.Offset, handlerLength: info.HandlerEnd.Offset - info.HandlerStart.Offset, kind: (ExceptionHandlingClauseOptions)info.HandlerType, exceptionTypeToken: catchToken); } convertedRoutine.EmitState.Body.ExceptionHandlers = handlers; return(true); }
public bool EmitILStream(ILConversion conversion, ConvertedRoutine convertedConstructor) { var typeReference = convertedConstructor.DeclaringType.SourceTypeReference; if (typeReference.FullName.Contains("Root.Testing.Tests.Apis.E01D.Runtimic.Execution.Emitting.Conversion.Inputs.InstructionTests/<>c")) { } if (!EmitOpCodes(conversion, convertedConstructor)) { return(false); } CreateTokenFixups(conversion, convertedConstructor); return(true); }
public Type[] CreateParameters(ILConversion conversion, ConvertedRoutine routine) { var methodDefinition = routine.MethodReference; if (!methodDefinition.HasParameters) { return(new Type[0]); } var systemParameterTypes = new Type[methodDefinition.Parameters.Count]; for (int i = 0; i < methodDefinition.Parameters.Count; i++) { var parameterDefinition = methodDefinition.Parameters[i]; var bound = Execution.Types.Ensuring.EnsureBound(conversion, parameterDefinition.ParameterType); var convertedParameter = new ConvertedRoutineParameter() { ParameterDefinition = parameterDefinition, Position = parameterDefinition.Sequence, Name = parameterDefinition.Name, ParameterType = bound }; // Make sure the 0th "this" parameter is not being overridden //if ( // //!methodDefinition.IsStatic && // convertedParameter.Position == 0) //{ // throw new Exception("Parameter position is zero which should be reserved for the 'return' argument."); //} routine.Parameters.All.Add(convertedParameter); systemParameterTypes[i] = bound.UnderlyingType; } return(systemParameterTypes); }
public bool GetMemberInfo(ILConversion conversion, ConvertedTypeDefinitionMask_I typeBeingBuilt, ConvertedRoutine routineBeingBuilt, BoundTypeDefinitionMask_I methodReferenceDeclaringType, MethodReference methodReference, out MemberInfo memberInfo) { if (methodReference == null) { throw new System.Exception($"Member reference is null. Cannot resolve member info."); } // If a constructor if (methodReference.Name == ConstructorInfo.ConstructorName) { return(Constructors.Getting.GetConstructor(conversion, typeBeingBuilt, methodReferenceDeclaringType, methodReference, out memberInfo)); } memberInfo = Methods.Getting.GetMethodInfoOrThrow(conversion, typeBeingBuilt, routineBeingBuilt, methodReferenceDeclaringType, methodReference); return(memberInfo != null); }
private bool EmitOpCode(ILConversion conversion, ConvertedRoutine routine, MethodDefinition methodDefinition, ConvertedILStream stream, Instruction instructionDefinition) { if (methodDefinition.Name == "GetCustomAttributeArgumentValue" && instructionDefinition.Offset == 0x062) { } OpCode opCode = Cecil.Metadata.Instructions.ConvertOpCode(instructionDefinition.OpCode.Code); switch (instructionDefinition.OpCode.Code) { case Libs.Mono.Cecil.Cil.Code.Add: case Libs.Mono.Cecil.Cil.Code.Add_Ovf: case Libs.Mono.Cecil.Cil.Code.Add_Ovf_Un: case Libs.Mono.Cecil.Cil.Code.And: case Libs.Mono.Cecil.Cil.Code.Arglist: case Libs.Mono.Cecil.Cil.Code.Break: case Libs.Mono.Cecil.Cil.Code.Ceq: case Libs.Mono.Cecil.Cil.Code.Cgt: case Libs.Mono.Cecil.Cil.Code.Cgt_Un: case Libs.Mono.Cecil.Cil.Code.Ckfinite: case Libs.Mono.Cecil.Cil.Code.Clt: case Libs.Mono.Cecil.Cil.Code.Clt_Un: case Libs.Mono.Cecil.Cil.Code.Conv_I: case Libs.Mono.Cecil.Cil.Code.Conv_I1: case Libs.Mono.Cecil.Cil.Code.Conv_I2: case Libs.Mono.Cecil.Cil.Code.Conv_I4: case Libs.Mono.Cecil.Cil.Code.Conv_I8: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I1: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I1_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I2: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I2_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I4: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I4_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I8: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I8_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_I_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U1: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U1_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U2: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U2_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U4: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U4_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U8: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U8_Un: case Libs.Mono.Cecil.Cil.Code.Conv_Ovf_U_Un: case Libs.Mono.Cecil.Cil.Code.Conv_R4: case Libs.Mono.Cecil.Cil.Code.Conv_R8: case Libs.Mono.Cecil.Cil.Code.Conv_R_Un: case Libs.Mono.Cecil.Cil.Code.Conv_U: case Libs.Mono.Cecil.Cil.Code.Conv_U1: case Libs.Mono.Cecil.Cil.Code.Conv_U2: case Libs.Mono.Cecil.Cil.Code.Conv_U4: case Libs.Mono.Cecil.Cil.Code.Conv_U8: case Libs.Mono.Cecil.Cil.Code.Cpblk: case Libs.Mono.Cecil.Cil.Code.Div: case Libs.Mono.Cecil.Cil.Code.Div_Un: case Libs.Mono.Cecil.Cil.Code.Dup: case Libs.Mono.Cecil.Cil.Code.Endfilter: case Libs.Mono.Cecil.Cil.Code.Endfinally: case Libs.Mono.Cecil.Cil.Code.Initblk: case Libs.Mono.Cecil.Cil.Code.Ldarg_0: case Libs.Mono.Cecil.Cil.Code.Ldarg_1: case Libs.Mono.Cecil.Cil.Code.Ldarg_2: case Libs.Mono.Cecil.Cil.Code.Ldarg_3: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_0: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_1: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_2: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_3: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_4: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_5: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_6: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_7: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_8: case Libs.Mono.Cecil.Cil.Code.Ldc_I4_M1: case Libs.Mono.Cecil.Cil.Code.Ldnull: case Libs.Mono.Cecil.Cil.Code.Ldelem_I: case Libs.Mono.Cecil.Cil.Code.Ldelem_I1: case Libs.Mono.Cecil.Cil.Code.Ldelem_I2: case Libs.Mono.Cecil.Cil.Code.Ldelem_I4: case Libs.Mono.Cecil.Cil.Code.Ldelem_I8: case Libs.Mono.Cecil.Cil.Code.Ldelem_R4: case Libs.Mono.Cecil.Cil.Code.Ldelem_R8: case Libs.Mono.Cecil.Cil.Code.Ldelem_Ref: case Libs.Mono.Cecil.Cil.Code.Ldelem_U1: case Libs.Mono.Cecil.Cil.Code.Ldelem_U2: case Libs.Mono.Cecil.Cil.Code.Ldelem_U4: case Libs.Mono.Cecil.Cil.Code.Ldlen: case Libs.Mono.Cecil.Cil.Code.Ldind_I: case Libs.Mono.Cecil.Cil.Code.Ldind_I1: case Libs.Mono.Cecil.Cil.Code.Ldind_I2: case Libs.Mono.Cecil.Cil.Code.Ldind_I4: case Libs.Mono.Cecil.Cil.Code.Ldind_I8: case Libs.Mono.Cecil.Cil.Code.Ldind_R4: case Libs.Mono.Cecil.Cil.Code.Ldind_R8: case Libs.Mono.Cecil.Cil.Code.Ldind_Ref: case Libs.Mono.Cecil.Cil.Code.Ldind_U1: case Libs.Mono.Cecil.Cil.Code.Ldind_U2: case Libs.Mono.Cecil.Cil.Code.Ldind_U4: case Libs.Mono.Cecil.Cil.Code.Ldloc_0: case Libs.Mono.Cecil.Cil.Code.Ldloc_1: case Libs.Mono.Cecil.Cil.Code.Ldloc_2: case Libs.Mono.Cecil.Cil.Code.Ldloc_3: case Libs.Mono.Cecil.Cil.Code.Localloc: case Libs.Mono.Cecil.Cil.Code.Mul: case Libs.Mono.Cecil.Cil.Code.Mul_Ovf: case Libs.Mono.Cecil.Cil.Code.Mul_Ovf_Un: case Libs.Mono.Cecil.Cil.Code.Neg: case Libs.Mono.Cecil.Cil.Code.Nop: case Libs.Mono.Cecil.Cil.Code.Not: case Libs.Mono.Cecil.Cil.Code.Pop: case Libs.Mono.Cecil.Cil.Code.Or: case Libs.Mono.Cecil.Cil.Code.Readonly: case Libs.Mono.Cecil.Cil.Code.Refanytype: case Libs.Mono.Cecil.Cil.Code.Rem: case Libs.Mono.Cecil.Cil.Code.Rem_Un: case Libs.Mono.Cecil.Cil.Code.Ret: case Libs.Mono.Cecil.Cil.Code.Rethrow: case Libs.Mono.Cecil.Cil.Code.Stelem_I: case Libs.Mono.Cecil.Cil.Code.Stelem_I1: case Libs.Mono.Cecil.Cil.Code.Stelem_I2: case Libs.Mono.Cecil.Cil.Code.Stelem_I4: case Libs.Mono.Cecil.Cil.Code.Stelem_I8: case Libs.Mono.Cecil.Cil.Code.Stelem_R4: case Libs.Mono.Cecil.Cil.Code.Stelem_R8: case Libs.Mono.Cecil.Cil.Code.Stelem_Ref: case Libs.Mono.Cecil.Cil.Code.Stind_I: case Libs.Mono.Cecil.Cil.Code.Stind_I1: case Libs.Mono.Cecil.Cil.Code.Stind_I2: case Libs.Mono.Cecil.Cil.Code.Stind_I4: case Libs.Mono.Cecil.Cil.Code.Stind_I8: case Libs.Mono.Cecil.Cil.Code.Stind_R4: case Libs.Mono.Cecil.Cil.Code.Stind_R8: case Libs.Mono.Cecil.Cil.Code.Stind_Ref: case Libs.Mono.Cecil.Cil.Code.Stloc_0: case Libs.Mono.Cecil.Cil.Code.Stloc_1: case Libs.Mono.Cecil.Cil.Code.Stloc_2: case Libs.Mono.Cecil.Cil.Code.Stloc_3: case Libs.Mono.Cecil.Cil.Code.Shl: case Libs.Mono.Cecil.Cil.Code.Shr: case Libs.Mono.Cecil.Cil.Code.Shr_Un: case Libs.Mono.Cecil.Cil.Code.Sub: case Libs.Mono.Cecil.Cil.Code.Sub_Ovf: case Libs.Mono.Cecil.Cil.Code.Sub_Ovf_Un: case Libs.Mono.Cecil.Cil.Code.Tail: case Libs.Mono.Cecil.Cil.Code.Throw: case Libs.Mono.Cecil.Cil.Code.Volatile: case Libs.Mono.Cecil.Cil.Code.Xor: { Generation.Emit(conversion, stream, opCode); break; } case Libs.Mono.Cecil.Cil.Code.Beq_S: case Libs.Mono.Cecil.Cil.Code.Bge_S: case Libs.Mono.Cecil.Cil.Code.Bge_Un_S: case Libs.Mono.Cecil.Cil.Code.Bgt_Un_S: case Libs.Mono.Cecil.Cil.Code.Bgt_S: case Libs.Mono.Cecil.Cil.Code.Ble_S: case Libs.Mono.Cecil.Cil.Code.Ble_Un_S: case Libs.Mono.Cecil.Cil.Code.Blt_S: case Libs.Mono.Cecil.Cil.Code.Blt_Un_S: case Libs.Mono.Cecil.Cil.Code.Bne_Un_S: case Libs.Mono.Cecil.Cil.Code.Brfalse_S: case Libs.Mono.Cecil.Cil.Code.Brtrue_S: case Libs.Mono.Cecil.Cil.Code.Br_S: case Libs.Mono.Cecil.Cil.Code.Leave_S: { var startingOffset = instructionDefinition.Offset; var opCodeSize = instructionDefinition.OpCode.Size; var targetOffset = ((Instruction)instructionDefinition.Operand).Offset; var relativeOffset = targetOffset - (startingOffset + opCodeSize + 1); if (instructionDefinition.BranchRelativeOffset != relativeOffset) { throw new Exception("Relative offset incorrect"); } Generation.Emit(conversion, stream, opCode, (sbyte)instructionDefinition.BranchRelativeOffset); break; } case Libs.Mono.Cecil.Cil.Code.Beq: case Libs.Mono.Cecil.Cil.Code.Bge: case Libs.Mono.Cecil.Cil.Code.Bge_Un: case Libs.Mono.Cecil.Cil.Code.Bgt: case Libs.Mono.Cecil.Cil.Code.Bgt_Un: case Libs.Mono.Cecil.Cil.Code.Ble: case Libs.Mono.Cecil.Cil.Code.Ble_Un: case Libs.Mono.Cecil.Cil.Code.Blt: case Libs.Mono.Cecil.Cil.Code.Blt_Un: case Libs.Mono.Cecil.Cil.Code.Bne_Un: case Libs.Mono.Cecil.Cil.Code.Br: case Libs.Mono.Cecil.Cil.Code.Brfalse: case Libs.Mono.Cecil.Cil.Code.Brtrue: case Libs.Mono.Cecil.Cil.Code.Leave: { var startingOffset = instructionDefinition.Offset; var opCodeSize = instructionDefinition.OpCode.Size; var targetOffset = ((Instruction)instructionDefinition.Operand).Offset; var relativeOffset = targetOffset - (startingOffset + opCodeSize + 4); if (instructionDefinition.BranchRelativeOffset != relativeOffset) { throw new Exception("Relative offset incorrect"); } Generation.Emit(conversion, stream, opCode, instructionDefinition.BranchRelativeOffset); break; } case Libs.Mono.Cecil.Cil.Code.Box: case Libs.Mono.Cecil.Cil.Code.Castclass: case Libs.Mono.Cecil.Cil.Code.Constrained: case Libs.Mono.Cecil.Cil.Code.Cpobj: case Libs.Mono.Cecil.Cil.Code.Initobj: case Libs.Mono.Cecil.Cil.Code.Isinst: case Libs.Mono.Cecil.Cil.Code.Ldelem_Any: case Libs.Mono.Cecil.Cil.Code.Ldelema: case Libs.Mono.Cecil.Cil.Code.Ldobj: case Libs.Mono.Cecil.Cil.Code.Mkrefany: case Libs.Mono.Cecil.Cil.Code.Newarr: case Libs.Mono.Cecil.Cil.Code.Refanyval: case Libs.Mono.Cecil.Cil.Code.Sizeof: case Libs.Mono.Cecil.Cil.Code.Stelem_Any: case Libs.Mono.Cecil.Cil.Code.Stobj: case Libs.Mono.Cecil.Cil.Code.Unbox: case Libs.Mono.Cecil.Cil.Code.Unbox_Any: { if (!Types.Ensuring.EnsurePhase3Type(conversion, routine.DeclaringType, methodDefinition, (TypeReference)instructionDefinition.Operand, out BoundTypeDefinitionMask_I type)) { return(false); } Generation.Emit(conversion, stream, opCode, type.UnderlyingType); break; } case Libs.Mono.Cecil.Cil.Code.Ldarg: case Libs.Mono.Cecil.Cil.Code.Ldarga: case Libs.Mono.Cecil.Cil.Code.Starg: { if (instructionDefinition.Operand is ParameterDefinition parameter) { Generation.Emit(conversion, stream, opCode, (ushort)parameter.Sequence); } else { Generation.Emit(conversion, stream, opCode, (ushort)instructionDefinition.Operand); } break; } case Libs.Mono.Cecil.Cil.Code.Ldarga_S: case Libs.Mono.Cecil.Cil.Code.Ldarg_S: case Libs.Mono.Cecil.Cil.Code.Starg_S: { if (instructionDefinition.Operand is ParameterDefinition parameter) { Generation.Emit(conversion, stream, opCode, (byte)parameter.Sequence); } else { Generation.Emit(conversion, stream, opCode, (byte)instructionDefinition.Operand); } break; } // Constant Loading - Push the supplied integer value onto the stack case Libs.Mono.Cecil.Cil.Code.Ldc_I4: { Generation.Emit(conversion, stream, opCode, (int)instructionDefinition.Operand); break; } case Libs.Mono.Cecil.Cil.Code.Ldc_I4_S: { Generation.Emit(conversion, stream, opCode, (sbyte)instructionDefinition.Operand); break; } case Libs.Mono.Cecil.Cil.Code.Ldc_I8: { Generation.Emit(conversion, stream, opCode, (long)instructionDefinition.Operand); break; } // Local Load - Push the local value at the location specified by the supplied short value onto the stack case Libs.Mono.Cecil.Cil.Code.Ldloc: case Libs.Mono.Cecil.Cil.Code.Ldloca: case Libs.Mono.Cecil.Cil.Code.Stloc: { if (instructionDefinition.Operand is VariableDefinition variable) { Generation.Emit(conversion, stream, opCode, (ushort)variable.Index); } else { Generation.Emit(conversion, stream, opCode, (ushort)instructionDefinition.Operand); } break; } // Local Load - Push the address of the local value at the location specified by the supplied byte value onto the stack case Libs.Mono.Cecil.Cil.Code.Ldloca_S: case Libs.Mono.Cecil.Cil.Code.Ldloc_S: case Libs.Mono.Cecil.Cil.Code.Stloc_S: { if (instructionDefinition.Operand is VariableDefinition variable) { Generation.Emit(conversion, stream, opCode, (byte)variable.Index); } else { Generation.Emit(conversion, stream, opCode, (byte)instructionDefinition.Operand); } break; } case Libs.Mono.Cecil.Cil.Code.Ldstr: { Generation.Emit(conversion, stream, opCode, (string)instructionDefinition.Operand); break; } case Libs.Mono.Cecil.Cil.Code.Ldc_R4: { Generation.Emit(conversion, stream, opCode, (float)instructionDefinition.Operand); break; } case Libs.Mono.Cecil.Cil.Code.Ldc_R8: { Generation.Emit(conversion, stream, opCode, (double)instructionDefinition.Operand); break; } case Libs.Mono.Cecil.Cil.Code.Unaligned: { Generation.Emit(conversion, stream, opCode, (byte)instructionDefinition.Operand); break; } case Libs.Mono.Cecil.Cil.Code.Callvirt: case Libs.Mono.Cecil.Cil.Code.Call: { var methodReference = (MethodReference)instructionDefinition.Operand; var declaringBound = Execution.Types.Ensuring.EnsureBound(conversion, methodReference.DeclaringType); if (declaringBound == null || (declaringBound is ConvertedTypeDefinition_I convertedType && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true))) { return(false); } if (!Members.GetMemberInfo(conversion, routine.DeclaringType, routine, declaringBound, methodReference, out MemberInfo memberInfo)) { return(false); } if (memberInfo is ConstructorInfo constructor) { Generation.Emit(conversion, stream, opCode, constructor); } else if (memberInfo is MethodInfo methodInfo) { Generation.Emit(conversion, stream, opCode, methodInfo); } else { throw new System.Exception("Not a constructor or method"); } break; } case Libs.Mono.Cecil.Cil.Code.Calli: { throw new System.NotSupportedException("Calli instruction not supported yet."); } case Libs.Mono.Cecil.Cil.Code.Jmp: case Libs.Mono.Cecil.Cil.Code.Ldftn: case Libs.Mono.Cecil.Cil.Code.Ldvirtftn: { var methodReference = (MethodReference)instructionDefinition.Operand; var declaringBound = Execution.Types.Ensuring.EnsureBound(conversion, methodReference.DeclaringType); if (declaringBound == null || (declaringBound is ConvertedTypeDefinition_I convertedType && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true))) { return(false); } if (!Members.GetMemberInfo(conversion, routine.DeclaringType, routine, declaringBound, methodReference, out MemberInfo memberInfo)) { throw new Exception("Could not find member."); } Generation.Emit(conversion, stream, opCode, (MethodInfo)memberInfo); break; } case Libs.Mono.Cecil.Cil.Code.Ldfld: case Libs.Mono.Cecil.Cil.Code.Ldflda: case Libs.Mono.Cecil.Cil.Code.Ldsfld: case Libs.Mono.Cecil.Cil.Code.Ldsflda: case Libs.Mono.Cecil.Cil.Code.Stfld: case Libs.Mono.Cecil.Cil.Code.Stsfld: { var fieldReference = (FieldReference)instructionDefinition.Operand; var declaringBound = Execution.Types.Ensuring.EnsureBound(conversion, fieldReference.DeclaringType); if (declaringBound == null || (declaringBound is ConvertedTypeDefinition_I convertedType && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true))) { return(false); } var fieldInfo = Models.Fields.ResolveFieldReference(conversion, routine.DeclaringType, declaringBound, fieldReference); Generation.Emit(conversion, stream, opCode, fieldInfo); break; } case Libs.Mono.Cecil.Cil.Code.Ldtoken: { var typeReference = instructionDefinition.Operand as TypeReference; System.Type resolvedType; if (typeReference is GenericParameter genericParameter) { if (!Instructions.GetGenericParameterType(conversion, routine.DeclaringType, routine, genericParameter, out resolvedType)) { return(false); } } else { var operandDeclaringType = Execution.Types.Ensuring.EnsureBound(conversion, typeReference); if (operandDeclaringType == null || (operandDeclaringType is ConvertedTypeDefinition_I convertedType && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true))) { return(false); } resolvedType = operandDeclaringType.UnderlyingType; } Generation.Emit(conversion, stream, opCode, resolvedType); break; } case Libs.Mono.Cecil.Cil.Code.Newobj: { var methodReference = (MethodReference)instructionDefinition.Operand; var operandDeclaringType = Execution.Types.Ensuring.EnsureBound(conversion, methodReference.DeclaringType); if (operandDeclaringType == null || (operandDeclaringType is ConvertedTypeDefinition_I convertedType && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true))) { return(false); } var found = Constructors.Getting.GetConstructor(conversion, routine.DeclaringType, operandDeclaringType, methodReference, out MemberInfo memberInfo); if (!found) { throw new Exception("Constructor not found. This needs to gracefully exit and comeback."); } if (memberInfo is ConstructorInfo constructorInfo) { Generation.Emit(conversion, stream, opCode, constructorInfo); } else if (memberInfo is MethodInfo methodInfo) { // Possible for multidimensional array creation Generation.Emit(conversion, stream, opCode, methodInfo); } else { throw new System.Exception("Not a constructor or method"); } break; } case Libs.Mono.Cecil.Cil.Code.Switch: { var instructions = (Instruction[])instructionDefinition.Operand; int[] offsets = new int[instructions.Length]; for (int i = 0; i < instructions.Length; i++) { var relativeOffsetModifier = (4 + 4 * instructions.Length + instructionDefinition.Offset + 1); offsets[i] = instructions[i].Offset - relativeOffsetModifier; } Generation.Emit(conversion, stream, opCode, offsets); break; } default: { //No = 214, throw new System.Exception($"Code {instructionDefinition.OpCode.Code.ToString()} not handled."); } } return(true); }
public byte[] GetLocalSignature(ILConversion conversion, ConvertedRoutine convertedRoutine) { return(LocalVariableSignatures.GetLocalSignature(conversion, convertedRoutine)); }
public bool GetGenericParameterType(ILConversion conversion, ConvertedTypeDefinitionMask_I input, ConvertedRoutine routine, GenericParameter genericParameter, out System.Type type) { switch (genericParameter.Type) { case GenericParameterType.Method: { var method = (ConvertedBuiltMethod)routine; var operandDeclaringType = method.DeclaringType; if ((operandDeclaringType is ConvertedTypeDefinition_I convertedType) && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true)) { type = null; return(false); } type = method.TypeParameters.Builders[genericParameter.Position]; return(true); } case GenericParameterType.Type: { var declaringType = genericParameter.DeclaringType; var boundType = Execution.Types.Ensuring.EnsureBound(conversion, declaringType); if ((boundType is ConvertedTypeDefinition_I convertedType) && Types.Building.CheckForPhase3Dependency(convertedType, (ConvertedTypeDefinition_I)routine.DeclaringType, true)) { type = null; return(false); } var x = (ConvertedTypeDefinitionWithTypeParameters_I)boundType; type = x.TypeParameters.Builders[genericParameter.Position]; return(true); } default: { throw new System.Exception("Not a method or a type."); } } }
public byte[] GetLocalSignature(ILConversion conversion, ConvertedRoutine routine) { ConvertedLocalVariableSignature signature = CreateLocalVariableSignature(conversion); throw new NotImplementedException(); }
public void Preprocess(ILConversion conversion, ConvertedRoutine routine) { if (routine.IsExceptionHandlingInfoPreprocessed) { return; } routine.IsExceptionHandlingInfoPreprocessed = true; routine.ExceptionHandlingInfo = new ExceptionHandlingInfo(); var handlingInfo = routine.ExceptionHandlingInfo; var methodDefinition = (MethodDefinition)routine.MethodReference; var methodDefinitionBody = methodDefinition.Body; if (!methodDefinitionBody.HasExceptionHandlers) { return; } foreach (var exceptionBlock in methodDefinitionBody.ExceptionHandlers) { switch (exceptionBlock.HandlerType) { case ExceptionHandlerType.Filter: { var filterBlock = new FilterBlock() { TryStartOffset = exceptionBlock.TryStart.Offset, TryEndOffset = exceptionBlock.TryEnd.Offset, HandlerEndOffset = exceptionBlock.HandlerEnd.Offset, FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1, ExceptionHandler = exceptionBlock }; handlingInfo.ExceptionBlocks.Add(filterBlock); AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, filterBlock); AddEvent(conversion, ExceptionBlockEventKind.Finally, handlingInfo, exceptionBlock.HandlerStart.Offset, filterBlock); AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, exceptionBlock.HandlerEnd.Offset, filterBlock); break; } case ExceptionHandlerType.Fault: { var faultBlock = new FaultBlock() { TryStartOffset = exceptionBlock.TryStart.Offset, TryEndOffset = exceptionBlock.TryEnd.Offset, HandlerEndOffset = exceptionBlock.HandlerEnd.Offset, FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1, ExceptionHandler = exceptionBlock }; handlingInfo.ExceptionBlocks.Add(faultBlock); AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, faultBlock); AddEvent(conversion, ExceptionBlockEventKind.Finally, handlingInfo, exceptionBlock.HandlerStart.Offset, faultBlock); AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, exceptionBlock.HandlerEnd.Offset, faultBlock); break; } case ExceptionHandlerType.Finally: { var finallyBlock = new TryFinallyBlock() { TryStartOffset = exceptionBlock.TryStart.Offset, TryEndOffset = exceptionBlock.TryEnd.Offset, HandlerEndOffset = exceptionBlock.HandlerEnd.Offset, FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1, ExceptionHandler = exceptionBlock }; handlingInfo.ExceptionBlocks.Add(finallyBlock); AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, finallyBlock); AddEvent(conversion, ExceptionBlockEventKind.Finally, handlingInfo, exceptionBlock.HandlerStart.Offset, finallyBlock); AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, exceptionBlock.HandlerEnd.Offset, finallyBlock); break; } case ExceptionHandlerType.Catch: { TryCatchBlock tryCatchBlock = null; for (int i = 0; i < handlingInfo.TryCatchEntries.Count; i++) { var x = handlingInfo.TryCatchEntries[i]; if (x.TryStartOffset == exceptionBlock.TryStart.Offset && x.TryEndOffset == exceptionBlock.TryEnd.Offset) { tryCatchBlock = x; } } if (tryCatchBlock == null) { tryCatchBlock = new TryCatchBlock() { // The first instruction that is included in the try catch block TryStartOffset = exceptionBlock.TryStart.Offset, // Gets the first instruction of the catch statement TryEndOffset = exceptionBlock.TryEnd.Offset, // Gets the first instruction that is outside of the catch statement HandlerEndOffset = exceptionBlock.HandlerEnd.Offset, FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1, HandlerEntries = new Dictionary <int, List <ExceptionHandler> >() }; handlingInfo.TryCatchEntries.Add(tryCatchBlock); handlingInfo.ExceptionBlocks.Add(tryCatchBlock); System.Diagnostics.Debug.WriteLine($"Try-Catch: BEGIN @ {exceptionBlock.TryStart.Offset.ToString("X2")}"); AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, tryCatchBlock); } if (!tryCatchBlock.HandlerEntries.TryGetValue(exceptionBlock.HandlerStart.Offset, out List <ExceptionHandler> list)) { list = new List <ExceptionHandler>(); tryCatchBlock.HandlerEntries.Add(exceptionBlock.HandlerStart.Offset, list); } list.Add(exceptionBlock); System.Diagnostics.Debug.WriteLine($"Try-Catch: CATCH @ {exceptionBlock.HandlerStart.Offset.ToString("X2")}"); AddEvent(conversion, ExceptionBlockEventKind.Catch, handlingInfo, exceptionBlock.HandlerStart.Offset, tryCatchBlock, exceptionBlock); break; } default: { throw new NotSupportedException(); } } } for (int i = 0; i < handlingInfo.TryCatchEntries.Count; i++) { var tryCatchBlock = handlingInfo.TryCatchEntries[i]; ExceptionHandler lastHandlerEntry = null; var handlerEntriesListList = tryCatchBlock.HandlerEntries.Values.ToList(); for (int j = 0; j < handlerEntriesListList.Count; j++) { var currentHandlerEntryList = handlerEntriesListList[j]; for (int k = 0; k < currentHandlerEntryList.Count; k++) { var currentHandlerEntry = currentHandlerEntryList[k]; if (lastHandlerEntry == null) { lastHandlerEntry = currentHandlerEntry; } else if (currentHandlerEntry.HandlerEnd.Offset > lastHandlerEntry.HandlerEnd.Offset) { lastHandlerEntry = currentHandlerEntry; } } } if (lastHandlerEntry == null) { continue; } System.Diagnostics.Debug.WriteLine($"Try-Catch: END CATCH @ {lastHandlerEntry.HandlerEnd.Offset.ToString("X2")}"); AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, lastHandlerEntry.HandlerEnd.Offset, tryCatchBlock); } }
public bool BuildBody(ILConversion conversion, ConvertedRoutine routine) { // If for some reason this is being called on a method that is not a method definition, then go ahead and mark it fully built // and return true, as there is nothing else to be done. // POSSIBLE ERROR CONDITION IN THE FUTURE. NEED TO SEE HOW INTERFACES DEFINITIONS ARE HANDLED. if (!routine.MethodReference.IsDefinition) { throw new System.Exception("The non-method definitions body is being emitted. This should not occur and should have been prevented " + "by the caller."); } if (routine.EmitState.Body == null) { routine.EmitState.Body = new ConvertedRoutineBodyEmitState(); } var bodyEmitState = routine.EmitState.Body; // If the body has already been fully built, then all the information is in the emit state. if (bodyEmitState.BodyFullyBuilt) { return(true); } var methodDefinition = (MethodDefinition)routine.MethodReference; // 1) Build the local variable signature. // This is an array of bytes that contain the serialized local variable // structure. Specify null if the method has no local variables. This method returns false // if a dependency is detected that is not yet been satisfied. if (!LocalVariableSignatures.GetLocalSignature(conversion, routine)) { // Dependency found that was not satisfied. return(false); } // 2) Build the IL Stream. This method returns false if a dependency is detected that is not yet // been satisfied. if (!IL.EmitILStream(conversion, routine)) { // Dependency found that was not satisfied. return(false); } // 3) Build the IL Stream. This method returns false if a dependency is detected that is not yet // been satisfied. if (!ExceptionHandling.GetExceptionHandlerList(conversion, routine)) { // Dependency found that was not satisfied. return(false); } // 4) Set max stack - This is put last in case the IL code ever computes the max stack size and cannot be determined // prior to IL emission. bodyEmitState.MaxStack = methodDefinition.Body.MaxStackSize; // Mark the methods body as fully built. bodyEmitState.BodyFullyBuilt = true; // Do unsatisfied dependencies were found. return(true); }
public void ProcessInstruction(ILConversion conversion, ConvertedRoutine routine, Instruction instruction) { var info = routine.ExceptionHandlingInfo; var ilGenerator = routine.IlGenerator; var methodReference = routine.MethodReference; if (!methodReference.IsDefinition) { return; } var methodDefintion = (MethodDefinition)methodReference; if (!methodDefintion.Body.HasExceptionHandlers) { return; } if (!info.Events.TryGetValue(instruction.Offset, out List <ExceptionBlockEventEntry> events)) { return; } foreach (var eventEntry in events) { switch (eventEntry.Kind) { case ExceptionBlockEventKind.Begin: { System.Diagnostics.Debug.WriteLine($"try @ {instruction.Offset.ToString("X2")}"); ilGenerator.BeginExceptionBlock(); break; } case ExceptionBlockEventKind.Catch: { System.Diagnostics.Debug.WriteLine($"catch @ {instruction.Offset.ToString("X2")}"); var typeReference = eventEntry.ExceptionHandler.CatchType; var declaringType = Execution.Types.Ensuring.EnsureToType(conversion, typeReference); ilGenerator.BeginCatchBlock(declaringType); break; } case ExceptionBlockEventKind.Finally: { System.Diagnostics.Debug.WriteLine($"finally @ {instruction.Offset.ToString("X2")}"); ilGenerator.BeginFinallyBlock(); break; } case ExceptionBlockEventKind.Fault: { ilGenerator.BeginFaultBlock(); break; } case ExceptionBlockEventKind.Filter: { ilGenerator.BeginExceptFilterBlock(); break; } case ExceptionBlockEventKind.EndBlock: { System.Diagnostics.Debug.WriteLine($"end @ {instruction.Offset.ToString("X2")}"); ilGenerator.EndExceptionBlock(); break; } } } }