void AddSZArraySig() { TypeSig = new SZArraySig(TypeSig); }
void WriteArrayValue(SZArraySig arrayType, IList<CAArgument> args) { if (arrayType == null) { helper.Error("Array type is null"); return; } if (args == null) writer.Write(uint.MaxValue); else { writer.Write((uint)args.Count); var arrayElementType = FixTypeSig(arrayType.Next); for (int i = 0; i < args.Count; i++) WriteValue(arrayElementType, args[i]); } }
TypeSig ResolveGenericArgs(TypeSig typeSig) { if (!recursionCounter.Increment()) { return(null); } if (ReplaceGenericArg(ref typeSig)) { recursionCounter.Decrement(); return(typeSig); } TypeSig result; switch (typeSig.ElementType) { case ElementType.Ptr: result = new PtrSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.ByRef: result = new ByRefSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.Var: result = new GenericVar((typeSig as GenericVar).Number); break; case ElementType.ValueArray: result = new ValueArraySig(ResolveGenericArgs(typeSig.Next), (typeSig as ValueArraySig).Size); break; case ElementType.SZArray: result = new SZArraySig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.MVar: result = new GenericMVar((typeSig as GenericMVar).Number); break; case ElementType.CModReqd: result = new CModReqdSig((typeSig as ModifierSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.CModOpt: result = new CModOptSig((typeSig as ModifierSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Module: result = new ModuleSig((typeSig as ModuleSig).Index, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Pinned: result = new PinnedSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.FnPtr: throw new NotSupportedException("FnPtr is not supported."); case ElementType.Array: var arraySig = (ArraySig)typeSig; var sizes = new List <uint>(arraySig.Sizes); var lbounds = new List <int>(arraySig.LowerBounds); result = new ArraySig(ResolveGenericArgs(typeSig.Next), arraySig.Rank, sizes, lbounds); break; case ElementType.GenericInst: var gis = (GenericInstSig)typeSig; var genArgs = new List <TypeSig>(gis.GenericArguments.Count); foreach (TypeSig ga in gis.GenericArguments) { genArgs.Add(ResolveGenericArgs(ga)); } result = new GenericInstSig(ResolveGenericArgs(gis.GenericType) as ClassOrValueTypeSig, genArgs); break; default: result = typeSig; break; } recursionCounter.Decrement(); return(result); }
public static TypeSig GetLoadedType(MethodDef method, IList <Instruction> instructions, int instrIndex, int argIndexFromEnd, out bool wasNewobj) { wasNewobj = false; var pushedArgs = MethodStack.GetPushedArgInstructions(instructions, instrIndex); var pushInstr = pushedArgs.GetEnd(argIndexFromEnd); if (pushInstr == null) { return(null); } TypeSig type; Local local; var corLibTypes = method.DeclaringType.Module.CorLibTypes; switch (pushInstr.OpCode.Code) { case Code.Ldstr: type = corLibTypes.String; break; case Code.Conv_I: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I_Un: type = corLibTypes.IntPtr; break; case Code.Conv_U: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U_Un: type = corLibTypes.UIntPtr; break; case Code.Conv_I8: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_I8_Un: type = corLibTypes.Int64; break; case Code.Conv_U8: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_U8_Un: type = corLibTypes.UInt64; break; case Code.Conv_R8: case Code.Ldc_R8: case Code.Ldelem_R8: case Code.Ldind_R8: type = corLibTypes.Double; break; case Code.Call: case Code.Calli: case Code.Callvirt: var calledMethod = pushInstr.Operand as IMethod; if (calledMethod == null) { return(null); } type = calledMethod.MethodSig.GetRetType(); break; case Code.Newarr: var type2 = pushInstr.Operand as ITypeDefOrRef; if (type2 == null) { return(null); } type = new SZArraySig(type2.ToTypeSig()); wasNewobj = true; break; case Code.Newobj: var ctor = pushInstr.Operand as IMethod; if (ctor == null) { return(null); } type = ctor.DeclaringType.ToTypeSig(); wasNewobj = true; break; case Code.Castclass: case Code.Isinst: case Code.Unbox_Any: case Code.Ldelem: case Code.Ldobj: type = (pushInstr.Operand as ITypeDefOrRef).ToTypeSig(); break; case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: type = pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType); break; case Code.Ldloc: case Code.Ldloc_S: case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: local = pushInstr.GetLocal(method.Body.Variables); if (local == null) { return(null); } type = local.Type.RemovePinned(); break; case Code.Ldloca: case Code.Ldloca_S: local = pushInstr.Operand as Local; if (local == null) { return(null); } type = CreateByRefType(local.Type.RemovePinned()); break; case Code.Ldarga: case Code.Ldarga_S: type = CreateByRefType(pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType)); break; case Code.Ldfld: case Code.Ldsfld: var field = pushInstr.Operand as IField; if (field == null || field.FieldSig == null) { return(null); } type = field.FieldSig.GetFieldType(); break; case Code.Ldflda: case Code.Ldsflda: var field2 = pushInstr.Operand as IField; if (field2 == null || field2.FieldSig == null) { return(null); } type = CreateByRefType(field2.FieldSig.GetFieldType()); break; case Code.Ldelema: case Code.Unbox: type = CreateByRefType(pushInstr.Operand as ITypeDefOrRef); break; default: return(null); } return(type); }
public static void WriteTo(this TypeSig type, ITextOutput writer, ILNameSyntax syntax, int depth) { if (depth++ > MAX_CONVERTTYPE_DEPTH) { return; } ILNameSyntax syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature; if (type is PinnedSig) { ((PinnedSig)type).Next.WriteTo(writer, syntaxForElementTypes, depth); writer.WriteSpace(); writer.Write("pinned", TextTokenType.Keyword); } else if (type is ArraySig) { ArraySig at = (ArraySig)type; at.Next.WriteTo(writer, syntaxForElementTypes, depth); writer.Write('[', TextTokenType.Operator); for (int i = 0; i < at.Rank; i++) { if (i != 0) { writer.Write(',', TextTokenType.Operator); writer.WriteSpace(); } int? lower = i < at.LowerBounds.Count ? at.LowerBounds[i] : (int?)null; uint?size = i < at.Sizes.Count ? at.Sizes[i] : (uint?)null; if (lower != null) { writer.Write(lower.ToString(), TextTokenType.Number); if (size != null) { writer.Write("..", TextTokenType.Operator); writer.Write((lower.Value + (int)size.Value - 1).ToString(), TextTokenType.Number); } else { writer.Write("...", TextTokenType.Operator); } } } writer.Write(']', TextTokenType.Operator); } else if (type is SZArraySig) { SZArraySig at = (SZArraySig)type; at.Next.WriteTo(writer, syntaxForElementTypes, depth); writer.Write("[]", TextTokenType.Operator); } else if (type is GenericSig) { if (((GenericSig)type).IsMethodVar) { writer.Write("!!", TextTokenType.Operator); } else { writer.Write("!", TextTokenType.Operator); } string typeName = type.TypeName; if (string.IsNullOrEmpty(typeName) || typeName[0] == '!' || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) { writer.Write(((GenericSig)type).Number.ToString(), TextTokenType.Number); } else { writer.Write(Escape(typeName), TextTokenHelper.GetTextTokenType(type)); } } else if (type is ByRefSig) { ((ByRefSig)type).Next.WriteTo(writer, syntaxForElementTypes, depth); writer.Write('&', TextTokenType.Operator); } else if (type is PtrSig) { ((PtrSig)type).Next.WriteTo(writer, syntaxForElementTypes, depth); writer.Write('*', TextTokenType.Operator); } else if (type is GenericInstSig) { ((GenericInstSig)type).GenericType.WriteTo(writer, syntaxForElementTypes, depth); writer.Write('<', TextTokenType.Operator); var arguments = ((GenericInstSig)type).GenericArguments; for (int i = 0; i < arguments.Count; i++) { if (i > 0) { writer.Write(',', TextTokenType.Operator); writer.WriteSpace(); } arguments[i].WriteTo(writer, syntaxForElementTypes, depth); } writer.Write('>', TextTokenType.Operator); } else if (type is CModOptSig) { ((ModifierSig)type).Next.WriteTo(writer, syntax, depth); writer.WriteSpace(); writer.Write("modopt", TextTokenType.Keyword); writer.Write('(', TextTokenType.Operator); ((ModifierSig)type).Modifier.WriteTo(writer, ILNameSyntax.TypeName, depth); writer.Write(')', TextTokenType.Operator); writer.WriteSpace(); } else if (type is CModReqdSig) { ((ModifierSig)type).Next.WriteTo(writer, syntax, depth); writer.WriteSpace(); writer.Write("modreq", TextTokenType.Keyword); writer.Write('(', TextTokenType.Operator); ((ModifierSig)type).Modifier.WriteTo(writer, ILNameSyntax.TypeName, depth); writer.Write(')', TextTokenType.Operator); writer.WriteSpace(); } else if (type is TypeDefOrRefSig) { WriteTo(((TypeDefOrRefSig)type).TypeDefOrRef, writer, syntax, depth); } else if (type is FnPtrSig) { WriteTo(type.ToTypeDefOrRef(), writer, syntax, depth); } //TODO: SentinelSig }
TypeSig?ResolveGenericArgs(TypeSig typeSig) { if (typeSig is null) { return(null); } if (!recursionCounter.Increment()) { return(null); } if (ReplaceGenericArg(ref typeSig)) { recursionCounter.Decrement(); return(typeSig); } TypeSig result; switch (typeSig.ElementType) { case ElementType.Ptr: result = new PtrSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.ByRef: result = new ByRefSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.Var: result = new GenericVar(((GenericVar)typeSig).Number, ((GenericVar)typeSig).OwnerType); break; case ElementType.ValueArray: result = new ValueArraySig(ResolveGenericArgs(typeSig.Next), ((ValueArraySig)typeSig).Size); break; case ElementType.SZArray: result = new SZArraySig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.MVar: result = new GenericMVar(((GenericMVar)typeSig).Number, ((GenericMVar)typeSig).OwnerMethod); break; case ElementType.CModReqd: result = new CModReqdSig(((ModifierSig)typeSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.CModOpt: result = new CModOptSig(((ModifierSig)typeSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Module: result = new ModuleSig(((ModuleSig)typeSig).Index, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Pinned: result = new PinnedSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.FnPtr: result = new FnPtrSig(ResolveGenericArgs(((FnPtrSig)typeSig).MethodSig)); break; case ElementType.Array: ArraySig arraySig = (ArraySig)typeSig; List <uint> sizes = new List <uint>(arraySig.Sizes); List <int> lbounds = new List <int>(arraySig.LowerBounds); result = new ArraySig(ResolveGenericArgs(typeSig.Next), arraySig.Rank, sizes, lbounds); break; case ElementType.GenericInst: GenericInstSig gis = (GenericInstSig)typeSig; List <TypeSig?> genArgs = new List <TypeSig?>(gis.GenericArguments.Count); foreach (TypeSig ga in gis.GenericArguments) { genArgs.Add(ResolveGenericArgs(ga)); } result = new GenericInstSig(ResolveGenericArgs(gis.GenericType as TypeSig) as ClassOrValueTypeSig, genArgs); break; default: result = typeSig; break; } recursionCounter.Decrement(); return(result); }
static void AppendTypeName(StringBuilder b, TypeSig type) { if (type == null) { // could happen when a TypeSpecification has no ElementType; e.g. function pointers in C++/CLI assemblies return; } if (type is GenericInstSig) { GenericInstSig giType = (GenericInstSig)type; AppendTypeNameWithArguments(b, giType.GenericType.TypeDefOrRef, giType.GenericArguments); return; } SZArraySig arrayType = type as SZArraySig; // TODO: multi-dimensional array if (arrayType != null) { AppendTypeName(b, arrayType.Next); b.Append("[]"); } ByRefSig refType = type as ByRefSig; if (refType != null) { AppendTypeName(b, refType.Next); b.Append('@'); } PtrSig ptrType = type as PtrSig; if (ptrType != null) { AppendTypeName(b, ptrType.Next); b.Append('*'); } GenericSig gp = type as GenericSig; if (gp != null) { b.Append('`'); if (gp.IsMethodVar) { b.Append('`'); } b.Append(gp.Number); } else { var typeRef = type.ToTypeDefOrRef(); var declType = Decompiler.DnlibExtensions.GetDeclaringType(typeRef); if (declType != null) { AppendTypeName(b, declType.ToTypeSig()); b.Append('.'); b.Append(typeRef.Name); } else { b.Append(type.FullName); } } }
// TODO: multi-dimensional array #region Array Initializers bool TransformArrayInitializers(List <ILNode> body, ILExpression expr, int pos) { ILVariable v, v3; ILExpression newarrExpr; ITypeDefOrRef elementType; ILExpression lengthExpr; int arrayLength; if (expr.Match(ILCode.Stloc, out v, out newarrExpr) && newarrExpr.Match(ILCode.Newarr, out elementType, out lengthExpr) && lengthExpr.Match(ILCode.Ldc_I4, out arrayLength) && arrayLength > 0) { ILExpression[] newArr; int initArrayPos; if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType.ToTypeSig(), arrayLength, out newArr, out initArrayPos)) { var arrayType = new SZArraySig(elementType.ToTypeSig()); //arrayType.Dimensions[0] = new ArrayDimension(0, arrayLength); body[pos] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr)); body.RemoveAt(initArrayPos); } // Put in a limit so that we don't consume too much memory if the code allocates a huge array // and populates it extremely sparsly. However, 255 "null" elements in a row actually occur in the Mono C# compiler! const int maxConsecutiveDefaultValueExpressions = 300; List <ILExpression> operands = new List <ILExpression>(); int numberOfInstructionsToRemove = 0; for (int j = pos + 1; j < body.Count; j++) { ILExpression nextExpr = body[j] as ILExpression; int arrayPos; if (nextExpr != null && nextExpr.Code.IsStoreToArray() && nextExpr.Arguments[0].Match(ILCode.Ldloc, out v3) && v == v3 && nextExpr.Arguments[1].Match(ILCode.Ldc_I4, out arrayPos) && arrayPos >= operands.Count && arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions && !nextExpr.Arguments[2].ContainsReferenceTo(v3)) { while (operands.Count < arrayPos) { operands.Add(new ILExpression(ILCode.DefaultValue, elementType)); } operands.Add(nextExpr.Arguments[2]); numberOfInstructionsToRemove++; } else { break; } } if (operands.Count == arrayLength) { var arrayType = new SZArraySig(elementType.ToTypeSig()); //arrayType.Dimensions[0] = new ArrayDimension(0, arrayLength); expr.Arguments[0] = new ILExpression(ILCode.InitArray, arrayType.ToTypeDefOrRef(), operands); body.RemoveRange(pos + 1, numberOfInstructionsToRemove); new ILInlining(method).InlineIfPossible(body, ref pos); return(true); } } return(false); }
void AddSZArraySig() => TypeSig = new SZArraySig(TypeSig);
TypeSig Create2(TypeSig type) { if (type == null) { return(type); } TypeSig result; GenericSig varSig; switch (type.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = type; break; case ElementType.Ptr: result = new PtrSig(Create2(type.Next)); break; case ElementType.ByRef: result = new ByRefSig(Create2(type.Next)); break; case ElementType.Array: var ary = (ArraySig)type; result = new ArraySig(ary.Next, ary.Rank, ary.Sizes, ary.LowerBounds); break; case ElementType.SZArray: result = new SZArraySig(Create2(type.Next)); break; case ElementType.Pinned: result = new PinnedSig(Create2(type.Next)); break; case ElementType.ValueType: case ElementType.Class: result = type; break; case ElementType.Var: varSig = (GenericSig)type; if (genericArgs != null && varSig.Number < (uint)genericArgs.Count) { result = genericArgs[(int)varSig.Number]; updated = true; } else { result = type; } break; case ElementType.MVar: varSig = (GenericSig)type; if (genericMethodArgs != null && varSig.Number < (uint)genericMethodArgs.Count) { result = genericMethodArgs[(int)varSig.Number]; updated = true; } else { result = type; } break; case ElementType.GenericInst: var gis = (GenericInstSig)type; var newGis = new GenericInstSig(Create2(gis.GenericType) as ClassOrValueTypeSig, gis.GenericArguments.Count); for (int i = 0; i < gis.GenericArguments.Count; i++) { newGis.GenericArguments.Add(Create2(gis.GenericArguments[i])); } result = newGis; break; case ElementType.ValueArray: result = new ValueArraySig(type.Next, ((ValueArraySig)type).Size); break; case ElementType.Module: result = new ModuleSig(((ModuleSig)type).Index, type.Next); break; case ElementType.CModReqd: result = new CModReqdSig(((ModifierSig)type).Modifier, type.Next); break; case ElementType.CModOpt: result = new CModOptSig(((ModifierSig)type).Modifier, type.Next); break; case ElementType.FnPtr: result = new FnPtrSig(Create(((FnPtrSig)type).MethodSig)); break; case ElementType.End: case ElementType.R: case ElementType.Sentinel: case ElementType.Internal: default: result = type; break; } return(result); }
private MosaInstruction ResolveInstruction(MethodDef methodDef, CilBody body, int index, GenericArgumentResolver resolver) { var instruction = body.Instructions[index]; int?prev = index == 0 ? null : (int?)body.Instructions[index - 1].Offset; int?next = index == body.Instructions.Count - 1 ? null : (int?)body.Instructions[index + 1].Offset; object operand = instruction.Operand; // Special case: newarr instructions need to have their operand changed now so that the type is a SZArray if (instruction.OpCode == OpCodes.Newarr) { var typeSig = resolver.Resolve(((ITypeDefOrRef)instruction.Operand).ToTypeSig()); var szArraySig = new SZArraySig(typeSig); operand = metadata.Loader.GetType(szArraySig); } else if (instruction.Operand is ITypeDefOrRef) { operand = ResolveTypeOperand((ITypeDefOrRef)instruction.Operand, resolver); } else if (instruction.Operand is MemberRef memberRef) { if (memberRef.IsFieldRef) { operand = ResolveFieldOperand(memberRef, resolver); } else { operand = ResolveMethodOperand(memberRef, resolver); } } else if (instruction.Operand is IField) { operand = ResolveFieldOperand((IField)instruction.Operand, resolver); } else if (instruction.Operand is IMethod) { operand = ResolveMethodOperand((IMethod)instruction.Operand, resolver); } else if (instruction.Operand is Local) { operand = ((Local)instruction.Operand).Index; } else if (instruction.Operand is Parameter) { operand = ((Parameter)instruction.Operand).Index; } else if (instruction.Operand is Instruction) { operand = (int)((Instruction)instruction.Operand).Offset; } else if (instruction.Operand is Instruction[] targets) { var offsets = new int[targets.Length]; for (int i = 0; i < offsets.Length; i++) { offsets[i] = (int)targets[i].Offset; } operand = offsets; } else if (instruction.Operand is string) { operand = metadata.Cache.GetStringId((string)instruction.Operand); } ushort code = (ushort)instruction.OpCode.Code; if (code > 0xff) // To match compiler's opcode values { code = (ushort)(0x100 + (code & 0xff)); } return(new MosaInstruction() { Offset = (int)instruction.Offset, OpCode = code, Operand = operand, Previous = prev, Next = next, Document = instruction.SequencePoint?.Document.Url, StartLine = instruction.SequencePoint?.StartLine ?? 0, StartColumn = instruction.SequencePoint?.StartColumn ?? 0, EndLine = instruction.SequencePoint?.EndLine ?? 0, EndColumn = instruction.SequencePoint?.EndColumn ?? 0, }); }
private static void Transform(ILASTExpression expr, ModuleDef module) { switch (expr.ILCode) { case Code.Ldlen: { expr.ILCode = Code.Call; var array = module.CorLibTypes.GetTypeRef("System", "Array"); var lenSig = MethodSig.CreateInstance(module.CorLibTypes.Int32); var methodRef = new MemberRefUser(module, "get_Length", lenSig, array); expr.Operand = methodRef; break; } case Code.Newarr: { expr.ILCode = Code.Newobj; var array = new SZArraySig(((ITypeDefOrRef)expr.Operand).ToTypeSig()).ToTypeDefOrRef(); var ctorSig = MethodSig.CreateInstance(module.CorLibTypes.Void, module.CorLibTypes.Int32); var ctorRef = new MemberRefUser(module, ".ctor", ctorSig, array); expr.Operand = ctorRef; break; } case Code.Ldelema: { expr.ILCode = Code.Call; var elemType = ((ITypeDefOrRef)expr.Operand).ToTypeSig(); var array = new SZArraySig(elemType).ToTypeDefOrRef(); var addrSig = MethodSig.CreateInstance(new ByRefSig(elemType), module.CorLibTypes.Int32); var addrRef = new MemberRefUser(module, "Address", addrSig, array); expr.Operand = addrRef; break; } case Code.Ldelem: TransformLDELEM(expr, module, (ITypeDefOrRef)expr.Operand); break; case Code.Ldelem_I1: TransformLDELEM(expr, module, module.CorLibTypes.SByte.ToTypeDefOrRef()); break; case Code.Ldelem_U1: TransformLDELEM(expr, module, module.CorLibTypes.Byte.ToTypeDefOrRef()); break; case Code.Ldelem_I2: TransformLDELEM(expr, module, module.CorLibTypes.Int16.ToTypeDefOrRef()); break; case Code.Ldelem_U2: TransformLDELEM(expr, module, module.CorLibTypes.UInt16.ToTypeDefOrRef()); break; case Code.Ldelem_I4: TransformLDELEM(expr, module, module.CorLibTypes.Int32.ToTypeDefOrRef()); break; case Code.Ldelem_U4: TransformLDELEM(expr, module, module.CorLibTypes.UInt32.ToTypeDefOrRef()); break; case Code.Ldelem_I8: TransformLDELEM(expr, module, module.CorLibTypes.Int64.ToTypeDefOrRef()); break; case Code.Ldelem_R4: TransformLDELEM(expr, module, module.CorLibTypes.Single.ToTypeDefOrRef()); break; case Code.Ldelem_R8: TransformLDELEM(expr, module, module.CorLibTypes.Double.ToTypeDefOrRef()); break; case Code.Ldelem_I: TransformLDELEM(expr, module, module.CorLibTypes.IntPtr.ToTypeDefOrRef()); break; case Code.Ldelem_Ref: TransformLDELEM(expr, module, module.CorLibTypes.Object.ToTypeDefOrRef()); break; } }
/// <summary> /// Reads the next type /// </summary> /// <returns>A new <see cref="TypeSig"/> instance or <c>null</c> if invalid element type</returns> private TypeSig ReadType() { if (!recursionCounter.Increment()) { return(null); } uint num; TypeSig nextType, result = null; switch ((ElementType)reader.ReadByte()) { case ElementType.Void: result = corLibTypes.Void; break; case ElementType.Boolean: result = corLibTypes.Boolean; break; case ElementType.Char: result = corLibTypes.Char; break; case ElementType.I1: result = corLibTypes.SByte; break; case ElementType.U1: result = corLibTypes.Byte; break; case ElementType.I2: result = corLibTypes.Int16; break; case ElementType.U2: result = corLibTypes.UInt16; break; case ElementType.I4: result = corLibTypes.Int32; break; case ElementType.U4: result = corLibTypes.UInt32; break; case ElementType.I8: result = corLibTypes.Int64; break; case ElementType.U8: result = corLibTypes.UInt64; break; case ElementType.R4: result = corLibTypes.Single; break; case ElementType.R8: result = corLibTypes.Double; break; case ElementType.String: result = corLibTypes.String; break; case ElementType.TypedByRef: result = corLibTypes.TypedReference; break; case ElementType.I: result = corLibTypes.IntPtr; break; case ElementType.U: result = corLibTypes.UIntPtr; break; case ElementType.Object: result = corLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(ReadType()); break; case ElementType.ByRef: result = new ByRefSig(ReadType()); break; case ElementType.ValueType: result = new ValueTypeSig(ReadTypeDefOrRef()); break; case ElementType.Class: result = new ClassSig(ReadTypeDefOrRef()); break; case ElementType.FnPtr: result = new FnPtrSig(ReadSig()); break; case ElementType.SZArray: result = new SZArraySig(ReadType()); break; case ElementType.CModReqd: result = new CModReqdSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.CModOpt: result = new CModOptSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(ReadType()); break; case ElementType.Var: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new GenericVar(num, gpContext.Type); break; case ElementType.MVar: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new GenericMVar(num, gpContext.Method); break; case ElementType.ValueArray: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) { break; } result = new ValueArraySig(nextType, num); break; case ElementType.Module: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new ModuleSig(num, ReadType()); break; case ElementType.GenericInst: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) { break; } var genericInstSig = new GenericInstSig(nextType as ClassOrValueTypeSig, num); var args = genericInstSig.GenericArguments; for (uint i = 0; i < num; i++) { args.Add(ReadType()); } result = genericInstSig; break; case ElementType.Array: nextType = ReadType(); uint rank; if (!reader.ReadCompressedUInt32(out rank)) { break; } if (rank == 0) { result = new ArraySig(nextType, rank); break; } if (!reader.ReadCompressedUInt32(out num)) { break; } var sizes = new List <uint>((int)num); for (uint i = 0; i < num; i++) { uint size; if (!reader.ReadCompressedUInt32(out size)) { goto exit; } sizes.Add(size); } if (!reader.ReadCompressedUInt32(out num)) { break; } var lowerBounds = new List <int>((int)num); for (uint i = 0; i < num; i++) { int size; if (!reader.ReadCompressedInt32(out size)) { goto exit; } lowerBounds.Add(size); } result = new ArraySig(nextType, rank, sizes, lowerBounds); break; case ElementType.Internal: IntPtr address; if (IntPtr.Size == 4) { address = new IntPtr(reader.ReadInt32()); } else { address = new IntPtr(reader.ReadInt64()); } result = helper.ConvertRTInternalAddress(address); break; case ElementType.End: case ElementType.R: default: result = null; break; } exit: recursionCounter.Decrement(); return(result); }