Exemple #1
0
        void LoadStoreField(Code op, object data)
        {
            bool ok = false;

            if (data is FieldReference fieldRef)
            {
                var fldName  = CilMain.MakeValidMemberName(fieldRef.Name);
                var fldClass = CilMain.GenericStack.EnterType(fieldRef.DeclaringType);
                var fldType  = ValueUtil.GetBoxedFieldType(fldClass, fieldRef);

                if (fldClass.Equals(JavaType.StringType) ||
                    fldClass.Equals(JavaType.ThrowableType))
                {
                    // generally we translate System.String to java.lang.String,
                    // and System.Exception to java.lang.Throwable,
                    // but not in the case of a field reference
                    fldClass = CilType.From(new JavaType(0, 0, fldClass.JavaName));
                }

                bool isLoad     = (op != Code.Stfld && op != Code.Stsfld);
                bool isStatic   = (op == Code.Ldsfld || op == Code.Ldsflda || op == Code.Stsfld);
                bool isAddress  = (op == Code.Ldflda || op == Code.Ldsflda);
                bool isVolatile = CheckVolatile(fldType);

                if (isLoad)
                {
                    if (isAddress)
                    {
                        ok = LoadFieldAddress(fldName, fldType, fldClass, isStatic);
                    }
                    else
                    {
                        ok = LoadFieldValue(fldName, fldType, fldClass, isStatic, isVolatile);
                    }
                }
                else
                {
                    ok = StoreFieldValue(fldName, fldType, fldClass, isStatic, isVolatile);
                }
            }

            if (!ok)
            {
                throw new InvalidProgramException();
            }
        }
        void InsertMethodInitCode()
        {
            if (method.IsStatic)
            {
                if ((!method.IsConstructor) && method.DeclType.HasGenericParameters)
                {
                    // in a static method in a generic class, if the class has
                    // a static initializer, then we want to start with a call to
                    // GetType(), to force initialization of the static data class

                    foreach (var m in defMethod.DeclaringType.Methods)
                    {
                        if (m.IsConstructor && m.IsStatic)
                        {
                            GenericUtil.LoadMaybeGeneric(method.DeclType, code);
                            code.NewInstruction(0x57 /* pop */, null, null);
                            code.StackMap.PopStack(CilMain.Where);
                            break;
                        }
                    }
                }
            }
            else if (method.IsConstructor)
            {
                if (method.DeclType.HasGenericParameters)
                {
                    // in a constructor of a generic class, we want to start
                    // with a call to GetType() and store the result in the
                    // $type field
                    GenericUtil.InitializeTypeField(method.DeclType, code);
                }

                // init the array of generic interfaces
                InterfaceBuilder.InitInterfaceArrayField(
                    method.DeclType, numCastableInterfaces, code, 0);

                // in any constructor, we want to allocate boxed instance fields
                ValueUtil.InitializeInstanceFields(newMethod.Class, method.DeclType,
                                                   defMethodBody.Instructions, code);
            }
        }
Exemple #3
0
        int InitLocalsVars(MethodBody cilBody, List <CilType> localTypes, int nextIndex)
        {
            int highestIndex = -1;

            if (cilBody.HasVariables)
            {
                foreach (var cilVar in cilBody.Variables)
                {
                    if (cilVar.Index > highestIndex)
                    {
                        highestIndex = cilVar.Index;
                    }
                }
            }

            varToLocalMap = new int[highestIndex + 1];

            if (cilBody.HasVariables)
            {
                foreach (var cilVar in cilBody.Variables)
                {
                    CilMain.Where.Push("local #" + cilVar.Index);

                    var genericMark = CilMain.GenericStack.Mark();
                    var varType     = CilMain.GenericStack.EnterType(cilVar.VariableType);

                    if (varType.IsValueClass || varType.IsPointer)
                    {
                        bool isByReference = varType.IsByReference;

                        if (varType.IsPointer)
                        {
                            varType = CilType.MakeSpanOf(varType);
                        }

                        // value classes are allocated at the top of the method
                        if (!isByReference)
                        {
                            ValueUtil.InitLocal(varType, nextIndex, code);
                            varType = varType.MakeClonedAtTop();
                        }
                    }
                    else if (varType.IsByReference)
                    {
                        varType = new BoxedType(varType, false);
                    }
                    else if (varType.IsArray && varType.IsGenericParameter)
                    {
                        // note that GenericArrayType is compared by reference
                        // in CodeArrays, to detect an array of a generic type T[]
                        varType = CodeArrays.GenericArrayType;
                    }

                    varToLocalMap[cilVar.Index] = nextIndex;
                    nextIndex += varType.Category;

                    localTypes.Add(varType);
                    while (nextIndex > localTypes.Count)
                    {
                        localTypes.Add(null);
                    }

                    CilMain.GenericStack.Release(genericMark);
                    CilMain.Where.Pop();
                }
            }

            return(nextIndex);
        }
Exemple #4
0
        internal static void BuildJavaClass(TypeDefinition cilType, JavaClass parentClass)
        {
            CilMain.Where.Push($"class '{cilType.FullName}'");

            var genericMark = CilMain.GenericStack.Mark();
            var myType      = CilMain.GenericStack.EnterType(cilType);

            var jclass = new JavaClass();

            jclass.Name  = myType.JavaName;
            jclass.Flags = AttributesToAccessFlags(cilType.Attributes, myType.IsInterface);

            if (myType.IsInterface)
            {
                jclass.Super = JavaType.ObjectType.ClassName; // java.lang.Object
            }
            else if (cilType.BaseType != null)
            {
                var myBaseType = CilType.From(cilType.BaseType);
                jclass.Super = myBaseType.Equals(JavaType.ObjectType)
                             ? JavaType.ObjectType.ClassName // java.lang.Object
                             : myBaseType.JavaName;
            }
            else
            {
                throw CilMain.Where.Exception("missing base class");
            }

            var myInterfaces = ImportInterfaces(jclass, myType, cilType);

            int numCastableInterfaces = myType.IsGenericThisOrSuper
                                      ? InterfaceBuilder.CastableInterfaceCount(myInterfaces)
                                      : 0;

            ImportFields(jclass, cilType, myType.IsRetainName);

            ImportMethods(jclass, cilType, numCastableInterfaces);

            if (myType.JavaName == "system.Convert")
            {
                DiscardBase64MethodsInConvertClass(jclass);
            }

            ValueUtil.InitializeStaticFields(jclass, myType);

            if (myType.IsValueClass)
            {
                ValueUtil.MakeValueClass(jclass, myType, numCastableInterfaces);
            }

            else if (myType.IsEnum)
            {
                ValueUtil.MakeEnumClass(jclass, myType,
                                        cilType.HasCustomAttribute("System.FlagsAttribute", true));
            }

            else if (myType.IsDelegate)
            {
                var delegateInterface = Delegate.FixClass(jclass, myType);
                CilMain.JavaClasses.Add(delegateInterface);
            }

            // if derives directly from object, and does not implement ToString
            CodeBuilder.CreateToStringMethod(jclass);

            ResetFieldReferences(jclass);

            LinkClasses(jclass, parentClass, cilType);

            var interfaceClasses = InterfaceBuilder.BuildProxyMethods(
                myInterfaces, cilType, myType, jclass);

            if (interfaceClasses != null)
            {
                foreach (var childClass in interfaceClasses)
                {
                    CilMain.JavaClasses.Add(childClass);
                }
            }

            if (myType.HasGenericParameters)
            {
                JavaClass dataClass;

                if (!myType.IsInterface)
                {
                    dataClass = GenericUtil.MakeGenericClass(jclass, myType);
                    if (dataClass != null)
                    {
                        CilMain.JavaClasses.Add(dataClass);
                    }
                }
                else
                {
                    dataClass = null;
                }

                JavaClass infoClass = jclass;
                if (myType.IsInterface)
                {
                    // Android 'D8' desugars static methods on an interface by
                    // moving into a separate class, so we do it ourselves.
                    // see also system.RuntimeType.CreateGeneric() in baselib
                    infoClass = CilMain.CreateInnerClass(jclass, jclass.Name + "$$info");
                    CilMain.JavaClasses.Add(infoClass);
                }

                GenericUtil.CreateGenericInfoMethod(infoClass, dataClass, myType);

                GenericUtil.CreateGenericVarianceField(infoClass, myType, cilType);
            }

            if (myType.IsGenericThisOrSuper)
            {
                jclass.Signature = GenericUtil.MakeGenericSignature(cilType, jclass.Super);

                if (!myInterfaces.Exists(x => x.InterfaceType.JavaName == "system.IGenericObject"))
                {
                    if (!myType.IsInterface)
                    {
                        // create IGenericObject methods GetType and TryCast
                        // only if class did not already implement IGenericObject
                        if (!myType.HasGenericParameters)
                        {
                            GenericUtil.BuildGetTypeMethod(jclass, myType);
                        }

                        InterfaceBuilder.BuildTryCastMethod(
                            myInterfaces, myType, numCastableInterfaces, jclass);
                    }
                }
            }

            CilMain.GenericStack.Release(genericMark);
            CilMain.Where.Pop();
        }
Exemple #5
0
        public static void ImportFields(JavaClass jclass, TypeDefinition cilType, bool isRetainName)
        {
            if (cilType.HasFields)
            {
                int n = cilType.Fields.Count;
                if (n > 0)
                {
                    if (isRetainName)
                    {
                        throw CilMain.Where.Exception("fields not supported in a [RetainName] type");
                    }

                    jclass.Fields = new List <JavaField>(n);
                    for (int i = 0; i < n; i++)
                    {
                        var cilField = cilType.Fields[i];
                        CilMain.Where.Push($"field '{cilField.Name}'");

                        if (cilField.InitialValue.Length != 0)
                        {
                            throw CilMain.Where.Exception("unsupported InitialValue in field");
                        }

                        var myField = new JavaField();
                        myField.Name  = CilMain.MakeValidMemberName(cilField.Name);
                        myField.Class = jclass;
                        myField.Flags = AttributesToAccessFlags(
                            cilField.Attributes,
                            (cilType.HasNestedTypes || cilType.HasGenericParameters));

                        if (cilType.IsEnum)
                        {
                            myField.Type = CilType.From(cilField.FieldType);

                            if (cilField.Constant != null)
                            {
                                myField.InitConstant(cilField.Constant, CilMain.Where);
                            }
                        }
                        else
                        {
                            myField.Type = ValueUtil.GetBoxedFieldType(null, cilField);

                            if (((CilType)myField.Type).IsValueClass)
                            {
                                myField.Constant = cilField;
                            }

                            else
                            {
                                if (cilField.Constant != null)
                                {
                                    myField.InitConstant(cilField.Constant, CilMain.Where);
                                }

                                if (((CilType)myField.Type).IsVolatile)
                                {
                                    myField.Flags |= JavaAccessFlags.ACC_VOLATILE;
                                }
                            }
                        }

                        jclass.Fields.Add(myField);

                        CilMain.Where.Pop();
                    }
                }
            }
        }