public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            // find the ClassReference object
            object         targetObject = property.serializedObject.targetObject;
            string         field        = property.propertyPath;
            ClassReference reference    = this.GetFieldValue(targetObject, field) as ClassReference;

            // get the types that inherit from the requested type and their names
            Type[]   types;
            String[] names;
            this.GetValidTypesFor(reference.GetRequiredType(), out types, out names);

            // Find the index of the selected type in the array of available types or set the index to zero if not found.
            // No need to remember the index since Unity will use this PropertyDrawer multiple times for different fields.
            int selectedIndex = this.FindTypeIndex(types, reference.ReferencedClassType);

            if (selectedIndex < 0)
            {
                selectedIndex = 0;
                reference.ReferencedClassType = null;
            }

            // draw the label and the combobox
            label = EditorGUI.BeginProperty(position, label, property);
            Rect comboboxPosition = EditorGUI.PrefixLabel(position, label);

            int selected = EditorGUI.Popup(comboboxPosition, selectedIndex, names);

            if (selected != selectedIndex)
            {
                reference.ReferencedClassType = types[selected];
            }

            EditorGUI.EndProperty();
        }
コード例 #2
0
 /// <summary>
 /// Default ctor
 /// </summary>
 private BoxInfo(XTypeReferenceKind metadataType, ClassReference boxedClass, PrimitiveType primitiveType,
                 string unboxMethodName, RCode convertAfterCode)
 {
     this.metadataType     = metadataType;
     this.boxedClass       = boxedClass;
     this.primitiveType    = primitiveType;
     this.unboxMethodName  = unboxMethodName;
     this.convertAfterCode = convertAfterCode;
 }
コード例 #3
0
        public int GetClassIndex(ClassReference reference)
        {
            var classInfo = new ClassInfo((ushort)GetUtf8Index(reference.Name));

            if (!_classInfos.TryGetValue(classInfo, out int index))
            {
                index = AddConstant(classInfo);
                _classInfos.Add(classInfo, index);
            }

            return(index);
        }
コード例 #4
0
        /// <summary>
        /// Execute an expression
        /// </summary>
        /// <param name="expression">The expression to interpret</param>
        /// <returns>Returns the returned value of the expression</returns>
        internal object RunExpression(AlgorithmExpression expression)
        {
            object result = null;

            switch (expression.DomType)
            {
            case AlgorithmDomType.PrimitiveExpression:
                result = new PrimitiveValue(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.PropertyReferenceExpression:
                result = new PropertyReference(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.VariableReferenceExpression:
                result = new VariableReference(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.ClassReferenceExpression:
                result = new ClassReference(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.ThisReferenceExpression:
                result = new ThisReference(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.InstanciateExpression:
                result = new Instanciate(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.InvokeCoreMethodExpression:
                result = new InvokeCoreMethod(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.InvokeMethodExpression:
                result = new InvokeMethod(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.BinaryOperatorExpression:
                result = new BinaryOperator(DebugMode, this, expression).Execute();
                break;

            case AlgorithmDomType.ArrayIndexerExpression:
                result = new ArrayIndexerExpression(DebugMode, this, expression).Execute();
                break;

            default:
                ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new InvalidCastException($"Unable to find an interpreter for this expression : '{expression.GetType().FullName}'"), expression), GetDebugInfo()));
                break;
            }

            return(FailedOrStop ? null : result);
        }
コード例 #5
0
        public JavaClassFile CreateClassFile(JavaClassImage image)
        {
            var context = new BuildingContext(this);

            // Basic structure.
            var file = new JavaClassFile
            {
                MajorVersion = image.MajorVersion,
                MinorVersion = image.MinorVersion,
            };

            var thisReference = new ClassReference(image.RootClass.Name);

            file.ThisClass = (ushort)ConstantPoolBuffer.GetClassIndex(thisReference);

            if (image.RootClass.SuperClass != null)
            {
                file.SuperClass = (ushort)ConstantPoolBuffer.GetClassIndex(image.RootClass.SuperClass);
            }

            file.AccessFlags = image.RootClass.AccessFlags;

            // Fields
            foreach (var field in image.RootClass.Fields)
            {
                file.Fields.Add(CreateFieldInfo(context, field));
            }

            // Methods
            foreach (var method in image.RootClass.Methods)
            {
                file.Methods.Add(CreateMethodInfo(context, method));
            }

            // Source file
            if (image.SourceFile != null)
            {
                file.Attributes.Add(CreateAttribute(context, new SingleIndexAttribute(
                                                        SingleIndexAttribute.SourceFileAttribute,
                                                        (ushort)ConstantPoolBuffer.GetUtf8Index(image.SourceFile))));
            }

            if (BootstrapMethodsAttribute.BootstrapMethods.Count > 0)
            {
                file.Attributes.Add(CreateAttribute(context, BootstrapMethodsAttribute));
            }

            AddAttributes(context, file, image);

            file.ConstantPool = ConstantPoolBuffer.CreateConstantPool();
            return(file);
        }
コード例 #6
0
        private void Remove(ClassReference classReference)
        {
            var entity = entities.Buffer[classReference.Index];

            if (references.UnorderedRemoveAt(classReference.Index))
            {
                references[classReference.Index].Index = classReference.Index;
            }
            entities.UnorderedRemoveAt(classReference.Index);
            classReference.Child?.ClassEntityCollection.RemoveBlind(classReference.Child);
            classReference.Clear();
            referencePool.Add(classReference);
            Removed?.Invoke(entity);
        }
コード例 #7
0
        private ClassReference ConvertClassReference(ClassReference sourceRef, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            TypeEntry type = _map.GetTypeBySignature(sourceRef.Descriptor);

            if (IsDelegateInstance(type))
            {
                // special delegate handling.
                return(GetDelegateInstanceType(type, sourceRef, compiler, targetPackage).InstanceDefinition);
            }
            else
            {
                var xTypeDef = ResolveToType(type, sourceRef, compiler);
                return(xTypeDef.GetClassReference(targetPackage));
            }
        }
コード例 #8
0
 /// <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);
 }
コード例 #9
0
        private ClassReference GetReference()
        {
            ClassReference reference = null;

            if (referencePool.Count > 0)
            {
                reference = referencePool.Buffer[referencePool.Count - 1];
                referencePool.Buffer[referencePool.Count - 1] = null;
                --referencePool.Count;
            }
            else
            {
                reference = new ClassReference();
            }
            reference.Collection = this;
            return(reference);
        }
コード例 #10
0
        public void BuildSimpleHelloWorld()
        {
            // Create main method.
            var mainMethod = new MethodDefinition("main",
                                                  new MethodDescriptor(BaseType.Void, ObjectType.String.CreateArrayType()))
            {
                AccessFlags = MethodAccessFlags.Public | MethodAccessFlags.Static,
            };

            // Build references.
            var printStream = new ClassReference("java/io/PrintStream");

            var systemOut = new FieldReference("out", new ClassReference("java/lang/System"),
                                               new FieldDescriptor(new ObjectType("java/io/PrintStream")));

            var println = new MethodReference("println", printStream,
                                              new MethodDescriptor(BaseType.Void, ObjectType.String));

            // Build body.
            mainMethod.Body = new ByteCodeMethodBody
            {
                Variables =
                {
                    new LocalVariable("args", new FieldDescriptor(mainMethod.Descriptor.ParameterTypes[0]))
                },
                Instructions =
                {
                    new ByteCodeInstruction(ByteOpCodes.GetStatic,     systemOut),
                    new ByteCodeInstruction(ByteOpCodes.Ldc,           "Hello, world!"),
                    new ByteCodeInstruction(ByteOpCodes.InvokeVirtual, println),
                    new ByteCodeInstruction(ByteOpCodes.Return)
                }
            };
            mainMethod.Body.Variables[0].Start = mainMethod.Body.Instructions[0];

            // Create container class.
            var classDef = new ClassDefinition("HelloWorld")
            {
                Methods    = { mainMethod },
                SuperClass = new ClassReference("java/lang/Object"),
            };
            var classImage = new JavaClassImage(classDef);

            // Verify.
            _fixture.BuildAndVerifyOutput(classImage, "Hello, world!" + Environment.NewLine);
        }
コード例 #11
0
        private dynamic ClassRefDo(ClassReference classReference)
        {
            var oldSpace = MemorySpaces.Current;

            var memorySpace = Get(classReference.ClassInstance).Value as MemorySpace;

            MemorySpaces.Current = memorySpace;

            try
            {
                if (classReference.Deferences.Count == 0)
                {
                    return(memorySpace);
                }

                foreach (var deref in classReference.Deferences)
                {
                    // make sure that the last dereference knows how to pull
                    // its arguments, which are from the original memory space and not
                    // the relative class space. i.e. A.b.foo(x), x is loaded from the
                    // space that contains A, not from the space of b.

                    if (deref == classReference.Deferences.Last())
                    {
                        deref.CallingMemory = oldSpace;
                    }

                    var newSpace = GetValue(Exec(deref));

                    if (deref == classReference.Deferences.Last())
                    {
                        return(newSpace);
                    }

                    MemorySpaces.Current = newSpace;
                }
            }
            finally
            {
                MemorySpaces.Current = oldSpace;
            }

            return(null);
        }
コード例 #12
0
        public override void Execute(Context context)
        {
            foreach (MethodDefinition method in context.Class.Methods.ToArray())
            {
                if (context.Engine.UntouchableMethods.Contains(method))
                {
                    continue;
                }
                for (int i = 0; i < method.Body.Instructions.Count; i++)
                {
                    ByteCodeInstruction byteCodeInstruction = method.Body.Instructions[i];
                    if (byteCodeInstruction.OpCode.Equal(ByteOpCodes.Ldc))
                    {
                        object operand     = byteCodeInstruction.Operand;
                        Type   operandType = operand.GetType();

                        if (operandType == typeof(string))
                        {
                            string value        = (string)operand;
                            string encodedValue = Encode(value);

                            var newString  = new ClassReference("java/lang/String");
                            var getDecoder = new MethodReference("getDecoder", new ClassReference("java/util/Base64"),
                                                                 new MethodDescriptor(new ObjectType("java/util/Base64$Decoder")));
                            var decode = new MethodReference("decode", new ClassReference("java/util/Base64$Decoder"),
                                                             new MethodDescriptor(new ArrayType(new BaseType(BaseTypeValue.Byte)), ObjectType.String));
                            var initString = new MethodReference("<init>", new ClassReference("java/lang/String"),
                                                                 new MethodDescriptor(BaseType.Void, new ArrayType(new BaseType(BaseTypeValue.Byte))));

                            method.Body.Instructions[i] = new ByteCodeInstruction(ByteOpCodes.New, newString);
                            method.Body.Instructions.Insert(i + 1, new ByteCodeInstruction(ByteOpCodes.Dup));
                            method.Body.Instructions.Insert(i + 2, new ByteCodeInstruction(ByteOpCodes.InvokeStatic, getDecoder));
                            method.Body.Instructions.Insert(i + 3, new ByteCodeInstruction(ByteOpCodes.Ldc, encodedValue));
                            method.Body.Instructions.Insert(i + 4, new ByteCodeInstruction(ByteOpCodes.InvokeVirtual, decode));
                            method.Body.Instructions.Insert(i + 5, new ByteCodeInstruction(ByteOpCodes.InvokeSpecial, initString));

                            i += 5;
                        }
                    }
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Create the body of the equals method.
        /// </summary>
        private static MethodBody CreateEqualsCheckTypeOnlyBody(ClassReference delegateClass)
        {
            MethodBody body = new MethodBody(null);

            // This pointer and method argument.
            Register rthis  = body.AllocateRegister(RCategory.Argument, RType.Object);
            Register rother = body.AllocateRegister(RCategory.Argument, RType.Object);

            // result register
            Register result = body.AllocateRegister(RCategory.Temp, RType.Value);

            var ins = body.Instructions;

            // Check if other object can be casted.
            ins.Add(new Instruction(RCode.Instance_of, delegateClass, new[] { result, rother }));

            // Add return instructions
            ins.Add(new Instruction(RCode.Return, result));

            return(body);
        }
コード例 #14
0
        /// <summary>
        /// Delegate methods are created unfortunately during the compilation phase in AstCompiler.VisitExpression.
        /// Model this behaviour here.
        /// </summary>
        private DelegateInstanceType GetDelegateInstanceType(TypeEntry typeEntry, ClassReference classRef, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            var scopeIds = typeEntry.ScopeId.Split(new[] { ":delegate:" }, StringSplitOptions.None);

            var typeScopId   = scopeIds[0];
            var xTypeDef     = compiler.Module.GetTypeByScopeID(GetTypeScopeId(typeEntry.Scope, typeScopId, typeEntry.Name));
            var delegateType = compiler.GetDelegateType(xTypeDef);

            var calledMethodId    = scopeIds[1];
            var calledTypeScopeId = calledMethodId.Split('|')[0];
            var calledMethodScope = calledMethodId.Split('|')[1];

            var calledTypeDef = compiler.Module.GetTypeByScopeID(calledTypeScopeId);
            var calledMethod  = calledTypeDef.GetMethodByScopeId(calledMethodScope);

            // NOTE: we are loosing the SequencePoint (DebugInfo) here. I'm not sure if this
            //       was ever valuable anyways.
            var delInstanceType = delegateType.GetOrCreateInstance(null, targetPackage, calledMethod);

            return(delInstanceType);
        }
コード例 #15
0
        /// <summary>
        /// will throw if type is not found.
        /// </summary>
        private static XTypeDefinition ResolveToType(TypeEntry type, ClassReference sourceRef, AssemblyCompiler compiler)
        {
            XTypeDefinition xTypeDef = null;

            if (type != null)
            {
                string scopeId = GetTypeScopeId(type);
                xTypeDef = compiler.Module.GetTypeByScopeID(scopeId);
            }
            else
            {
                string scopeId = sourceRef.Descriptor.Substring(1, sourceRef.Descriptor.Length - 2);
                xTypeDef = compiler.Module.GetTypeByScopeID(scopeId);
            }

            if (xTypeDef == null)
            {
                throw new CompilerCacheResolveException("unable to resolve " + sourceRef);
            }
            return(xTypeDef);
        }
コード例 #16
0
        // Generally this is used with the name resolver. So for example, you have a refernce to a ClassDefinition
        // instance from the resolver, but you want to turn it into a ClassReference instance.
        // TODO: put this in a method on these classes and implement an interface. The function signatures are all close enough.
        public static Expression ConvertStaticReferenceToExpression(TopLevelEntity item, Token primaryToken, Node owner)
        {
            Expression     output           = null;
            TopLevelEntity referencedEntity = null;

            if (item is ClassDefinition)
            {
                ClassDefinition classDef = (ClassDefinition)item;
                output           = new ClassReference(primaryToken, classDef, owner);
                referencedEntity = classDef;
            }
            else if (item is EnumDefinition)
            {
                EnumDefinition enumDef = (EnumDefinition)item;
                output           = new EnumReference(primaryToken, enumDef, owner);
                referencedEntity = enumDef;
            }
            else if (item is ConstDefinition)
            {
                ConstDefinition constDef = (ConstDefinition)item;
                output           = new ConstReference(primaryToken, constDef, owner);
                referencedEntity = constDef;
            }
            else if (item is FunctionDefinition)
            {
                FunctionDefinition funcDef = (FunctionDefinition)item;
                output           = new FunctionReference(primaryToken, funcDef, owner);
                referencedEntity = funcDef;
            }
            else
            {
                throw new InvalidOperationException();
            }

            Node.EnsureAccessIsAllowed(primaryToken, owner, referencedEntity);

            return(output);
        }
コード例 #17
0
 public ReadOnlyClassReference(ClassReference classReference)
 {
     genericParameters = classReference.GenericParameters.ToArray(parameter => new ReadOnlyTypeReference(parameter));
     if (!string.IsNullOrWhiteSpace(classReference.TypeText))
     {
         name = classReference.TypeText;
     }
     else if (classReference.Class != null)
     {
         name = classReference.Class.Name;
     }
     else if (classReference.ClassNestedClass != null)
     {
         name = classReference.ClassNestedClass.Name;
     }
     else if (classReference.StructNestedClass != null)
     {
         name = classReference.StructNestedClass.Name;
     }
     else if (classReference.Type != null)
     {
         name = classReference.Type.Name;
     }
 }
コード例 #18
0
 public int GetClassIndex(ClassReference reference)
 {
     return(_buffer.GetClassIndex(reference));
 }
コード例 #19
0
ファイル: BaseCollector.cs プロジェクト: yuva2achieve/dot42
 public virtual void Collect(ClassReference @class)
 {
     Collect(@class as TypeReference);
 }
コード例 #20
0
        private dynamic Expression(Expr ast)
        {
            var lhs = ast.Left;
            var rhs = ast.Right;

            switch (ast.Token.TokenType)
            {
            case TokenType.Equals:
                if (lhs.AstType == AstTypes.ClassRef)
                {
                    // a litle trickery here. create a copy of the class reference
                    // with everytihng up to the second to last item. this gives you
                    // the workign memory space that the very last item should sit in
                    // then lets execute this as if we are asking for the memory space
                    // and finally assign the very last symbol to the calculated memory
                    // space we got

                    var classRef = (lhs as ClassReference);

                    var lastItem = classRef.Deferences.Last();

                    var fakeRef = new ClassReference(classRef.ClassInstance,
                                                     classRef.Deferences.Take(classRef.Deferences.Count - 1)
                                                     .ToList());

                    var space = GetValue(Exec(fakeRef));

                    Assign(lastItem, Exec(rhs), space);
                }

                else
                {
                    ValueMemory itemSpace = Get(lhs);

                    Assign(lhs, Exec(rhs), itemSpace != null ? itemSpace.Memory : null);
                }
                return(null);

            case TokenType.Word:
                return(Get(ast));

            case TokenType.Int:
                return(Convert.ToInt32(ast.Token.TokenValue));

            case TokenType.Float:
                return(Convert.ToDouble(ast.Token.TokenValue));

            case TokenType.QuotedString:
                return(ast.Token.TokenValue);

            case TokenType.Nil:
                return(TokenType.Nil);

            case TokenType.True:
                return(true);

            case TokenType.False:
                return(false);
            }

            if (TokenUtil.IsOperator(ast.Token))
            {
                return(ApplyOperation(ast));
            }

            return(null);
        }
コード例 #21
0
 public void Visit(ClassReference ast)
 {
     throw new NotImplementedException();
 }
コード例 #22
0
 public void Visit(ClassReference ast)
 {
     Exec(ast);
 }
コード例 #23
0
 public int GetClassIndex(ClassReference reference)
 {
     return(_builder.ConstantPoolBuffer.GetClassIndex(reference));
 }
コード例 #24
0
 private static void AddGenericParameterArguments(Prototype result, bool buildAsArray, int numParameters, string parameterBaseName, ClassReference annType, IList <Parameter> parameterArray)
 {
     if (buildAsArray)
     {
         // Add GenericInstance parameter (to pass the generic instance array of the declaring type)
         var paramType  = FrameworkReferences.ClassArray;
         var dparameter = new Parameter(paramType, parameterBaseName);
         dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
         result.Parameters.Add(dparameter);
         parameterArray.Add(dparameter);
     }
     else
     {
         for (int i = 0; i < numParameters; ++i)
         {
             var dparameter = new Parameter(FrameworkReferences.Class, parameterBaseName + (i + 1));
             dparameter.Annotations.Add(new Annotation(annType, AnnotationVisibility.Runtime));
             result.Parameters.Add(dparameter);
             parameterArray.Add(dparameter);
         }
     }
 }
コード例 #25
0
        /// <summary>
        /// Create the body of the equals method.
        /// </summary>
        private static MethodBody CreateEqualsBody(ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition equalsMethod, Prototype equalsPrototype, FieldDefinition instanceField, ClassReference delegateClass)
        {
            MethodBody body = new MethodBody(null);

            // This pointer and method argument.
            Register rthis  = body.AllocateRegister(RCategory.Argument, RType.Object);
            Register rother = body.AllocateRegister(RCategory.Argument, RType.Object);

            // Create code.
            var ins = body.Instructions;

            // Temporary parameter result.
            Register result = body.AllocateRegister(RCategory.Temp, RType.Value);

            // Prepare the return instruction.
            Instruction returnInstruction = new Instruction(RCode.Return, result);

            // Check if other object can be casted.
            ins.Add(new Instruction(RCode.Instance_of, delegateClass, new[] { result, rother }));
            ins.Add(new Instruction(RCode.If_eqz, returnInstruction, new[] { result })); // compare instance members

            // Cast of the other object.
            ins.Add(new Instruction(RCode.Check_cast, delegateClass, new[] { rother }));

            // Get instance fields of this and other.
            var thisInstance  = body.AllocateRegister(RCategory.Temp, RType.Object);
            var otherInstance = body.AllocateRegister(RCategory.Temp, RType.Object);

            // Load the instance fields.
            ins.Add(new Instruction(RCode.Iget_object, thisInstance, rthis)
            {
                Operand = instanceField
            });
            ins.Add(new Instruction(RCode.Iget_object, otherInstance, rother)
            {
                Operand = instanceField
            });

            // Compare the instance fields.
            ins.Add(new Instruction(RCode.If_eq, returnInstruction, new[] { thisInstance, otherInstance })); // compare instance members

            // Set result to false if not equal.
            ins.Add(new Instruction(RCode.Const, 0, new[] { result }));

            // Add return instructions
            ins.Add(returnInstruction);

            return(body);
        }
コード例 #26
0
        /// <summary>
        /// Create the body of the invoke method.
        /// </summary>
        private static MethodBody CreateInvokeBody(ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition calledMethod, XMethodDefinition invokeMethod, Prototype invokePrototype, Prototype calledMethodPrototype, FieldDefinition instanceField, ClassReference delegateClass)
        {
            var body  = new MethodBody(null);
            var rthis = body.AllocateRegister(RCategory.Argument, RType.Object);

            foreach (var p in invokePrototype.Parameters)
            {
                if (p.Type.IsWide())
                {
                    body.AllocateWideRegister(RCategory.Argument);
                }
                else
                {
                    var type = (p.Type is PrimitiveType) ? RType.Value : RType.Object;
                    body.AllocateRegister(RCategory.Argument, type);
                }
            }
            var incomingMethodArgs = body.Registers.ToArray();

            // Create code
            var      ins      = body.Instructions;
            Register instance = null;

            if (!calledMethod.IsStatic)
            {
                // load instance
                instance = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Iget_object, instance, rthis)
                {
                    Operand = instanceField
                });
            }
            // Invoke
            var calledMethodRef = calledMethod.GetReference(targetPackage);
            var inputArgs       = calledMethod.IsStatic ? incomingMethodArgs.Skip(1).ToArray() : incomingMethodArgs;

            // Cast arguments (if needed)
            var outputArgs = new List <Register>();

            if (!calledMethod.IsStatic)
            {
                outputArgs.Add(instance);
            }
            var parameterIndex = 0;

            for (var i = calledMethod.IsStatic ? 0 : 1; i < inputArgs.Length;)
            {
                var invokeType  = invokePrototype.Parameters[parameterIndex].Type;
                var inputIsWide = invokeType.IsWide();
                var calledType  = calledMethodPrototype.Parameters[parameterIndex].Type;
                if (!invokeType.Equals(calledType))
                {
                    // Add cast / unbox
                    var source = inputIsWide
                                     ? new RegisterSpec(inputArgs[i], inputArgs[i + 1], invokeType)
                                     : new RegisterSpec(inputArgs[i], null, invokeType);
                    var tmp = ins.Unbox(sequencePoint, source, calledMethod.Parameters[parameterIndex].ParameterType, compiler, targetPackage, body);
                    outputArgs.Add(tmp.Result.Register);
                    if (calledType.IsWide())
                    {
                        outputArgs.Add(tmp.Result.Register2);
                    }
                }
                else
                {
                    outputArgs.Add(inputArgs[i]);
                    if (calledType.IsWide())
                    {
                        outputArgs.Add(inputArgs[i + 1]);
                    }
                }
                i += inputIsWide ? 2 : 1;
                parameterIndex++;
            }

            // Actual call
            ins.Add(new Instruction(calledMethod.Invoke(calledMethod, null), calledMethodRef, outputArgs.ToArray()));

            // Collect return value
            var         invokeReturnType = invokePrototype.ReturnType;
            var         calledReturnType = calledMethodPrototype.ReturnType;
            var         needsBoxing      = !invokeReturnType.Equals(calledReturnType);
            Instruction returnInstruction;

            if (calledReturnType.IsWide())
            {
                var r = body.AllocateWideRegister(RCategory.Temp);
                ins.Add(new Instruction(RCode.Move_result_wide, r.Item1));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r.Item1, r.Item2, calledReturnType);
                    var tmp    = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                }
                else
                {
                    // Return wide
                    returnInstruction = new Instruction(RCode.Return_wide, r.Item1);
                }
            }
            else if (calledMethod.ReturnType.IsVoid())
            {
                // Void return
                returnInstruction = new Instruction(RCode.Return_void);
            }
            else if (calledReturnType is PrimitiveType)
            {
                // Single register return
                var r = body.AllocateRegister(RCategory.Temp, RType.Value);
                ins.Add(new Instruction(RCode.Move_result, r));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r, null, invokeReturnType);
                    var tmp    = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                }
                else
                {
                    // Return
                    returnInstruction = new Instruction(RCode.Return, r);
                }
            }
            else
            {
                var r = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Move_result_object, r));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r, null, invokeReturnType);
                    var tmp    = ins.Box(sequencePoint, source, invokeMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                }
                else
                {
                    // Return
                    returnInstruction = new Instruction(RCode.Return_object, r);
                }
            }

            // Call next delegate (if any)
            var next = body.AllocateRegister(RCategory.Temp, RType.Object);
            var multicastDelegateType = new ClassReference(targetPackage.NameConverter.GetConvertedFullName("System.MulticastDelegate"));
            var nextReference         = new FieldReference(multicastDelegateType, "next", multicastDelegateType);

            ins.Add(new Instruction(RCode.Iget_object, nextReference, new[] { next, rthis })); // load this.next
            var afterCallNext = new Instruction(RCode.Nop);

            ins.Add(new Instruction(RCode.If_eqz, afterCallNext, new[] { next })); // if next == null, continue
            ins.Add(new Instruction(RCode.Check_cast, delegateClass, new[] { next }));
            var nextInvokeMethod = new MethodReference(delegateClass, "Invoke", invokePrototype);
            var nextInvokeArgs = new[] { next }.Concat(incomingMethodArgs.Skip(1)).ToArray();

            ins.Add(new Instruction(RCode.Invoke_virtual, nextInvokeMethod, nextInvokeArgs));
            ins.Add(afterCallNext);

            // Add return instructions
            ins.Add(returnInstruction);

            return(body);
        }
コード例 #27
0
        /// <summary>
        /// Create the body of the equals method.
        /// </summary>
        private MethodBody CreateHashCodeBody(ClassReference delegateInstance)
        {
            MethodBody body = new MethodBody(null);

            // This pointer and method argument.
            Register rthis   = body.AllocateRegister(RCategory.Argument, RType.Object);
            Register tempObj = body.AllocateRegister(RCategory.Temp, RType.Object);
            Register tempInt = body.AllocateRegister(RCategory.Temp, RType.Value);

            Register tempArray       = body.AllocateRegister(RCategory.Temp, RType.Object);
            Register tempIdx         = body.AllocateRegister(RCategory.Temp, RType.Value);
            Register tempArrayLength = body.AllocateRegister(RCategory.Temp, RType.Value);

            // Create code.
            var ins = body.Instructions;

            // Temporary parameter result.
            Register result = body.AllocateRegister(RCategory.Temp, RType.Value);

            var hashCodeMethod = compiler.GetDot42InternalType("Java.Lang", "System")
                                 .Resolve()
                                 .Methods.First(m => m.Name == "IdentityHashCode")
                                 .GetReference(targetPackage);

            // Check if other object can be casted.
            ins.Add(new Instruction(RCode.Const_class, delegateInstance, new[] { tempObj }));
            ins.Add(new Instruction(RCode.Invoke_static, hashCodeMethod, new[] { tempObj }));
            ins.Add(new Instruction(RCode.Move_result, null, new[] { result }));

            if (instanceField != null)
            {
                ins.Add(new Instruction(RCode.Mul_int_lit, 397, new[] { result, result }));
                ins.Add(new Instruction(RCode.Iget_object, tempObj, rthis)
                {
                    Operand = instanceField
                });
                ins.Add(new Instruction(RCode.Invoke_static, tempObj)
                {
                    Operand = hashCodeMethod
                });
                ins.Add(new Instruction(RCode.Move_result, tempInt));
                ins.Add(new Instruction(RCode.Xor_int_2addr, result, tempInt));
            }

            foreach (var field in GenericTypeFields)
            {
                if (field.Type.Equals(FrameworkReferences.Class))
                {
                    ins.Add(new Instruction(RCode.Iget_object, tempObj, rthis)
                    {
                        Operand = field
                    });
                    ins.Add(new Instruction(RCode.Invoke_static, hashCodeMethod, new[] { tempObj }));
                    ins.Add(new Instruction(RCode.Move_result, null, new[] { tempInt }));
                    ins.Add(new Instruction(RCode.Xor_int_2addr, null, new[] { result, tempInt }));
                }
                else // array
                {
                    ins.Add(new Instruction(RCode.Iget_object, tempArray, rthis)
                    {
                        Operand = field
                    });
                    ins.Add(new Instruction(RCode.Array_length, tempArrayLength, rthis));
                    ins.Add(new Instruction(RCode.Const, tempIdx)
                    {
                        Operand = 0
                    });

                    Instruction loop;
                    ins.Add(loop = new Instruction());
                    ins.Add(new Instruction(RCode.Mul_int_lit, 397, new[] { result, result }));
                    ins.Add(new Instruction(RCode.Aget_object, tempObj, tempArray, tempIdx));
                    ins.Add(new Instruction(RCode.Invoke_static, hashCodeMethod, new[] { tempObj }));
                    ins.Add(new Instruction(RCode.Move_result, null, new[] { tempInt }));
                    ins.Add(new Instruction(RCode.Xor_int_2addr, null, new[] { result, tempInt }));

                    ins.Add(new Instruction(RCode.Add_int_lit8, 1, new[] { tempIdx, tempIdx }));
                    ins.Add(new Instruction(RCode.If_ltz, tempIdx, tempArrayLength)
                    {
                        Operand = loop
                    });
                }
            }

            // Add return instructions
            ins.Add(new Instruction(RCode.Return, null, new[] { result }));

            return(body);
        }
コード例 #28
0
        public void Visit(ClassReference ast)
        {
            if (!ResolvingTypes)
            {
                return;
            }

            var declaredSymbol = Resolve(ast.ClassInstance);

            if (declaredSymbol == null)
            {
                throw new UndefinedElementException(string.Format("Class instance '{0}' does not exist in current scope", ast.ClassInstance.Token.TokenValue));
            }

            var classScope = Resolve(declaredSymbol.Type.TypeName) as ClassSymbol;

            if (classScope == null)
            {
                classScope = Global.Resolve(declaredSymbol.Type.TypeName) as ClassSymbol;
            }

            var oldScope = Current;

            Current = classScope;

            foreach (var reference in ast.Deferences)
            {
                if (reference == ast.Deferences.Last())
                {
                    reference.CallingScope = oldScope;
                }

                reference.CurrentScope = Current;

                reference.IsPureDynamic = Current == null;

                reference.Visit(this);

                var field = Resolve(reference);


                if (field == null && !reference.IsPureDynamic)
                {
                    throw new InvalidSyntax(String.Format("Class {0} has no field named {1}", declaredSymbol.Type.TypeName, reference.Token.TokenValue));
                }

                if (field != null && field.Type.ExpressionType == ExpressionTypes.UserDefined)
                {
                    Current = Global.Resolve(field.Type.TypeName) as ClassSymbol;
                }
            }

            Current = oldScope;

            ast.AstSymbolType = ast.Deferences.Last().AstSymbolType;

            if (ast.AstSymbolType.ExpressionType == ExpressionTypes.Method)
            {
                try
                {
                    ast.AstSymbolType = (ast.AstSymbolType.Src as MethodDeclr).ReturnAst.AstSymbolType;
                }
                catch (Exception ex)
                {
                }
            }

            SetScope(ast);

            SetScope(ast.ClassInstance);
        }
コード例 #29
0
        /// <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);
        }
コード例 #30
0
        /// <summary>
        /// Create an android EnclosingClass annotation and attach it to the given provider.
        /// </summary>
        public static void AddEnclosingClassAnnotation(this IAnnotationProvider provider, ClassReference @class)
        {
            var annotation = new Annotation {
                Type = new ClassReference("dalvik/annotation/EnclosingClass"), Visibility = AnnotationVisibility.System
            };

            annotation.Arguments.Add(new AnnotationArgument("class", @class));
            provider.Annotations.Add(annotation);
        }