예제 #1
0
        public static CilType CastMaybeGeneric(CilType castType, bool valueOnly, JavaCode code)
        {
            if (!castType.IsGenericParameter)
            {
                return(castType);
            }

            if (!valueOnly)
            {
                GenericUtil.ValueLoad(code);
            }

            var genericMark = CilMain.GenericStack.Mark();

            var(resolvedType, resolvedIndex) = CilMain.GenericStack.Resolve(castType.JavaName);

            if (resolvedIndex == 0)
            {
                if (valueOnly)
                {
                    // this flag is set when called from LoadFieldAddress.  we can cast
                    // the generic field to the actual type only if it is a value type
                    if (resolvedType.IsValueClass)
                    {
                        castType = resolvedType;
                        code.NewInstruction(0xC0 /* checkcast */, castType.AsWritableClass, null);
                    }
                    else if (castType.IsByReference)
                    {
                        var boxedType = new BoxedType(resolvedType, false);
                        code.NewInstruction(0xC0 /* checkcast */, boxedType, null);
                        castType = boxedType;
                    }
                }
                else
                {
                    // this flag is clear whe called from LoadFieldValue and
                    // PushMethodReturnType.  we can cast to any known actual types.

                    var arrayRank = castType.GetMethodGenericParameter()?.ArrayRank ?? 0;
                    castType = (arrayRank == 0) ? resolvedType : resolvedType.AdjustRank(arrayRank);

                    if (!castType.IsReference)
                    {
                        var boxedType = new BoxedType(castType, false);
                        code.NewInstruction(0xC0 /* checkcast */, boxedType, null);
                        boxedType.GetValue(code);
                    }
                    else
                    {
                        code.NewInstruction(0xC0 /* checkcast */, castType.AsWritableClass, null);
                    }
                }
            }

            CilMain.GenericStack.Release(genericMark);
            return(castType);
        }
예제 #2
0
        public static bool CheckCast(CilType castType, bool @throw, JavaCode code)
        {
            if (object.ReferenceEquals(castType, GenericArrayType) ||
                (castType.IsArray && (castType.IsInterface ||
                                      castType.IsGenericParameter ||
                                      castType.ClassName == JavaType.ObjectType.ClassName ||
                                      castType.ClassName == CilType.SystemValueType.ClassName)))
            {
                // if casting to Object[], ValueType[], to an array of interface type,
                // or to an array of a generic parameter, we can't rely on a simple
                // 'checkcast' or 'instanceof', because the jvm will permit the cast
                // of a value type array to the aforementioned reference types.
                //
                // instead, we generate a call to system.Array.CheckCast in baselib,
                // except if we are generating code for the system.Array class itself.

                if (code.Method.Class.Name.StartsWith("system.Array"))
                {
                    return(false);
                }

                // note the caller of this method already popped the stack once.
                // which we have to undo that, before we push anything else.
                code.StackMap.PushStack(JavaType.ObjectType);   // array

                var method = new JavaMethodRef("CheckCast", JavaType.ObjectType);
                method.Parameters.Add(new JavaFieldRef("", JavaType.ObjectType));

                if (object.ReferenceEquals(castType, GenericArrayType) ||
                    castType.IsGenericParameter)
                {
                    method.Parameters.Add(new JavaFieldRef("", CilType.SystemTypeType));
                    GenericUtil.LoadMaybeGeneric(castType, code);
                    // CilType.SystemTypeType pushed to the stack
                }
                else
                {
                    method.Parameters.Add(new JavaFieldRef("", JavaType.ClassType));
                    code.NewInstruction(0x12 /* ldc */, castType.AdjustRank(-1), null);
                    code.StackMap.PushStack(JavaType.ClassType);
                }

                method.Parameters.Add(new JavaFieldRef("", JavaType.BooleanType));
                code.NewInstruction(0x12 /* ldc */, null, (int)(@throw ? 1 : 0));
                code.StackMap.PushStack(JavaType.IntegerType);  // boolean

                code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType, method);

                code.StackMap.PopStack(CilMain.Where);  // boolean
                code.StackMap.PopStack(CilMain.Where);  // class/type
                code.StackMap.PopStack(CilMain.Where);  // array

                return(true);
            }

            return(false);
        }
예제 #3
0
        static void LoadGenericInstance_3_N(CilType loadType, int genericCount,
                                            List <JavaFieldRef> parameters,
                                            JavaCode code)
        {
            if (genericCount <= 8)
            {
                // handling for the less common case of a generic instace with
                // less than eight arguments.  we don't check if the provided
                // type arguments are concrete or generic, and call a GetType()
                // override for the appropriate number of parameters.
                // note that the first class argument to GetType was alredy
                // inserted by our caller, LoadMaybeGeneric().

                for (int i = 0; i < genericCount; i++)
                {
                    LoadMaybeGeneric(loadType.GenericParameters[i], code);
                    // next parameter always has type system.Type
                    parameters.Add(new JavaFieldRef("", CilType.SystemTypeType));
                }
            }
            else
            {
                // generic handling for the less common case of a generic instace
                // with more than eight arguments.  we don't check if the provided
                // type arguments are concrete or generic.  we build an array of
                // system.Type references, and call GetType(class, system.Type[]).
                // note that the first class argument to GetType was alredy
                // inserted by our caller, LoadMaybeGeneric().

                var arrayOfType = CilType.SystemTypeType.AdjustRank(1);
                parameters.Add(new JavaFieldRef("", arrayOfType));

                code.NewInstruction(0x12 /* ldc */, null, genericCount);
                code.StackMap.PushStack(JavaType.IntegerType);

                code.NewInstruction(0xBD /* anewarray */, CilType.SystemTypeType, null);
                code.StackMap.PopStack(CilMain.Where);
                code.StackMap.PushStack(arrayOfType);

                for (int i = 0; i < genericCount; i++)
                {
                    code.NewInstruction(0x59 /* dup */, null, null);
                    code.StackMap.PushStack(arrayOfType);

                    code.NewInstruction(0x12 /* ldc */, null, i);
                    code.StackMap.PushStack(JavaType.IntegerType);

                    LoadMaybeGeneric(loadType.GenericParameters[i], code);

                    code.NewInstruction(0x53 /* aastore */, null, null);
                    code.StackMap.PopStack(CilMain.Where);
                    code.StackMap.PopStack(CilMain.Where);
                    code.StackMap.PopStack(CilMain.Where);
                }
            }
        }
예제 #4
0
        public static void Instance(JavaCode code, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst)
        {
            if (cilInst.Operand is TypeReference cilType && cilInst.Next != null)
            {
                var stackTop = (CilType)code.StackMap.PopStack(CilMain.Where);
                if (!stackTop.IsReference)
                {
                    throw new InvalidProgramException(); // top of stack is a primitive type
                }
                var      castType  = (CilType)CilType.From(cilType);
                JavaType castClass = CilType.From(cilType).AsWritableClass;

                if (GenericUtil.ShouldCallGenericCast(stackTop, castType) ||
                    castType.IsGenericParameter)
                {
                    code.StackMap.PushStack(stackTop);
                    // casting to a generic type is done via GenericType.TestCast
                    GenericUtil.CastToGenericType(cilType, 0, code);
                    code.StackMap.PopStack(CilMain.Where);  // stackTop
                    if (!castType.IsGenericParameter)
                    {
                        code.NewInstruction(0xC0 /* checkcast */, castClass, null);
                    }
                    code.StackMap.PushStack(castClass);
                }

                else if (CodeArrays.CheckCast(castType, false, code))
                {
                    // if casting to Object[], ValueType[], to an array of
                    // interface type, or to an array of a generic parameter,
                    // then CodeArrays.CheckCast already generated a call to
                    // system.Array.CheckCast in baselib, and we are done here

                    if (!castType.IsGenericParameter)
                    {
                        // avoid cast since T[] might be a primitive array
                        code.NewInstruction(0xC0 /* checkcast */, castClass, null);
                    }
                    code.StackMap.PushStack(castClass);
                }

                //
                // the cil 'isinst' casts the operand to the requested class,
                // but the jvm 'instanceof' only returns zero or one.  so we
                // also use 'checkcast' to get the jvm to acknowledge the cast
                //
                // however, if the cil 'isinst' is immediately followed by
                // 'brtrue' or 'brfalse' then we don't have to actually cast
                //

                else if (!TestForBranch(code, castClass, cilInst.Next))
                {
                    ushort nextLabel = (ushort)cilInst.Next.Offset;
                    TestAndCast(code, castClass, stackTop, nextLabel, locals);
                }
            }
예제 #5
0
        public static CilType WrapMethodGenericParameter(CilType fromType, string newJavaName = null)
        {
            var newType = new CilType();

            newType.CopyFrom(JavaType.ObjectType);
            newType.Flags             = fromType.Flags | IS_GEN_PRM;
            newType.JavaName          = newJavaName ?? fromType.JavaName;
            newType.GenericParameters = new List <CilType>();
            newType.GenericParameters.Add(fromType);
            return(newType);
        }
예제 #6
0
        CilType Clone()
        {
            var newType = new CilType();

            newType.CopyFrom(this);
            newType.JavaName          = JavaName;
            newType.SuperTypes        = SuperTypes;
            newType.GenericParameters = GenericParameters;
            newType.Flags             = Flags;
            return(newType);
        }
예제 #7
0
        bool LoadFieldValue(string fldName, CilType fldType, CilType fldClass,
                            bool isStatic, bool isVolatile)
        {
            if (isStatic && fldClass.HasGenericParameters)
            {
                fldClass = LoadStaticData(fldClass);
                isStatic = false;
            }

            byte op;

            if (!isStatic)
            {
                if (method.IsConstructor &&
                    LoadFieldInConstructor(fldName, fldType, fldClass))
                {
                    return(true);
                }

                PopObjectAndLoadFromSpan(fldClass);
                op = 0xB4; // getfield
            }
            else
            {
                op = 0xB2; // getstatic
            }
            code.NewInstruction(op, fldClass.AsWritableClass, new JavaFieldRef(fldName, fldType));

            if (fldType is BoxedType boxedType)
            {
                boxedType.GetValue(code, isVolatile);
                fldType = boxedType.UnboxedType;
                if (fldType.IsReference)
                {
                    if (fldType.IsGenericParameter && fldType.IsArray)
                    {
                        fldType = CodeArrays.GenericArrayType;
                    }
                    else if (!fldType.Equals(JavaType.ObjectType))
                    {
                        code.NewInstruction(0xC0 /* checkcast */, fldType.AsWritableClass, null);
                    }
                }
            }
            else if (fldType.IsGenericParameter)
            {
                var newType = GenericUtil.CastMaybeGeneric(fldType, false, code);
                fldType = (newType != fldType) ? newType : CilType.From(JavaType.ObjectType);
            }

            stackMap.PushStack(fldType);

            return(true);
        }
예제 #8
0
        public static void LoadMaybeGeneric(CilType loadType, JavaCode code)
        {
            if (loadType.IsGenericParameter)
            {
                LoadGeneric(loadType.JavaName, code);
            }
            else
            {
                // all GetType variants take a first parameter of type java.lang.Class
                List <JavaFieldRef> parameters = new List <JavaFieldRef>();
                parameters.Add(new JavaFieldRef("", JavaType.ClassType));

                int arrayRank = loadType.ArrayRank;
                if (arrayRank == 0 || (!loadType.IsGenericParameter))
                {
                    code.NewInstruction(0x12 /* ldc */, loadType.AsWritableClass, null);
                }
                else
                {
                    // for a generic type T[], we want to load just the element T,
                    // and then (see below) call MakeArrayType on the result
                    var loadTypeElem = loadType.AdjustRank(-arrayRank);
                    code.NewInstruction(0x12 /* ldc */, loadTypeElem.AsWritableClass, null);
                }
                code.StackMap.PushStack(JavaType.ClassType);

                if (loadType.HasGenericParameters)
                {
                    LoadGenericInstance(loadType, parameters, code);
                }

                code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType,
                                    new JavaMethodRef("GetType", CilType.SystemTypeType, parameters));

                for (int i = 0; i < parameters.Count; i++)
                {
                    code.StackMap.PopStack(CilMain.Where);
                }

                code.StackMap.PushStack(CilType.SystemTypeType);

                if (arrayRank != 0 && loadType.IsGenericParameter)
                {
                    code.NewInstruction(0x12 /* ldc */, null, (int)arrayRank);
                    code.StackMap.PushStack(JavaType.IntegerType);

                    code.NewInstruction(0xB6 /* invokevirtual */, CilType.SystemTypeType,
                                        new JavaMethodRef("MakeArrayType",
                                                          CilType.SystemTypeType, JavaType.IntegerType));

                    code.StackMap.PopStack(CilMain.Where);
                }
            }
        }
예제 #9
0
 public static bool Box(CilType intoType, JavaType spanType, JavaCode code)
 {
     if (spanType.Equals(SpanType) && intoType.IsByReference)
     {
         code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
                             new JavaMethodRef("Box", CilType.SystemValueType));
         code.StackMap.PushStack(CilType.SystemValueType);
         return(true);
     }
     return(false);
 }
예제 #10
0
        //
        // generate code to initialize the generic type field
        //

        public static void InitializeTypeField(CilType declType, JavaCode code)
        {
            code.NewInstruction(0x19 /* aload */, null, (int)0);
            code.StackMap.PushStack(declType);

            LoadMaybeGeneric(declType, code);

            code.NewInstruction(0xC0 /* checkcast */, CilType.SystemRuntimeTypeType, null);
            code.NewInstruction(0xB5 /* putfield */, declType, ConcreteTypeField);

            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);
        }
예제 #11
0
 public override JavaType ResolveConflict(JavaType other)
 {
     // the ternary operator ?: may produce code that causes a conflict:
     //      object x = flag ? (object) new A() : (object) new B();
     // if we detect such a conflict at a branch target, we assume this
     // is the cause, and set the stack elements to a common denominator
     // or to the lowest common denominator, java.lang.Object
     if (IsReference && other.IsReference && other is CilType other2 &&
         (!this.IsValueClass) && (!other2.IsValueClass))
     {
         return(FindCommonSuperType(this, other2) ?? CilType.From(JavaType.ObjectType));
     }
     return(null);
예제 #12
0
        public static void MakeValueClass(JavaClass valueClass, CilType fromType,
                                          int numCastableInterfaces)
        {
            valueClass.Super = CilType.SystemValueType.ClassName;

            CreateDefaultConstructor(valueClass, fromType, numCastableInterfaces, true);
            CreateValueMethods(valueClass, fromType, numCastableInterfaces);

            if ((valueClass.Flags & JavaAccessFlags.ACC_ABSTRACT) == 0)
            {
                valueClass.Flags |= JavaAccessFlags.ACC_FINAL;
            }
        }
예제 #13
0
 public static bool Clear(JavaType stackTop, CilType dataType, JavaCode code)
 {
     if (stackTop.Equals(SpanType) &&
         dataType.IsValueClass &&
         code.Method.Class.Name != SpanType.ClassName)
     {
         // if initobj is called on a span or pointer, call Span<T>.Clear()
         code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
                             new JavaMethodRef("Clear", JavaType.VoidType));
         return(true);
     }
     return(false);
 }
예제 #14
0
        //
        // create default parameterless constructor.  (it will be called at the
        // top of any method which allocates a value type local.)  and note that
        // if this is a generic value type, this new constructor will be further
        // modified in GenericUtil.MakeGenericClass.FixConstructorsInFrom
        //

        static void CreateDefaultConstructor(JavaClass valueClass, CilType fromType,
                                             int numCastableInterfaces, bool initFields)
        {
            foreach (var oldMethod in valueClass.Methods)
            {
                if (oldMethod.Name == "<init>")
                {
                    return;
                }
            }

            var code = CilMethod.CreateConstructor(valueClass, fromType.GenericParametersCount, true);

            if (fromType.HasGenericParameters)
            {
                code.StackMap = new JavaStackMap();
                var genericMark = CilMain.GenericStack.Mark();
                CilMain.GenericStack.EnterMethod(fromType, code.Method, true);

                // initialize the generic type field
                GenericUtil.InitializeTypeField(fromType, code);

                CilMain.GenericStack.Release(genericMark);
                code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where);
            }

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

            if (initFields)
            {
                var oldLabel = code.SetLabel(0xFFFF);

                InitializeInstanceFields(valueClass, fromType, null, code);

                code.SetLabel(oldLabel);
            }

            code.NewInstruction(0x19 /* aload */, null, (int)0);
            code.NewInstruction(0xB7 /* invokespecial */, new JavaType(0, 0, valueClass.Super),
                                new JavaMethodRef("<init>", JavaType.VoidType));

            code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where);
            if (code.MaxStack < 1)
            {
                code.MaxStack = 1;
            }

            code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null);
        }
예제 #15
0
        public void Address(CilType arrayType)
        {
            stackMap.PopStack(CilMain.Where);       // index

            if (arrayType == null)
            {
                arrayType = (CilType)stackMap.PopStack(CilMain.Where);
            }
            else
            {
                stackMap.PopStack(CilMain.Where);   // array
            }
            var elemType = arrayType.AdjustRank(-arrayType.ArrayRank);

            if (elemType.IsReference)
            {
                if (elemType.IsGenericParameter)
                {
                    // call system.Array.Box(object array, int index)
                    code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType,
                                        new JavaMethodRef("Box", CilType.SystemValueType,
                                                          JavaType.ObjectType, JavaType.IntegerType));
                }
                else if (elemType.IsValueClass)
                {
                    code.NewInstruction(0x32 /* aaload */, null, null);
                }
                else
                {
                    // call system.Reference.Box(object a, int i)
                    elemType = new BoxedType(elemType, false);
                    code.NewInstruction(0xB8 /* invokestatic */, elemType,
                                        new JavaMethodRef("Box", elemType,
                                                          JavaType.ObjectType, JavaType.IntegerType));
                }
                stackMap.PushStack(elemType);
            }
            else
            {
                // call system.(PrimitiveType).Box(primitiveType[] a, int i)
                var typeCode = elemType.PrimitiveType;

                stackMap.PushStack(new BoxedType(elemType, false));

                arrayType = elemType.AdjustRank(1);
                elemType  = elemType.AsWritableClass;
                code.NewInstruction(0xB8 /* invokestatic */, elemType,
                                    new JavaMethodRef("Box", elemType, arrayType, JavaType.IntegerType));
            }
        }
예제 #16
0
        //
        // create a java generic class signature, this is used by
        // system.RuntimeType in baselib to provide more accurate reflection
        //

        public static string MakeGenericSignature(TypeDefinition fromType, string superName)
        {
            string signature = "";

            if (fromType.GenericParameters.Count > 0)
            {
                signature = "<";
                foreach (var prm in fromType.GenericParameters)
                {
                    signature += prm.Name + ":Ljava/lang/Object;";
                }
                signature += ">";
            }
            signature += ClassSignature(superName, fromType.BaseType);
            if (fromType.HasInterfaces)
            {
                foreach (var ifc in fromType.Interfaces)
                {
                    var name = CilType.From(ifc.InterfaceType).JavaName;
                    if (name != "system.ValueMethod")
                    {
                        signature += ClassSignature(name, ifc.InterfaceType);
                    }
                }
            }
            return(signature);

            string ClassSignature(string className, TypeReference fromType)
            {
                var signature = "L" + className.Replace('.', '/');

                if (fromType is GenericInstanceType fromGenericType)
                {
                    signature += "<";
                    foreach (var arg in fromGenericType.GenericArguments)
                    {
                        if (arg is GenericParameter genericArg)
                        {
                            signature += "T" + arg.Name + ";";
                        }
                        else
                        {
                            signature += ClassSignature(CilType.From(arg).JavaName, arg);
                        }
                    }
                    signature += ">";
                }
                return(signature + ";");
            }
        }
예제 #17
0
 public static bool MaybeGetProxy(CilType fromType, CilType intoType, JavaCode code)
 {
     if (fromType.IsArray ||
         object.ReferenceEquals(fromType, GenericArrayType) ||
         fromType.Equals(JavaType.StringType))
     {
         if (GenericUtil.ShouldCallGenericCast(fromType, intoType))
         {
             code.NewInstruction(0xB8 /* invokestatic */,
                                 SystemArrayType, GetProxyMethod);
             return(true);
         }
     }
     return(false);
 }
예제 #18
0
        public static CilType LoadStaticData(CilType fldClass, JavaCode code)
        {
            LoadMaybeGeneric(fldClass, code);
            code.StackMap.PopStack(CilMain.Where);

            code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType,
                                new JavaMethodRef("GetStatic",
                                                  JavaType.ObjectType, CilType.SystemTypeType));

            var returnType = PushStaticDataType(fldClass, code);

            code.NewInstruction(0xC0 /* checkcast */, returnType, null);

            return(returnType);
        }
예제 #19
0
        void PopObjectAndLoadFromSpan(CilType fldClass)
        {
            var stackTop = stackMap.PopStack(CilMain.Where);

            stackMap.PushStack(stackTop);

            if (fldClass.IsValueClass &&
                CodeSpan.LoadStore(true, (CilType)stackTop, null, fldClass, code))
            {
                stackMap.PopStack(CilMain.Where);
                code.NewInstruction(0xC0 /* checkcast */, fldClass, null);
            }

            // pop object reference
            stackMap.PopStack(CilMain.Where);
        }
예제 #20
0
        public static CilType MakeSpanOf(CilType fromType)
        {
            if (!fromType.IsPointer)
            {
                throw new ArgumentException();
            }
            var newType = CodeSpan.SpanType.Clone();

            newType.Flags |= VALUE;
            // we add the original buffer type as a generic parameter,
            // but we do not mark with HAS_GEN_PRM HasGenericParameters,
            // similar to WrapMethodGenericParameter
            newType.GenericParameters = new List <CilType>();
            newType.GenericParameters.Add(fromType);
            return(newType);
        }
예제 #21
0
        static CilInterface ImportPlainInterface(CilType interfaceType, List <CilInterface> list)
        {
            foreach (var ifc in list)
            {
                if (ifc.InterfaceType.JavaName == interfaceType.JavaName &&
                    ifc.GenericTypes == null)
                {
                    return(ifc);
                }
            }

            var myInterface = new CilInterface();

            myInterface.InterfaceType = interfaceType;
            return(myInterface);
        }
예제 #22
0
        public static void BuildGenericProxy(CilInterfaceMethod ifcMethod, string methodSuffix,
                                             CilType intoType, List <CilInterfaceMethod> classMethods,
                                             JavaClass ifcClass)
        {
            CilMethod targetMethod = null;

            //Console.WriteLine("\n***** LOOKING FOR INTERFACE METHOD " + ifcMethod + " (SUFFIX " + methodSuffix + ") AKA " + ifcMethod.Method);

            foreach (var clsMethod in classMethods)
            {
                /*Console.WriteLine("> LOOKING AT "
                 + (clsMethod.Method.IsExplicitImpl ? "EXPLICIT " : "")
                 + "CLASS METHOD " + clsMethod + " AKA " + clsMethod.Method);*/

                if (ifcMethod.GenericCompare(clsMethod))
                {
                    if (clsMethod.Method.IsExplicitImpl)
                    {
                        // a matching explicit override method is the best match,
                        // and we can immediately stop searching
                        targetMethod = clsMethod.Method;
                        break;
                    }
                    else
                    {
                        // more than one method may match, if a derived type overrides
                        // or hides a method that also exists in a base type.  but the
                        // derived (primary) type methods always come first.
                        if (targetMethod == null)
                        {
                            targetMethod = clsMethod.Method;
                        }
                    }
                }
            }

            if (targetMethod == null)
            {
                throw CilMain.Where.Exception(
                          $"missing method '{ifcMethod.Method}' "
                          + $"(for interface '{ifcMethod.Method.DeclType}')");
            }

            // Console.WriteLine("INTERFACE METHOD " + ifcMethod.Method + " TARGET " + targetMethod);

            BuildGenericProxy2(ifcMethod, targetMethod, true, intoType, ifcClass);
        }
예제 #23
0
        public static void ValueCopy(CilType valueType, JavaCode code, bool swap = false)
        {
            // if 'from' value is pushed before 'into' object, call with swap == false
            // if 'into' object is pushed before 'from' value, call with swap == true
            if (valueType.IsGenericParameter)
            {
                if (swap)
                {
                    code.NewInstruction(0x5F /* swap */, null, null);
                }
                else
                {
                    // if storing a primitive value into a generic type,
                    // and the generic type can be resolved to a primitive type,
                    // then use a boxed-set method call

                    var stackArray    = code.StackMap.StackArray();
                    int stackArrayLen = stackArray.Length;
                    if (stackArrayLen > 0 && (!stackArray[stackArrayLen - 1].IsReference))
                    {
                        var genericMark = CilMain.GenericStack.Mark();
                        var(primitiveType, _) = CilMain.GenericStack.Resolve(valueType.JavaName);
                        CilMain.GenericStack.Release(genericMark);

                        if (!primitiveType.IsReference)
                        {
                            var boxedType = new BoxedType(primitiveType, false);
                            code.NewInstruction(0xC0 /* checkcast */, boxedType, null);
                            boxedType.SetValueVO(code);
                            return;
                        }
                    }
                }

                code.NewInstruction(0xB8 /* invokestatic */, SystemGenericType,
                                    new JavaMethod("Copy", JavaType.VoidType,
                                                   JavaType.ObjectType, JavaType.ObjectType));
            }
            else
            {
                if (swap)
                {
                    code.NewInstruction(0x5F /* swap */, null, null);
                }
                CilMethod.ValueMethod(CilMethod.ValueCopyTo, code);
            }
        }
예제 #24
0
        public bool IsDerivedFrom(CilType otherBaseType)
        {
            var obj = this;

            for (;;)
            {
                if (obj.JavaName.Equals(otherBaseType.JavaName))
                {
                    return(true);
                }
                if (obj.SuperTypes == null || obj.SuperTypes.Count == 0)
                {
                    return(false);
                }
                obj = obj.SuperTypes[0];
            }
        }
예제 #25
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();
            }
        }
예제 #26
0
        public static CilType From(JavaType oldType)
        {
            var newType = new CilType();

            newType.CopyFrom(oldType);
            if (newType.IsReference)
            {
                newType.JavaName = newType.ClassName;
            }
            else
            {
                string s;
                switch (newType.PrimitiveType)
                {
                case TypeCode.Empty:    s = "system.Void";      break;

                case TypeCode.Boolean:  s = "system.Boolean";   break;

                case TypeCode.Char:     s = "system.Char";      break;

                case TypeCode.SByte:    s = "system.SByte";     break;

                case TypeCode.Byte:     s = "system.Byte";      break;

                case TypeCode.Int16:    s = "system.Int16";     break;

                case TypeCode.UInt16:   s = "system.UInt16";    break;

                case TypeCode.Int32:    s = "system.Int32";     break;

                case TypeCode.UInt32:   s = "system.UInt32";    break;

                case TypeCode.Int64:    s = "system.Int64";     break;

                case TypeCode.UInt64:   s = "system.UInt64";    break;

                case TypeCode.Single:   s = "system.Single";    break;

                case TypeCode.Double:   s = "system.Double";    break;

                default:                throw new ArgumentException();
                }
                newType.JavaName = s;
            }
            return(newType);
        }
예제 #27
0
        static void LoadGeneric(CilType loadType, int loadIndex, JavaCode code)
        {
            if (loadIndex < 0)
            {
                if (code.Method.Class != null &&
                    (code.Method.Class
                     .Flags & JavaAccessFlags.ACC_INTERFACE) != 0)
                {
                    // a method compiled as part of an interface does not
                    // have access to the generic-type member field
                    throw CilMain.Where.Exception(
                              "unsupported generic argument reference in interface method");
                }

                // generic type is accessible through the generic-type member field

                code.NewInstruction(0x19 /* aload */, null, (int)0);
                code.NewInstruction(0xB4 /* getfield */, loadType, ConcreteTypeField);
                code.StackMap.PushStack(ConcreteTypeField.Type);

                code.NewInstruction(0x12 /* ldc */, null, -loadIndex - 1);
                code.StackMap.PushStack(JavaType.IntegerType);

                // call system.RuntimeType.Argument(RuntimeType runtimeType, int typeArgumentIndex)
                code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType,
                                    new JavaMethodRef("Argument", CilType.SystemTypeType,
                                                      CilType.SystemRuntimeTypeType, JavaType.IntegerType));

                code.StackMap.PopStack(CilMain.Where);              // integer
                code.StackMap.PopStack(CilMain.Where);              // generic type field
                code.StackMap.PushStack(CilType.SystemTypeType);    // type result
            }
            else if (loadIndex > 0)
            {
                // generic type is accessible through a parameter

                code.NewInstruction(0x19 /* aload */, null, (int)(loadIndex - 1));
                code.StackMap.PushStack(CilType.SystemTypeType);
            }
            else
            {
                // generic type is known to be a constant

                LoadMaybeGeneric(loadType, code);
            }
        }
예제 #28
0
 static CilType FindCommonSuperType(CilType type1, CilType type2)
 {
     if (type1.SuperTypes != null && type2.SuperTypes != null)
     {
         foreach (var sup1 in type1.SuperTypes)
         {
             if (!sup1.Equals(JavaType.ObjectType))
             {
                 if (FindCommonSuperTypeRecursive(sup1, type2))
                 {
                     return(sup1);
                 }
             }
         }
     }
     return(null);
 }
예제 #29
0
 static bool FindCommonSuperTypeRecursive(CilType sup1, CilType type2)
 {
     if (type2.SuperTypes != null)
     {
         foreach (var sup2 in type2.SuperTypes)
         {
             if (sup2.Equals(sup1))
             {
                 return(true);
             }
             if (FindCommonSuperTypeRecursive(sup1, sup2))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
예제 #30
0
        bool LoadFieldAddress(string fldName, CilType fldType, CilType fldClass, bool isStatic)
        {
            if (!(fldType is BoxedType))
            {
                if (!fldType.IsValueClass)
                {
                    throw CilMain.Where.Exception($"cannot load address of unboxed field '{fldName}'");
                }
            }

            if (isStatic && fldClass.HasGenericParameters)
            {
                fldClass = LoadStaticData(fldClass);
                isStatic = false;
            }

            byte op;

            if (!isStatic)
            {
                PopObjectAndLoadFromSpan(fldClass);
                op = 0xB4; // getfield
            }
            else
            {
                op = 0xB2; // getstatic
            }
            code.NewInstruction(op, fldClass.AsWritableClass, new JavaFieldRef(fldName, fldType));

            if (fldType is ThreadBoxedType tlsType)
            {
                tlsType.GetInnerObject(code);
            }

            if (fldType.IsGenericParameter)
            {
                fldType = GenericUtil.CastMaybeGeneric(fldType, true, code);
            }

            stackMap.PushStack(fldType);

            return(true);
        }