Exemple #1
0
        /// <summary>
        /// The given node is defaultvalue(struct).
        /// Convert it to newobj
        /// </summary>
        internal static void ConvertDefaultValue(AstExpression callNode, XMethodDefinition defaultCtorDef)
        {
            var type        = (XTypeReference)callNode.Operand;
            var defaultCtor = type.CreateReference(defaultCtorDef);
            var typeDef     = defaultCtorDef.DeclaringType;

            if (typeDef.IsImmutableStruct)
            {
                var fieldDef = typeDef.Fields.SingleOrDefault(f => f.Name == NameConstants.Struct.DefaultFieldName);
                if (fieldDef != null)
                {
                    // load the default field.
                    callNode.Arguments.Clear();
                    callNode.Code    = AstCode.Ldsfld;
                    callNode.Operand = fieldDef;
                    callNode.SetType(defaultCtor.DeclaringType);
                    return;
                }
            }
            else
            {
                // Remove "this" argument
                callNode.Arguments.Clear();
                callNode.Code    = AstCode.Newobj;
                callNode.Operand = defaultCtor;
                callNode.SetType(defaultCtor.DeclaringType);
            }
        }
        private bool IsUnderlyingCodeModified(XMethodDefinition sourceMethod)
        {
            var ilMethod   = sourceMethod as XModel.DotNet.XBuilder.ILMethodDefinition;
            var javaMethod = sourceMethod as XModel.Java.XBuilder.JavaMethodDefinition;

            if (ilMethod != null)
            {
                var assembly = ilMethod.OriginalMethod.DeclaringType.Module.Assembly;

                if (_modifiedDetector.IsModified(assembly))
                {
                    return(true);
                }
            }
            else if (javaMethod != null)
            {
                var javaType  = (XModel.Java.XBuilder.JavaTypeDefinition)javaMethod.DeclaringType;
                var classFile = (ClassFile)javaType.OriginalTypeDefinition;
                var loader    = classFile.Loader as AssemblyClassLoader;
                var assembly  = loader == null ? null : loader.GetAssembly(classFile);
                if (assembly == null || _modifiedDetector.IsModified(assembly))
                {
                    return(true);
                }
            }
            else
            {
                // TODO: synthetic methods could be resolved from the cache as well.
                //       check if this would bring any performance benefits.
                return(true);
            }
            return(false);
        }
Exemple #3
0
        /// <summary>
        /// Process an argument of the given call node.
        /// </summary>
        private static void CloneStructArgument(AstExpression callNode, XMethodDefinition method, int argumentIndex)
        {
            // Clone structs
            var paramIndex = method.IsStatic ? argumentIndex : argumentIndex - 1;

            if ((paramIndex >= 0) && (method.Name != NameConstants.Struct.CloneMethodName) && (method.Name != NameConstants.Struct.CopyFromMethodName))
            {
                var             paramType = method.Parameters[paramIndex].ParameterType;
                XTypeDefinition typeDef;
                if (paramType.IsStruct(out typeDef) && !typeDef.IsImmutableStruct)
                // TODO: check if this decision should be made based on the actual argument type, not the destination type.
                //       this should be true at least for generic parameters, which might either take a ValueType or
                //       a reference type.
                //       Then again, maybe the struct argument should be cloned on an "box" instruction.
                {
                    // Call $Clone
                    var argNode = callNode.Arguments[argumentIndex];
                    if (IsCloneNeeded(argNode))
                    {
                        var cloneMethod = GetCloneMethod(typeDef);
                        var clone       = new AstExpression(argNode.SourceLocation, AstCode.Call, paramType.CreateReference(cloneMethod), argNode);
                        callNode.Arguments[argumentIndex] = clone;
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// The given node is newarr(struct).
        /// Convert it to initStructArray(newarr(struct))
        /// </summary>
        private static void ConvertNewArrStruct(AstExpression newArrNode, XMethodDefinition defaultCtor)
        {
            var newArrClone = new AstExpression(newArrNode);

            newArrNode.Code = AstCode.InitStructArray;
            newArrNode.Arguments.Clear();
            newArrNode.Arguments.Add(newArrClone);

            var typeDef = defaultCtor.DeclaringType;

            if (typeDef.IsImmutableStruct)
            {
                var field = typeDef.Fields.SingleOrDefault(f => f.Name == NameConstants.Struct.DefaultFieldName);
                if (field != null)
                {
                    newArrNode.Operand = field;
                }
                else
                {
                    newArrNode.Operand = defaultCtor;
                }
            }
            else
            {
                newArrNode.Operand = defaultCtor;
            }
        }
        /// <summary>
        /// Create the body of the ctor.
        /// </summary>
        private static MethodBody CreateCtorBody(XMethodDefinition calledMethod, FieldDefinition instanceField, ClassReference baseClass)
        {
            var body = new MethodBody(null);
            // Create code
            var ins   = body.Instructions;
            var rthis = body.AllocateRegister(RCategory.Argument, RType.Object);
            // Call base ctor
            var baseCtorRef = new MethodReference(baseClass, "<init>", new Prototype(PrimitiveType.Void));

            ins.Add(new Instruction(RCode.Invoke_direct, rthis)
            {
                Operand = baseCtorRef
            });
            if (!calledMethod.IsStatic)
            {
                // load instance into field
                var rvalue = body.AllocateRegister(RCategory.Argument, RType.Object);
                ins.Add(new Instruction(RCode.Iput_object, rvalue, rthis)
                {
                    Operand = instanceField
                });
            }
            ins.Add(new Instruction(RCode.Return_void));
            return(body);
        }
Exemple #6
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public CompiledMethod(XMethodDefinition method)
 {
     if (method == null)
     {
         throw new ArgumentNullException("method");
     }
     this.method = method;
 }
Exemple #7
0
 /// <summary>
 /// Java ctor
 /// </summary>
 public MethodSource(XMethodDefinition method, JavaMethodDefinition javaMethod)
 {
     if (javaMethod == null)
     {
         throw new ArgumentNullException();
     }
     this.method     = method;
     this.javaMethod = javaMethod;
 }
Exemple #8
0
        /// <summary>
        /// The given node is newarr(struct).
        /// Convert it to initStructArray(newarr(struct))
        /// </summary>
        private static void ConvertNewArrStruct(AstExpression newArrNode, XMethodDefinition defaultCtor)
        {
            var newArrClone = new AstExpression(newArrNode);

            newArrNode.Code = AstCode.InitStructArray;
            newArrNode.Arguments.Clear();
            newArrNode.Arguments.Add(newArrClone);
            newArrNode.Operand = defaultCtor;
        }
Exemple #9
0
        /// <summary>
        /// Default ctor
        /// </summary>
        public DelegateType(AssemblyCompiler compiler, XTypeDefinition delegateType, ClassDefinition interfaceClass, Dex target, NameConverter nsConverter)
        {
            this.compiler       = compiler;
            this.delegateType   = delegateType;
            this.interfaceClass = interfaceClass;

            // Build invoke prototype
            invokeMethod = delegateType.Methods.First(x => x.EqualsName("Invoke"));
        }
Exemple #10
0
 /// <summary>
 /// AST ctor
 /// </summary>
 public MethodSource(XMethodDefinition method, AstBlock ast)
 {
     if (ast == null)
     {
         throw new ArgumentNullException();
     }
     this.method = method;
     this.ast    = ast;
 }
Exemple #11
0
 /// <summary>
 /// IL ctor
 /// </summary>
 public MethodSource(XMethodDefinition method, ILMethodDefinition ilMethod)
 {
     if (ilMethod == null)
     {
         throw new ArgumentNullException();
     }
     this.method   = method;
     this.ilMethod = ilMethod;
 }
Exemple #12
0
        /// <summary>
        /// The given node is defaultvalue(struct).
        /// Convert it to newobj
        /// </summary>
        private static void ConvertDefaultValue(AstExpression callNode, XMethodDefinition defaultCtorDef)
        {
            var type        = (XTypeReference)callNode.Operand;
            var defaultCtor = type.CreateReference(defaultCtorDef);

            // Remove "this" argument
            callNode.Arguments.Clear();
            callNode.Code    = AstCode.Newobj;
            callNode.Operand = defaultCtor;
            callNode.SetType(defaultCtor.DeclaringType);
        }
Exemple #13
0
 /// <summary>
 /// .NET ctor
 /// </summary>
 public DecompilerContext(XMethodDefinition currentMethod)
 {
     if (currentMethod == null)
     {
         throw new ArgumentNullException("currentMethod");
     }
     name = currentMethod.Name;
     declaringTypeName = currentMethod.DeclaringType.Name;
     declaringType     = currentMethod.DeclaringType;
     returnType        = currentMethod.ReturnType;
     currentModule     = currentMethod.Module;
 }
Exemple #14
0
            /// <summary>
            /// Resolve this reference to it's definition.
            /// </summary>
            public override bool TryResolve(out XMethodDefinition method)
            {
                method = null;
                var             declaringTypeRef = DeclaringType.IsArray ? Module.TypeSystem.Object : DeclaringType.GetElementType();
                XTypeDefinition declaringType;

                if (!declaringTypeRef.TryResolve(out declaringType))
                {
                    return(false);
                }
                return(declaringType.TryGet(this, out method));
            }
Exemple #15
0
        /// <summary>
        /// Get a compiled method info for the given method.
        /// Create if needed.
        /// </summary>
        internal CompiledMethod GetOrCreateCompileMethod(XMethodDefinition method)
        {
            CompiledMethod result;

            if (!xMethodMap.TryGetValue(method, out result))
            {
                result = new CompiledMethod(method);
                compiledMethods.Add(result);
                xMethodMap.Add(method, result);
            }
            return(result);
        }
Exemple #16
0
 /// <summary>
 /// Generate an Invoke opcode.
 /// </summary>
 internal static RCode Invoke(this XMethodDefinition targetMethod, XMethodReference targetMethodRef, MethodSource currentMethod, bool isSpecial = false)
 {
     if (targetMethod != null)
     {
         if (targetMethod.DeclaringType.IsDelegate())
         {
             return(RCode.Invoke_interface);
         }
         if (targetMethod.IsStatic || targetMethod.IsAndroidExtension)
         {
             return(RCode.Invoke_static);
         }
         if ((currentMethod != null) && targetMethod.UseInvokeSuper(currentMethod.Method))
         {
             return(RCode.Invoke_super);
         }
         if (isSpecial && !targetMethod.IsConstructor && (currentMethod != null) && targetMethod.DeclaringType.IsBaseOf(currentMethod.Method.DeclaringType))
         {
             return(RCode.Invoke_super);
         }
         if (targetMethod.UseInvokeInterface)
         {
             return(RCode.Invoke_interface);
         }
         if (targetMethod.IsDirect)
         {
             return(RCode.Invoke_direct);
         }
         if (targetMethod.DeclaringType.IsInterface)
         {
             return(RCode.Invoke_interface);
         }
     }
     if (targetMethodRef != null)
     {
         if (!targetMethodRef.HasThis)
         {
             return(RCode.Invoke_static);
         }
         switch (targetMethodRef.Name)
         {
         case "<init>":
         case "<clinit>":
         case ".ctor":
         case ".cctor":
             return(RCode.Invoke_direct);
         }
     }
     return(RCode.Invoke_virtual);
 }
        public CacheEntry GetFromCache(MethodDefinition targetMethod, XMethodDefinition sourceMethod, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var ret = GetFromCacheImpl(targetMethod, sourceMethod, compiler, targetPackage);

            if (ret != null)
            {
                Interlocked.Increment(ref statCacheHits);
            }
            else
            {
                Interlocked.Increment(ref statCacheMisses);
            }

            return(ret);
        }
Exemple #18
0
        public MethodBody GetMethodBody(MethodDefinition targetMethod, XMethodDefinition sourceMethod)
        {
            var javaType  = (XBuilder.JavaTypeDefinition)sourceMethod.DeclaringType;
            var className = javaType.ClassFile.ClassName;
            var source    = javaType.ClassFile.Loader.TryGetClassSource(className);

            if (source == null)
            {
                return(null);
            }

            DexLookup dex       = GetOrCreateDex(source, waitForResult: true);
            var       methodDef = dex.GetMethod(targetMethod.Owner.Fullname, targetMethod.Name, targetMethod.Prototype.ToSignature());

            return(methodDef == null ? null : methodDef.Body);
        }
 /// <summary>
 /// Create the current type as class definition.
 /// </summary>
 internal DelegateInstanceTypeBuilder(
     ISourceLocation sequencePoint,
     AssemblyCompiler compiler, DexTargetPackage targetPackage,
     ClassDefinition delegateClass,
     XMethodDefinition invokeMethod, Prototype invokePrototype,
     XMethodDefinition calledMethod)
 {
     this.sequencePoint          = sequencePoint;
     this.compiler               = compiler;
     this.targetPackage          = targetPackage;
     this.delegateClass          = delegateClass;
     this.invokeMethod           = invokeMethod;
     this.invokePrototype        = invokePrototype;
     this.calledMethod           = calledMethod;
     this.multicastDelegateClass = compiler.GetDot42InternalType("System", "MulticastDelegate").GetClassReference(targetPackage);
 }
Exemple #20
0
        /// <summary>
        /// Implement the class now that all classes have been created
        /// </summary>
        protected override void CreateMembers(DexTargetPackage targetPackage)
        {
            base.CreateMembers(targetPackage);

            // Build default ctor
            XTypeSystem typeSystem          = Compiler.Module.TypeSystem;
            XSyntheticMethodDefinition ctor = XSyntheticMethodDefinition.Create(XType, XSyntheticMethodFlags.Constructor, "<init>", null, typeSystem.Void);

            ctor.Body = CreateCtorBody();
            Class.Methods.Add(ctor.GetDexMethod(Class, targetPackage));

            // Build Invoke method.
            XMethodDefinition sourceMethod = XType.Methods.Single(x => x.EqualsName("Invoke"));
            Prototype         prototype    = PrototypeBuilder.BuildPrototype(Compiler, targetPackage, Class, sourceMethod);
            MethodDefinition  method       = new MethodDefinition(Class, sourceMethod.Name, prototype)
            {
                AccessFlags = AccessFlags.Public | AccessFlags.Abstract,
                MapFileId   = Compiler.GetNextMapFileId()
            };

            Class.Methods.Add(method);

            // Find xSource method
            targetPackage.NameConverter.Record(sourceMethod, method);

            // If void() delegate, implement java.lang.Runnable
            if (sourceMethod.ReturnType.IsVoid() && (sourceMethod.Parameters.Count == 0))
            {
                // Implement interface
                Class.Interfaces.Add(FrameworkReferences.Runnable);

                // Build run method
                var run = new MethodDefinition(Class, "run", new Prototype(PrimitiveType.Void))
                {
                    AccessFlags = AccessFlags.Public | AccessFlags.Final
                };
                Class.Methods.Add(run);
                run.Body = new DexLib.Instructions.MethodBody(run, 1)
                {
                    IncomingArguments = 1, OutgoingArguments = 1
                };
                var insList = run.Body.Instructions;
                var rThis   = run.Body.Registers[0];
                insList.Add(new DexLib.Instructions.Instruction(OpCodes.Invoke_virtual, method, rThis));
                insList.Add(new DexLib.Instructions.Instruction(OpCodes.Return_void));
            }
        }
Exemple #21
0
        /// <summary>
        /// Create the current type as class definition.
        /// </summary>
        public void Create(ClassDefinition declaringClass, DexTargetPackage targetPackage)
        {
            // Find xMethod
            xMethod = XBuilder.AsMethodDefinition(compiler.Module, method);

            // Create method definition
            dmethod           = new DexLib.MethodDefinition();
            dmethod.Name      = GetMethodName(method, targetPackage);
            dmethod.MapFileId = compiler.GetNextMapFileId();
            AddMethodToDeclaringClass(declaringClass, dmethod, targetPackage);
            targetPackage.Record(xMethod, dmethod);

            // Set access flags
            SetAccessFlags(dmethod, method);

            // Create prototype
            dmethod.Prototype = PrototypeBuilder.BuildPrototype(compiler, targetPackage, declaringClass, xMethod);
        }
Exemple #22
0
        /// <summary>
        /// Default ctor
        /// </summary>
        public DelegateType(AssemblyCompiler compiler, XTypeDefinition delegateType, ClassDefinition interfaceClass, Dex target, NameConverter nsConverter)
        {
            this.compiler       = compiler;
            this.delegateType   = delegateType;
            this.interfaceClass = interfaceClass;

            // Build invoke prototype
            invokeMethod = delegateType.Methods.First(x => x.EqualsName("Invoke"));
            XTypeDefinition baseType = delegateType;

            while ((null != baseType) && !baseType.Methods.Any(x => x.EqualsName("Equals")))
            {
                baseType = baseType.BaseType as XTypeDefinition;
            }
            if (null != baseType)
            {
                equalsMethod = baseType.Methods.First(x => x.EqualsName("Equals"));
            }
        }
Exemple #23
0
        public static MethodEntry RecordMapping(TypeEntry typeEntry, XMethodDefinition xMethod, MethodDefinition method, DexLib.MethodDefinition dmethod, CompiledMethod compiledMethod)
        {
            var scopeId = xMethod.ScopeId;

            StringBuilder netSignature = new StringBuilder();

            method.MethodSignatureFullName(netSignature);

            var entry = new MethodEntry(method.OriginalName, netSignature.ToString(), dmethod.Name, dmethod.Prototype.ToSignature(), dmethod.MapFileId,
                                        scopeId);

            typeEntry.Methods.Add(entry);

            if (compiledMethod != null)
            {
                compiledMethod.RecordMapping(entry);
            }

            return(entry);
        }
Exemple #24
0
        /// <summary>
        /// Process an argument of the given call node.
        /// </summary>
        private static void CloneStructArgument(AstExpression callNode, XMethodDefinition method, int argumentIndex)
        {
            // Clone structs
            var paramIndex = method.IsStatic ? argumentIndex : argumentIndex - 1;

            if ((paramIndex >= 0) && (method.Name != NameConstants.Struct.CloneMethodName) && (method.Name != NameConstants.Struct.CopyFromMethodName))
            {
                var             paramType = method.Parameters[paramIndex].ParameterType;
                XTypeDefinition typeDef;
                if (paramType.IsStruct(out typeDef))
                {
                    // Call $Clone
                    var argNode = callNode.Arguments[argumentIndex];
                    if (IsCloneNeeded(argNode))
                    {
                        var cloneMethod = GetCloneMethod(typeDef);
                        var clone       = new AstExpression(argNode.SourceLocation, AstCode.Call, paramType.CreateReference(cloneMethod), argNode);
                        callNode.Arguments[argumentIndex] = clone;
                    }
                }
            }
        }
Exemple #25
0
        /// <summary>
        /// Process an argument of the given call node.
        /// </summary>
        private static void ProcessArgument(AstExpression callNode, XMethodDefinition method, int argumentIndex, XModule assembly)
        {
            var argNode = callNode.Arguments[argumentIndex];

            // Process argument
            switch (argNode.Code)
            {
            case AstCode.Ldloca:     // Parameter
                argNode.Code = AstCode.Ldloc;
                break;

            case AstCode.Ldflda:     // Instance field
                argNode.Code = AstCode.Ldfld;
                break;

            case AstCode.Ldsflda:     // Static field
                argNode.Code = AstCode.Ldsfld;
                break;

            case AstCode.Ldelema:     // Array element
                argNode.Code = AstCode.Ldelem_Any;
                break;

            case AstCode.Ldobj:     // Load object
                if ((argumentIndex == 0) && !method.IsStatic)
                {
                    AstVariable variable;
                    if ((argNode.Arguments.Count == 1) && (argNode.Arguments[0].Match(AstCode.Ldloc, out variable)) &&
                        variable.Type.IsByReference)
                    {
                        argNode.Code         = AstCode.Ldloc;
                        argNode.Operand      = variable;
                        argNode.InferredType = variable.Type.ElementType;
                        argNode.Arguments.Clear();
                    }
                }
                break;
            }
        }
Exemple #26
0
        /// <summary>
        /// Record the given method mapping
        /// </summary>
        internal DexLib.MethodDefinition GetMethod(XMethodDefinition xMethod)
        {
            DexLib.MethodDefinition dmethod;
            if (xMethodMap.TryGetValue(xMethod, out dmethod))
            {
                return(dmethod);
            }

            /*var javaImportAttr = ilMethod.GetJavaImportAttribute();
             * if (javaImportAttr != null)
             * {
             *  string memberName;
             *  string descriptor;
             *  string className;
             *  javaImportAttr.GetDexOrJavaImportNames(ilMethod, out memberName, out descriptor, out className);
             *  var javaMethod = javaMethodMap.Keys.FirstOrDefault(x => (x.Name == memberName) && (x.Descriptor == descriptor) && (x.DeclaringClass.ClassName == className));
             *  if (javaMethod != null)
             *  {
             *      return GetMethod(javaMethod);
             *  }
             * }*/
            throw new ArgumentException(string.Format("Method {0} not found", xMethod));
        }
Exemple #27
0
        /// <summary>
        /// Get a compiled method info for the given method.
        /// </summary>
        internal CompiledMethod GetMethod(XMethodDefinition method)
        {
            CompiledMethod result;

            return(xMethodMap.TryGetValue(method, out result) ? result : null);
        }
Exemple #28
0
 /// <summary>
 /// Record the given method mapping
 /// </summary>
 internal void Record(XMethodDefinition xMethod, MethodDefinition dMethod)
 {
     NameConverter.Record(xMethod, dMethod);
     GetOrCreateCompileMethod(xMethod).DexMethod = dMethod;
 }
 /// <summary>
 /// Resolve this reference to it's definition.
 /// </summary>
 public override bool TryResolve(out XMethodDefinition method)
 {
     method = null;
     var declaringTypeRef = DeclaringType.IsArray ? Module.TypeSystem.Object : DeclaringType.GetElementType();
     XTypeDefinition declaringType;
     if (!declaringTypeRef.TryResolve(out declaringType))
         return false;
     return declaringType.TryGet(this, out method);
 }
 /// <summary>
 /// Default ctor
 /// </summary>
 public DelegateInstanceType(XMethodDefinition calledMethod, ClassDefinition instanceDefinition, Dot42.DexLib.MethodDefinition instanceCtor)
 {
     this.calledMethod       = calledMethod;
     this.instanceDefinition = instanceDefinition;
     this.instanceCtor       = instanceCtor;
 }
        /// <summary>
        /// Create a prototype for the given methods signature
        /// </summary>
        internal static Prototype BuildPrototype(AssemblyCompiler compiler, DexTargetPackage targetPackage, ClassDefinition declaringClass, XMethodDefinition method)
        {
            var result = new Prototype();

            result.ReturnType = method.ReturnType.GetReference(targetPackage);
            if (method.IsAndroidExtension && !method.IsStatic)
            {
                // Add "this" parameter
                var dparameter = new Parameter(method.DeclaringType.GetReference(targetPackage), "this");
                result.Parameters.Add(dparameter);
            }
            foreach (var p in method.Parameters)
            {
                var dparameter = new Parameter(p.ParameterType.GetReference(targetPackage), p.Name);
                result.Parameters.Add(dparameter);
            }
            if (method.NeedsGenericInstanceTypeParameter)
            {
                // Add GenericInstance parameter (to pass the generic instance array of the declaring type)
                var paramType  = FrameworkReferences.ClassArray;
                var dparameter = new Parameter(paramType, "__$$git");
                var annType    = compiler.GetDot42InternalType(InternalConstants.GenericTypeParameterAnnotation).GetClassReference(targetPackage);
                dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
                result.Parameters.Add(dparameter);
                result.GenericInstanceTypeParameter = dparameter;
            }
            if (method.NeedsGenericInstanceMethodParameter)
            {
                // Add GenericInstance parameter
                var paramType  = FrameworkReferences.ClassArray;
                var dparameter = new Parameter(paramType, "__$$gim");
                var annType    = compiler.GetDot42InternalType(InternalConstants.GenericMethodParameterAnnotation).GetClassReference(targetPackage);
                dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
                result.Parameters.Add(dparameter);
                result.GenericInstanceMethodParameter = dparameter;
            }
            return(result);
        }