internal MapGenericMethodParameters(IMetadataHost host, IGenericMethodInstance genericMethodInstance) : base(host, copyAndRewriteImmutableReferences: true) { Contract.Requires(host != null); Contract.Requires(genericMethodInstance != null); this.genericArguments = IteratorHelper.GetAsArray(genericMethodInstance.GenericArguments); }
public bool TestAssemGenericMethodCall() { ITypeDefinition type = Helper.GetNamespaceType((IUnitNamespace)this.ModuleReaderTest.AssemblyAssembly.NamespaceRoot, this.Assem); IMethodDefinition method = Helper.GetMethodNamed(type, this.GenMethod); IOperation op = Helper.GetOperation(method, 7); IMethodReference methodRef = op.Value as IMethodReference; if (methodRef == null) { return(false); } IGenericMethodInstance gmi = methodRef.ResolvedMethod as IGenericMethodInstance; if (gmi == null) { return(false); } StringILDasmPaper stringPaper = new StringILDasmPaper(2); ILDasmPrettyPrinter prettyPrinter = new ILDasmPrettyPrinter(stringPaper, this.ModuleReaderTest.TestAssembly); prettyPrinter.MethodDefinition(gmi); string result = @".method public hidebysig instance explicit default[mscorlib]System.Object GenMethod<[mscorlib]System.Object>( [mscorlib]System.Object t, [mscorlib]System.Collections.Generic.List`1<[mscorlib]System.Object> l, [mscorlib]System.Object[] ta, [mscorlib]System.Object[,] tm, [mscorlib]System.Object[,] tn )cil managed { .maxstack 6 .locals init( V_0 ) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldnull IL_0003: ldnull IL_0004: ldnull IL_0005: ldnull IL_0006: ldnull IL_0007: call instance!!0[MRW_Assembly]Assem::GenMethod<[mscorlib]System.Object>(!!0,[mscorlib]System.Collections.Generic.List`1<!!0>,!!0[],!!0[,],!!0[,]) IL_000c: pop IL_000d: ldarg.1 IL_000e: stloc.0 IL_000f: br.s IL_0011 IL_0011: ldloc.0 IL_0012: ret } "; return(result.Equals(stringPaper.Content)); }
/// <summary> /// A specialized method definition or generic method instance does not have a body. Given a method definition, /// find the unspecialized version of the definition and fetch the body. /// </summary> /// <param name="methodDefinition"></param> /// <returns></returns> internal static IMethodBody GetMethodBodyFromUnspecializedVersion(IMethodDefinition methodDefinition) { IGenericMethodInstance genericMethodInstance = methodDefinition as IGenericMethodInstance; if (genericMethodInstance != null) { return(GetMethodBodyFromUnspecializedVersion(genericMethodInstance.GenericMethod.ResolvedMethod)); } ISpecializedMethodDefinition specializedMethodDefinition = methodDefinition as ISpecializedMethodDefinition; if (specializedMethodDefinition != null) { return(GetMethodBodyFromUnspecializedVersion(specializedMethodDefinition.UnspecializedVersion.ResolvedMethod)); } return(methodDefinition.Body); }
/// <summary> /// Get the unspecialized method definition is <paramref name="methodDefinition"/> is a specialized /// version, or itself otherwise. /// </summary> /// <param name="methodDefinition"></param> /// <returns></returns> internal static IMethodDefinition UnspecializedMethodDefinition(IMethodDefinition methodDefinition) { IGenericMethodInstance genericMethodInstance = methodDefinition as IGenericMethodInstance; if (genericMethodInstance != null) { methodDefinition = genericMethodInstance.GenericMethod.ResolvedMethod; } ISpecializedMethodDefinition specializedMethodDefinition = methodDefinition as ISpecializedMethodDefinition; if (specializedMethodDefinition != null) { return(specializedMethodDefinition.UnspecializedVersion); } return(methodDefinition); }
/// <summary> /// See if a method definition is compiler generated, or is inside a compiler generated type. /// </summary> /// <param name="methodDefinition"></param> /// <returns></returns> internal static bool IsCompilerGenerated(IMethodDefinition /*!*/ methodDefinition) { if (AttributeHelper.Contains(methodDefinition.Attributes, methodDefinition.ContainingType.PlatformType.SystemRuntimeCompilerServicesCompilerGeneratedAttribute)) { return(true); } IGenericMethodInstance genericMethodInstance = methodDefinition as IGenericMethodInstance; if (genericMethodInstance != null) { return(IsCompilerGenerated(genericMethodInstance.GenericMethod.ResolvedMethod)); } if (methodDefinition.ContainingType == null) { return(false); } return(IsCompilerGenerated(methodDefinition.ContainingType)); }
public static IMethodDefinition GetInstantiatedMeth(IMethodDefinition templateMeth, IMethodDefinition instMeth) { IGenericMethodInstance genericM = instMeth as IGenericMethodInstance; IEnumerable <ITypeReference> genericArgs = genericM.GenericArguments; IList <ITypeReference> stubbedArgList = new List <ITypeReference>(); foreach (ITypeReference garg in genericArgs) { ITypeDefinition addedType = Stubber.CheckAndAdd(garg.ResolvedType); if (addedType != null) { stubbedArgList.Add(addedType); } else { stubbedArgList.Add(garg.ResolvedType); } } string argStr = GetGenericArgStr(stubbedArgList); IDictionary <string, IMethodDefinition> instMap; if (ClassAndMethodVisitor.genericMethodMap.ContainsKey(templateMeth)) { instMap = ClassAndMethodVisitor.genericMethodMap[templateMeth]; } else { instMap = new Dictionary <string, IMethodDefinition>(); ClassAndMethodVisitor.genericMethodMap[templateMeth] = instMap; } if (instMap.ContainsKey(argStr)) { return(instMap[argStr]); } else { GenericMethodInstanceReference newInstMethRef = new GenericMethodInstanceReference(templateMeth, genericArgs, internFactory); IMethodDefinition newInstMeth = newInstMethRef.ResolvedMethod; instMap[argStr] = newInstMeth; return(newInstMeth); } }
private void NoteGenericParameterFlowForMethod(IMethodDefinition calledMethod) { // There are three ways generic parameters can flow // // 1) generic type parameters via a newobject constructor // 2) generic type parameters via a static call // 3) generic method parameters via a (non-constructor)method call // t-devinc: // I don't think this handles specialized types properly (i.e. a type some of whose parameters are instantiated // and some of whom are generic). This can happen with inner classes. // handle Foo<T>.DoSomething(); or new Foo<T>() if (calledMethod.ContainingTypeDefinition is IGenericTypeInstance && (calledMethod.IsStatic || calledMethod.IsConstructor)) { IGenericTypeInstance instantiatedType = calledMethod.ContainingTypeDefinition as IGenericTypeInstance; ITypeDefinition genericType = instantiatedType.GenericType.ResolvedType; IEnumerable <ITypeReference> actuals = instantiatedType.GenericArguments; IEnumerable <IGenericParameter> formals = genericType.GenericParameters; NoteGenericParametersFlow(actuals, formals); } // handle Bar.DoSomething<T>(); if (calledMethod is IGenericMethodInstance) { IGenericMethodInstance instantiatedMethod = calledMethod as IGenericMethodInstance; IMethodDefinition genericMethod = instantiatedMethod.GenericMethod.ResolvedMethod; IEnumerable <ITypeReference> actuals = instantiatedMethod.GenericArguments; IEnumerable <IGenericParameter> formals = genericMethod.GenericParameters; NoteGenericParametersFlow(actuals, formals); } }
internal virtual void Visit(IOperation op) { IMethodDefinition target; switch (op.OperationCode) { case OperationCode.Newobj: target = ResolveMethodReference(op.Value as IMethodReference); if (target != null) { Contract.Assert(!(target is Dummy)); if (target.ContainingType is INamedTypeReference) { //Console.WriteLine("Got newobj to {0}", ((INamedTypeReference)target.ContainingType).Name); } ITypeDefinition constructedType = target.ContainingType.ResolvedType; Contract.Assert(GarbageCollectHelper.TypeIsConstructable(constructedType)); summary.ReachableTypes.Add(constructedType); summary.ConstructedTypes.Add(constructedType); summary.NonvirtuallyCalledMethods.Add(target); } break; case OperationCode.Box: // Boxing a struct means a callvirt could possibly // dispatch to one of its methods. ITypeDefinition boxedType = ResolveTypeReference(op.Value as ITypeReference); if (boxedType != null) { // Guard for structs here because box to a reference type is a no-op but allowed and // the Code Contracts instrumentation does this. if (boxedType.IsStruct) { Contract.Assert(GarbageCollectHelper.TypeIsConstructable(boxedType)); summary.ConstructedTypes.Add(boxedType); } } break; case OperationCode.Ldtoken: if (op.Value is IFieldReference) { IFieldDefinition field = ResolveFieldReference(op.Value as IFieldReference); if (field != null) { summary.ReachableFields.Add(field); } } // t-devinc: Need to handle: method and type tokens, as well as generics. // Fully supporting generics here may be very tricky -- this is a place // where operating over specialized bytecode could perhaps help. break; /* Notes on call/callvirt: * * We can get a call on a virtual method when that method is called via 'base' * We can also get a callvirt on a non-virtual method whenever the compiler * feels like it? This seems a little wonky. */ case OperationCode.Ldftn: case OperationCode.Call: target = ResolveMethodReference(op.Value as IMethodReference); if (target != null) { if (target.ContainingType is INamedTypeReference) { //Console.WriteLine("Got call to {0}", target); } summary.NonvirtuallyCalledMethods.Add(target); if (target.Name.Value == "CreateInstance") { // t-devinc: gross, clean this up INamespaceTypeDefinition containingTypeDefinition = target.ContainingTypeDefinition as INamespaceTypeDefinition; if (containingTypeDefinition != null && containingTypeDefinition.Name.Value == "Activator") { if (containingTypeDefinition.ContainingNamespace.Name.Value == "System") { IGenericMethodInstance targetAsGenericMethodInstance = target as IGenericMethodInstance; if (targetAsGenericMethodInstance != null) { // We have a call to 'new T()'; ITypeDefinition definitionForT = targetAsGenericMethodInstance.GenericArguments.First().ResolvedType; summary.ConstructedTypeParameters.Add((IGenericParameter)definitionForT); } } } } } break; case OperationCode.Ldvirtftn: case OperationCode.Callvirt: target = ResolveMethodReference(op.Value as IMethodReference); if (target != null) { if (target.ContainingType is INamedTypeReference) { //Console.WriteLine("Got callvirt to {0}", target); } if (target.IsVirtual) { summary.VirtuallyCalledMethods.Add(target); } else { // In its infinite wisdom, sometimes the compiler gives us a callvirt on a non-virtual method summary.NonvirtuallyCalledMethods.Add(target); } } break; case OperationCode.Ldfld: case OperationCode.Ldflda: case OperationCode.Ldsfld: case OperationCode.Ldsflda: /* For now we treat loads and stores as the same -- we'll want to be smarter about this in the future */ case OperationCode.Stfld: case OperationCode.Stsfld: IFieldDefinition fieldDefinition = ResolveFieldReference(op.Value as IFieldReference); if (fieldDefinition != null) { summary.ReachableTypes.Add(fieldDefinition.ContainingTypeDefinition); summary.ReachableFields.Add(fieldDefinition); } break; default: break; } }
public void SaveScope(IMetadataHost host) { string modulesFN = "modules.txt"; StreamWriter modulesSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, modulesFN)); List <IModule> moduleList = host.LoadedUnits.OfType <IModule>().ToList(); TypeDefinitionComparer tdc = new TypeDefinitionComparer(); ISet <ITypeDefinition> processedTypes = new HashSet <ITypeDefinition>(tdc); foreach (IModule module in moduleList) { if (module == null || module == Dummy.Module || module == Dummy.Assembly) { System.Console.WriteLine("WARNING: SaveScope - modules: Dummy or null module - skipping."); continue; } modulesSW.WriteLine("MODULE:" + module.Name.Value + " LOCATION:" + module.Location); } modulesSW.Close(); string classesFN = "classes.txt"; StreamWriter classesSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, classesFN)); foreach (ITypeDefinition cl in classes) { if (processedTypes.Contains(cl)) { continue; } IModule mod = TypeHelper.GetDefiningUnit(cl) as IModule; if (cl is IGenericTypeInstance) { ProcessGenericType(cl, classesSW, mod, processedTypes); } else { classesSW.WriteLine("CLASS:" + cl.FullName() + " ARGS: MODULE:" + mod.Name.Value); processedTypes.Add(cl); } } classesSW.Close(); string entClassesFN = "entrypt_classes.txt"; StreamWriter entClassesSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, entClassesFN)); foreach (ITypeDefinition cl in entryPtClasses) { IModule mod = TypeHelper.GetDefiningUnit(cl) as IModule; entClassesSW.WriteLine("CLASS:" + cl.FullName() + " ARGS: MODULE:" + mod.Name.Value); } entClassesSW.Close(); string methodsFN = "methods.txt"; StreamWriter methodsSW = new StreamWriter(Path.Combine(ConfigParams.SaveScopePath, methodsFN)); foreach (IMethodDefinition meth in methods) { string argStr = ""; IMethodDefinition methToRecord = meth; if (meth is IGenericMethodInstance) { IGenericMethodInstance genericM = meth as IGenericMethodInstance; IEnumerable <ITypeReference> genericArgs = genericM.GenericArguments; foreach (ITypeReference ty in genericArgs) { ITypeDefinition tyDefn = ty.ResolvedType; argStr += tyDefn.FullName() + ";"; } if (!argStr.Equals("")) { argStr = argStr.TrimEnd(';'); } methToRecord = genericM.GenericMethod.ResolvedMethod; } methodsSW.WriteLine("METHOD:" + methToRecord.FullName() + " ARGS:" + argStr + " CLASS:" + methToRecord.ContainingTypeDefinition.FullName()); } methodsSW.Close(); }