/// <summary> /// Relocates the <see cref="TypeSig"/>. /// </summary> /// <param name="typeSig">The type sig.</param> /// <returns>A new type if it was relocated, null otherwise</returns> /// <exception cref="InvalidOperationException">If signature is of unknown type.</exception> public virtual TypeSig TryRelocateTypeSig(TypeSig typeSig) { if (typeSig == null) return null; if (typeSig is CorLibTypeSig) return null; if (typeSig is GenericInstSig) return TryRelocateGeneric((GenericInstSig)typeSig); if (typeSig is PtrSig) return null; if (typeSig is ByRefSig) return TryRelocateByRef((ByRefSig)typeSig); if (typeSig is ArraySig) return TryRelocateArray((ArraySig)typeSig); if (typeSig is SZArraySig) return TryRelocateSZArray((SZArraySig)typeSig); if (typeSig is GenericVar) return null; // TODO constraints if (typeSig is GenericMVar) return null; // TODO constraints if (typeSig is ValueTypeSig || typeSig is ClassSig) { var typeRef = typeSig.TryGetTypeRef(); if (typeRef != null) return TryRelocateTypeRef(typeRef); var typeDefOrRef = TryRelocateTypeDefOrRef(typeSig.ToTypeDefOrRef()); return typeDefOrRef?.ToTypeSig(); } throw new InvalidOperationException(); }
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 == null ? null : giType.GenericType.TypeDefOrRef, giType.GenericArguments); return; } ArraySigBase arrayType = type as ArraySigBase; if (arrayType != null) { AppendTypeName(b, arrayType.Next); b.Append('['); var lowerBounds = arrayType.GetLowerBounds(); var sizes = arrayType.GetSizes(); for (int i = 0; i < arrayType.Rank; i++) { if (i > 0) b.Append(','); if (i < lowerBounds.Count && i < sizes.Count) { b.Append(lowerBounds[i]); b.Append(':'); b.Append(sizes[i] + lowerBounds[i] - 1); } } b.Append(']'); return; } ByRefSig refType = type as ByRefSig; if (refType != null) { AppendTypeName(b, refType.Next); b.Append('@'); return; } PtrSig ptrType = type as PtrSig; if (ptrType != null) { AppendTypeName(b, ptrType.Next); b.Append('*'); return; } GenericSig gp = type as GenericSig; if (gp != null) { b.Append('`'); if (gp.IsMethodVar) { b.Append('`'); } b.Append(gp.Number); } else { var typeRef = type.ToTypeDefOrRef(); if (typeRef.DeclaringType != null) { AppendTypeName(b, typeRef.DeclaringType.ToTypeSig()); b.Append('.'); b.Append(typeRef.Name); } else { b.Append(type.FullName); } } }
MEventDef CreateEvent(MTypeDef ownerType, string name, TypeSig eventType) { if (string.IsNullOrEmpty(name) || eventType == null || eventType.ElementType == ElementType.Void) return null; var newEvent = ownerType.Module.ModuleDefMD.UpdateRowId(new EventDefUser(name, eventType.ToTypeDefOrRef(), 0)); var eventDef = ownerType.FindAny(newEvent); if (eventDef != null) return eventDef; eventDef = ownerType.Create(newEvent); memberInfos.Add(eventDef); if (isVerbose) Logger.v("Restoring event: {0}", Utils.RemoveNewlines(newEvent)); return eventDef; }
Ast.Expression Convert(Ast.Expression expr, TypeSig actualType, TypeSig reqType) { if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) { return expr; } else if (actualType is ByRefSig && reqType is PtrSig && expr is DirectionExpression) { return Convert( new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()), new PtrSig(((ByRefSig)actualType).Next), reqType); } else if (actualType is PtrSig && reqType is ByRefSig) { expr = Convert(expr, actualType, new PtrSig(((ByRefSig)reqType).Next)); return new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr) }; } else if (actualType is PtrSig && reqType is PtrSig) { if (actualType.FullName != reqType.FullName) return expr.CastTo(AstBuilder.ConvertType(reqType)); else return expr; } else { bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType); bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType); if (reqType.GetElementType() == ElementType.Boolean) { if (actualType.GetElementType() == ElementType.Boolean) return expr; if (actualIsIntegerOrEnum) { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType.ToTypeDefOrRef())); } else { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); } } if (actualType.GetElementType() == ElementType.Boolean && requiredIsIntegerOrEnum) { return new ConditionalExpression { Condition = expr, TrueExpression = AstBuilder.MakePrimitive(1, reqType.ToTypeDefOrRef()), FalseExpression = AstBuilder.MakePrimitive(0, reqType.ToTypeDefOrRef()) }; } if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType)) { return expr.CastTo(AstBuilder.ConvertType(actualType)); } bool actualIsPrimitiveType = actualIsIntegerOrEnum || actualType.GetElementType() == ElementType.R4 || actualType.GetElementType() == ElementType.R8; bool requiredIsPrimitiveType = requiredIsIntegerOrEnum || reqType.GetElementType() == ElementType.R4 || reqType.GetElementType() == ElementType.R8; if (actualIsPrimitiveType && requiredIsPrimitiveType) { return expr.CastTo(AstBuilder.ConvertType(reqType)); } return expr; } }
Expression MakeDefaultValue(TypeSig type) { TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef(); if (typeDef != null) { if (TypeAnalysis.IsIntegerOrEnum(type)) return AstBuilder.MakePrimitive(0, type); else if (!typeDef.IsValueType) return new NullReferenceExpression(); switch (typeDef.FullName) { case "System.Nullable`1": return new NullReferenceExpression(); case "System.Single": return new PrimitiveExpression(0f); case "System.Double": return new PrimitiveExpression(0.0); case "System.Decimal": return new PrimitiveExpression(0m); } } return new DefaultValueExpression { Type = AstBuilder.ConvertType(type) }; }
static void AppendTypeName(StringBuilder b, TypeSig type) { if (type == null) return; if (type is GenericInstSig) { GenericInstSig giType = (GenericInstSig)type; AppendTypeNameWithArguments(b, giType.GenericType == null ? null : giType.GenericType.TypeDefOrRef, giType.GenericArguments); return; } ArraySigBase arrayType = type as ArraySigBase; if (arrayType != null) { AppendTypeName(b, arrayType.Next); b.Append('['); var lowerBounds = arrayType.GetLowerBounds(); var sizes = arrayType.GetSizes(); for (int i = 0; i < arrayType.Rank; i++) { if (i > 0) b.Append(','); if (i < lowerBounds.Count && i < sizes.Count) { b.Append(lowerBounds[i]); b.Append(':'); b.Append(sizes[i] + lowerBounds[i] - 1); } } b.Append(']'); return; } ByRefSig refType = type as ByRefSig; if (refType != null) { AppendTypeName(b, refType.Next); b.Append('@'); return; } PtrSig ptrType = type as PtrSig; if (ptrType != null) { AppendTypeName(b, ptrType.Next); b.Append('*'); return; } GenericSig gp = type as GenericSig; if (gp != null) { b.Append('`'); if (gp.IsMethodVar) { b.Append('`'); } b.Append(gp.Number); } else { var typeRef = type.ToTypeDefOrRef(); if (typeRef.DeclaringType != null) { AppendTypeName(b, typeRef.DeclaringType.ToTypeSig()); b.Append('.'); b.Append(typeRef.Name); } else { FullNameCreator.FullNameSB(type, false, null, null, null, b); } } }
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); } } }
void WriteToolTip(ITextOutput output, TypeSig type, GenericParamContext gpContext, IHasCustomAttribute typeAttributes) { var gsig = type.RemovePinnedAndModifiers() as GenericSig; var gp = GetGenericParam(gsig, gpContext); if (gp != null) { output.Write(IdentifierEscaper.Escape(gp.Name), gsig.IsMethodVar ? TextTokenType.MethodGenericParameter : TextTokenType.TypeGenericParameter); return; } WriteToolTip(output, type.ToTypeDefOrRef(), typeAttributes); }
private static IEnumerable<TypeSig> BaseTypes(TypeSig type) { TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow(); if (typeDef.BaseType == null) yield break; TypeSig baseType = type; do { var args = new GenericArguments(); if (baseType.IsGenericInstanceType) args.PushTypeArgs(((GenericInstSig)baseType).GenericArguments); baseType = args.Resolve(typeDef.BaseType.ToTypeSig()); yield return baseType; typeDef = typeDef.BaseType.ResolveTypeDef(); } while (typeDef != null && typeDef.BaseType != null); }
public static bool IsEnum(TypeSig type) { // Arrays/Pointers/ByReference resolve to their element type, but we don't want to consider those to be enums // However, GenericInstanceTypes, ModOpts etc. should be considered enums. if (type == null || IsArrayPointerOrReference(type)) return false; // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef() as TypeDef; return typeDef != null && typeDef.IsEnum; }
public const int NativeInt = 33; // treat native int as between int32 and int64 /// <summary> /// Gets the underlying type, if the specified type is an enum. /// Otherwise, returns null. /// </summary> public static TypeSig GetEnumUnderlyingType(TypeSig enumType) { // unfortunately we cannot rely on enumType.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec) if (enumType != null && !IsArrayPointerOrReference(enumType)) { // value type might be an enum TypeDef typeDef = enumType.ToTypeDefOrRef().ResolveTypeDef() as TypeDef; if (typeDef != null && typeDef.IsEnum) { return typeDef.Fields.Single(f => !f.IsStatic).FieldType; } } return null; }
/* needs a better name */ static TypeSig ICast(TypeSig a, TypeSig b, ICorLibTypes ts) { if (comp.Equals(a, b)) return a; if (comp.Equals(a, ts.String)) return a; if (comp.Equals(b, ts.String)) return b; if (comp.Equals(a, ts.IntPtr) || comp.Equals(a, ts.UIntPtr)) return a; if (comp.Equals(b, ts.IntPtr) || comp.Equals(b, ts.UIntPtr)) return b; if (comp.Equals(a, ts.Double)) return a; if (comp.Equals(b, ts.Double)) return b; if (comp.Equals(a, ts.Single)) return a; if (comp.Equals(b, ts.Single)) return b; if (comp.Equals(a, ts.Int64) || comp.Equals(a, ts.UInt64)) return a; if (comp.Equals(b, ts.Int64) || comp.Equals(b, ts.UInt64)) return b; if (!a.IsByRef || !b.IsByRef) return ts.Object; var ad = a.ToTypeDefOrRef().ResolveTypeDefThrow(); var bd = b.ToTypeDefOrRef().ResolveTypeDefThrow(); if ((!ad.IsSequentialLayout || !ad.IsExplicitLayout) && (!bd.IsSequentialLayout || !bd.IsExplicitLayout)) return ts.IntPtr; // close enough return ad.PackingSize > bd.PackingSize ? a : b; }