Пример #1
0
        /// <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();
        }
Пример #2
0
 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);
         }
     }
 }
Пример #3
0
		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;
		}
Пример #4
0
		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) };
		}
Пример #6
0
		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);
				}
			}
		}
Пример #7
0
 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);
         }
     }
 }
Пример #8
0
        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;
		}
Пример #12
0
        /* 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;
        }