Ejemplo n.º 1
0
 public bool hasMethod(ExpandedMethod method)
 {
     return analyzedMethods.Contains(method);
 }
Ejemplo n.º 2
0
 public AnalyzerData addMethod(ExpandedMethod method)
 {
     return hasMethod(method)
     ? this : new AnalyzerData(usedTypes, analyzedMethods.Add(method), virtualMethodsToAnalyze, analyzedVirtualMethods);
 }
Ejemplo n.º 3
0
        static AnalyzerData analyze(
            AnalyzerData data, ExpandedMethod method, AnalyserLogger log
            )
        {
            if (data.hasMethod(method)) return data;
              log.log("method", method);
              log.incIndent();

              data = data.addMethod(method);

              if (method.definition.IsConstructor) data = data.addType(method.declaringType);
              data = data.addType(method.returnType);
              data = method.parameters.Aggregate(data, (current, parameter) => current.addType(parameter));

              if (method.definition.IsVirtual && method.definition.Body == null) {
            // Because we don't know with what concrete types the implementation classes
            // of virtual methods will be instantiated, we will need to do a separate
            // analyzing stage once we know all the concrete types.
            data = data.addType(method.declaringType);
            data = data.addVirtualMethod(new VirtualMethod(method));
              }
              else if (method.definition.Body != null) {
            var body = method.definition.Body;
            foreach (var varDef in body.Variables) {
              var exVar = ExpandedType.create(varDef.VariableType, method.genericParameterToExType);
              data = data.addType(exVar);
            }
            foreach (var instruction in body.Instructions) {
              if (
            instruction.OpCode == OpCodes.Stfld || instruction.OpCode == OpCodes.Stsfld
            || instruction.OpCode == OpCodes.Ldsfld
              ) {
            var fieldDef = (FieldReference) instruction.Operand;
            var fieldGenerics = method.genericParameterToExType;
            var gFieldType = fieldDef.FieldType as GenericInstanceType;

            if (fieldDef.FieldType.DeclaringType != null /*fieldDef.FieldType.IsNested*/) {
              if (fieldDef.FieldType.IsGenericParameter) {
                var generics = ExpandedMethod.genericArgumentsDict(
                  ((GenericInstanceType) fieldDef.DeclaringType).GenericArguments,
                  fieldDef.FieldType.DeclaringType.GenericParameters,
                  fieldGenerics
                );
                fieldGenerics = fieldGenerics.AddRange(generics);
              }
              if (gFieldType != null) {
                var tpl =
                  gFieldType.GenericArguments.SequenceEqual(gFieldType.ElementType.GenericParameters)
                  ? F.t(
                    (IList<TypeReference>)gFieldType.ElementType.DeclaringType.GenericParameters.Cast<TypeReference>().ToList(),
                    (IList<GenericParameter>)gFieldType.GenericArguments.Cast<GenericParameter>().ToList()
                  )
                  : gFieldType.ElementType.DeclaringType.HasGenericParameters
                    ? F.t(
                      (IList<TypeReference>) gFieldType.GenericArguments,
                      (IList<GenericParameter>) gFieldType.ElementType.DeclaringType.GenericParameters
                    )
                    : F.t(
                      (IList<TypeReference>)new TypeReference[0],
                      (IList<GenericParameter>)new GenericParameter[0]
                    );

                var generics =
                  ExpandedMethod.genericArgumentsDict(tpl._1, tpl._2, fieldGenerics);
                fieldGenerics = fieldGenerics.AddRange(generics);
              }
            }
            var exFieldDef = ExpandedType.create(fieldDef.FieldType, fieldGenerics);
            var exDeclaringType = ExpandedType.create(fieldDef.DeclaringType, method.genericParameterToExType);
            data = data.addType(exFieldDef).addType(exDeclaringType);
              }
              else if (
            instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli
            || instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Newobj
              ) {
            var methodRef = (MethodReference)instruction.Operand;
            if (instruction.OpCode == OpCodes.Newobj && methodRef.DeclaringType.Resolve().isDelegate()) {
              methodRef = (MethodReference) instruction.Previous.Operand;
            }
            var expanded = ExpandedMethod.create(methodRef, method.genericParameterToExType);
            data = analyze(data, expanded, log);
              }
            }
              }
              else if (! (method.definition.IsInternalCall || method.definition.IsPInvokeImpl)) {
            throw new Exception("Method body null when not expected: " + method);
              }
              log.decIndent();
              return data;
        }
Ejemplo n.º 4
0
        public static AnalyzerData analyze(
            IEnumerable<MethodDefinition> entryPoints,
            AnalyserLogger log
            )
        {
            var data = new AnalyzerData(
            ImmutableHashSet<ExpandedType>.Empty, ImmutableHashSet<ExpandedMethod>.Empty,
            ImmutableHashSet<VirtualMethod>.Empty, ImmutableHashSet<VirtualMethod>.Empty
              );
              foreach (var entryMethod in entryPoints) {
            var exEntryMethod = ExpandedMethod.create(
              entryMethod, ExpandedType.EMPTY_GENERIC_LOOKUP
            );
            data = data.addType(exEntryMethod.declaringType);
            if (!data.hasMethod(exEntryMethod)) {
              log.log("Entry", exEntryMethod);
              data = analyze(data, exEntryMethod, log);
            }
              }

              // Once we know all used types, resolve the called virtual methods.
              // Iterate in a loop because expanding virtual method bodies might invoke additional
              // virtual methods.
              while (!data.virtualMethodsToAnalyze.IsEmpty) {
            foreach (var virtualMethod in data.virtualMethodsToAnalyze) {
              var declaring = virtualMethod.method.declaringType;
              foreach (var _usedType in data.usedTypes.Where(et => et.implements(declaring))) {
            var usedType = _usedType;
            MethodDefinition matching = null;
            while (matching == null) {
              matching = VirtualMethods.GetMethod(
                usedType.definition.Methods, virtualMethod.method.definition
              );
              if (matching == null) {
                if (usedType.definition.BaseType == null) throw new Exception(
                  "Can't find implementation for [" + virtualMethod + "] in [" + _usedType + "]!"
                );
                usedType = ExpandedType.create(
                  usedType.definition.BaseType,
                  usedType.genericParametersToArguments
                );
              }
            }

            var generics = usedType.genericParametersToArguments.AddRange(
              ExpandedMethod.genericArgumentsDict(
                virtualMethod.method.genericArguments.Select(t => (TypeReference)t.definition).ToList(),
                matching.GenericParameters,
                usedType.genericParametersToArguments
              )
            );
            var exMatching = new ExpandedMethod(
              virtualMethod.method.returnType, usedType, matching,
              virtualMethod.method.genericArguments,
              virtualMethod.method.parameters, generics
            );
            data = analyze(data, exMatching, log);
              }
              data = data.analyzedVirtualMethod(virtualMethod);
            }
              }
              return data;
        }
 public void log(string prefix, ExpandedMethod method)
 {
     log(prefix + " " + method);
 }
 public void log(string prefix, ExpandedMethod method)
 {
 }