private void SerializeExceptionRegions(MethodBody body) { // Get exception clauses, quit if none var clauses = body.ExceptionHandlingClauses; if (clauses.Count == 0) { return; } // Can we use a small exception table? var useSmallTable = HasSmallExceptionRegions(body.ExceptionHandlingClauses); // Align to 4 byte boundary var exre = ExceptionRegionEncoder.SerializeTableHeader(_metadata.ILBuilder, clauses.Count, useSmallTable); foreach (var ex in body.ExceptionHandlingClauses) { exre.Add((ExceptionRegionKind)ex.Flags, ex.TryOffset, ex.TryLength, ex.HandlerOffset, ex.HandlerLength, ex.Flags == ExceptionHandlingClauseOptions.Clause ? _metadata.GetTypeHandle(ex.CatchType) : default(EntityHandle), ex.Flags == ExceptionHandlingClauseOptions.Filter ? ex.FilterOffset : 0); } }
internal static void FromSystemType(this SignatureTypeEncoder typeEncoder, Type type, IAssemblyMetadata metadata) { if (type.IsByRef) { throw new ArgumentException("ByRef types should be handled by parameter encoder or return type encoder"); } else if (type.IsPointer) { typeEncoder.Pointer().FromSystemType(type.GetElementType(), metadata); } else if (type.IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type)); } else if (type == typeof(string)) { typeEncoder.String(); } else if (type == typeof(object)) { typeEncoder.Object(); } else if (type == typeof(void)) { throw new ArgumentException( "Void type is not allowed in SignatureTypeEncoder. Please, use FromSystemType from ReturnTypeEncoder.", nameof(type)); } else if (type.IsArray) { var elementType = type.GetElementType(); if (type.GetArrayRank() == 1) { typeEncoder.SZArray().FromSystemType(elementType, metadata); } else { typeEncoder.Array( x => x.FromSystemType(elementType, metadata), x => x.Shape( type.GetArrayRank(), ImmutableArray.Create <int>(), ImmutableArray.CreateRange <int>(Enumerable.Repeat(0, type.GetArrayRank())) // better matches metadata from C# )); } } else if (type.IsGenericType) { var genericTypeDef = type.GetGenericTypeDefinition(); var typeHandler = metadata.GetTypeHandle(genericTypeDef); var genericArguments = type.GetGenericArguments(); var inst = typeEncoder.GenericInstantiation(typeHandler, genericArguments.Length, type.IsValueType); foreach (var ga in genericArguments) { if (ga.IsGenericParameter) { inst.AddArgument().GenericTypeParameter(ga.GenericParameterPosition); } else { inst.AddArgument().FromSystemType(ga, metadata); } } } else if (type.IsGenericMethodParameter()) { typeEncoder.GenericMethodTypeParameter(type.GenericParameterPosition); } else if (type.IsGenericParameter) { typeEncoder.GenericTypeParameter(type.GenericParameterPosition); } else { var typeHandler = metadata.GetTypeHandle(type); typeEncoder.Type(typeHandler, type.IsValueType); } }
public static void Write(IAssemblyMetadata metadata, IReadOnlyList <Instruction> il) { for (var i = 0; i < il.Count; i++) { var opCode = il[i].OpCode; opCode.WriteOpCode(metadata.ILBuilder.WriteByte); switch (opCode.OperandType) { case OperandType.InlineNone: break; case OperandType.InlineSwitch: var branches = (int[])il[i].Operand; metadata.ILBuilder.WriteInt32(branches.Length); for (var k = 0; k < branches.Length; k++) { var branchOffset = branches[k]; metadata.ILBuilder.WriteInt32(branchOffset); } break; case OperandType.ShortInlineBrTarget: var offset8 = (sbyte)il[i].Operand; metadata.ILBuilder.WriteSByte(offset8); break; case OperandType.InlineBrTarget: var offset32 = (int)il[i].Operand; // offset convention in IL: zero is at next instruction metadata.ILBuilder.WriteInt32(offset32); break; case OperandType.ShortInlineI: if (opCode == OpCodes.Ldc_I4_S) { metadata.ILBuilder.WriteSByte((sbyte)il[i].Operand); } else { metadata.ILBuilder.WriteByte((byte)il[i].Operand); } break; case OperandType.InlineI: metadata.ILBuilder.WriteInt32((int)il[i].Operand); break; case OperandType.ShortInlineR: metadata.ILBuilder.WriteSingle((float)il[i].Operand); break; case OperandType.InlineR: metadata.ILBuilder.WriteDouble((double)il[i].Operand); break; case OperandType.InlineI8: metadata.ILBuilder.WriteInt64((long)il[i].Operand); break; case OperandType.InlineSig: metadata.ILBuilder.WriteBytes((byte[])il[i].Operand); break; case OperandType.InlineString: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetOrAddUserString((string)il[i].Operand))); break; case OperandType.InlineType: case OperandType.InlineTok: case OperandType.InlineMethod: case OperandType.InlineField: switch (il[i].Operand) { case Type type: metadata.ILBuilder.WriteInt32(MetadataTokens.GetToken(metadata.GetTypeHandle(type))); break; case ConstructorInfo constructorInfo: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetConstructorHandle(constructorInfo))); break; case FieldInfo fieldInfo: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetFieldHandle(fieldInfo))); break; case MethodInfo methodInfo: metadata.ILBuilder.WriteInt32( MetadataTokens.GetToken(metadata.GetMethodHandle(methodInfo))); break; default: throw new NotSupportedException($"Unsupported inline operand: {il[i].Operand}"); } break; case OperandType.ShortInlineVar: var bLocalVariableInfo = il[i].Operand as LocalVariableInfo; var bParameterInfo = il[i].Operand as ParameterInfo; if (bLocalVariableInfo != null) { metadata.ILBuilder.WriteByte((byte)bLocalVariableInfo.LocalIndex); } else if (bParameterInfo != null) { metadata.ILBuilder.WriteByte((byte)bParameterInfo.Position); } else { throw new NotSupportedException($"Unsupported short inline variable: {il[i].Operand}"); } break; case OperandType.InlineVar: var sLocalVariableInfo = il[i].Operand as LocalVariableInfo; var sParameterInfo = il[i].Operand as ParameterInfo; if (sLocalVariableInfo != null) { metadata.ILBuilder.WriteUInt16((ushort)sLocalVariableInfo.LocalIndex); } else if (sParameterInfo != null) { metadata.ILBuilder.WriteUInt16((ushort)sParameterInfo.Position); } else { throw new NotSupportedException($"Unsupported inline variable: {il[i].Operand}"); } break; default: throw new NotSupportedException($"Unsupported operand type: {opCode.OperandType}"); } } }
internal static void FromSystemType(this SignatureTypeEncoder typeEncoder, Type type, IAssemblyMetadata metadata) { if (type.IsByRef && type.GetElementType().IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type.GetElementType())); } else if (type.IsPrimitive) { typeEncoder.PrimitiveType(GetPrimitiveTypeCode(type)); } else if (type == typeof(string)) { typeEncoder.String(); } else if (type == typeof(object)) { typeEncoder.Object(); } else if (type == typeof(void)) { throw new ArgumentException( "Void type is not allowed in SignatureTypeEncoder. Please, use FromSystemType from ReturnTypeEncoder.", nameof(type)); } else if (type.IsArray) { var elementType = type.GetElementType(); typeEncoder.Array( x => x.FromSystemType(elementType, metadata), x => x.Shape( type.GetArrayRank(), ImmutableArray.Create <int>(), ImmutableArray.Create <int>())); } else if (type.IsGenericType) { var genericTypeDef = type.GetGenericTypeDefinition(); var typeHandler = metadata.GetTypeHandle(genericTypeDef); var genericArguments = type.GetGenericArguments(); var inst = typeEncoder.GenericInstantiation(typeHandler, genericArguments.Length, false); foreach (var ga in genericArguments) { if (ga.IsGenericParameter) { inst.AddArgument().GenericTypeParameter(ga.GenericParameterPosition); } else { inst.AddArgument().FromSystemType(ga, metadata); } } } else { var typeHandler = metadata.GetTypeHandle(type); typeEncoder.Type(typeHandler, type.IsValueType); } }