Ejemplo n.º 1
0
        public static void CompareEq(JavaType stackTop, JavaType stackTop2,
                                     Mono.Cecil.Cil.Instruction cilInst, JavaCode code)
        {
            if (stackTop.Equals(SpanType) &&
                (stackTop2.PrimitiveType == TypeCode.Int64 ||
                 stackTop2.PrimitiveType == TypeCode.UInt64))
            {
                // compare Span with long
                throw new InvalidProgramException();
            }

            if (stackTop2.Equals(SpanType) &&
                (stackTop.PrimitiveType == TypeCode.Int64 ||
                 stackTop.PrimitiveType == TypeCode.UInt64))
            {
                if (cilInst.Previous == null ||
                    cilInst.Previous.OpCode.Code != Code.Conv_U ||
                    cilInst.Previous.Previous == null ||
                    cilInst.Previous.Previous.OpCode.Code != Code.Ldc_I4_0)
                {
                    // make sure the program is comparing the span address against
                    // a zero value, which we can convert to a null reference.
                    //      ldarg.1 (span argument)
                    //      ldc.i4.0
                    //      conv.u
                    //      bne.un label
                    throw new InvalidProgramException();
                }
                // compare long with Span
                code.NewInstruction(0x58 /* pop2 */, null, null);
                code.NewInstruction(0x01 /* aconst_null */, null, null);
            }
        }
Ejemplo n.º 2
0
        static int ConvertToLong(JavaCode code, TypeCode oldType, TypeCode newType)
        {
            if (oldType == TypeCode.Int64 || oldType == TypeCode.UInt64)
            {
                return(0x00); // nop
            }
            if (oldType == TypeCode.Double)
            {
                return(0x8F); // d2l
            }
            if (oldType == TypeCode.Single)
            {
                return(0x8C); // f2l
            }
            if (newType == TypeCode.UInt64)
            {
                code.NewInstruction(0x85 /* i2l */, null, null);
                code.StackMap.PushStack(JavaType.LongType);
                long maskValue = (oldType == TypeCode.Byte)   ? 0xFF
                               : (oldType == TypeCode.UInt16) ? 0xFFFF
                                                              : 0xFFFFFFFF;
                code.NewInstruction(0x12 /* ldc */, null, (long)maskValue);
                code.StackMap.PushStack(JavaType.LongType);
                code.StackMap.PopStack(CilMain.Where);
                code.StackMap.PopStack(CilMain.Where);
                return(0x7F); // land
            }

            CilMain.MakeRoomForCategory2ValueOnStack(code);
            return(0x85); // i2l
        }
Ejemplo n.º 3
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;
                    int    localIndex = locals.GetTempIndex(stackTop);

                    TestAndCast(code, castClass, stackTop, nextLabel, localIndex);

                    locals.FreeTempIndex(localIndex);
                }
            }
Ejemplo n.º 4
0
        static void LoadGeneric(CilType loadType, int loadIndex, JavaCode code)
        {
            if (loadIndex < 0)
            {
                // 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(int typeArgumentIndex)
                code.NewInstruction(0xB6 /* invokevirtual */, CilType.SystemRuntimeTypeType,
                                    new JavaMethodRef("Argument", CilType.SystemTypeType, 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);
            }
        }
Ejemplo n.º 5
0
 public static void LoadParameterlessGeneric(CilType loadType, JavaCode code)
 {
     code.NewInstruction(0x12 /* ldc */, loadType.AsWritableClass, null);
     code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType,
                         new JavaMethodRef("GetType", CilType.SystemTypeType, JavaType.ClassType));
     code.StackMap.PushStack(CilType.SystemTypeType);
 }
Ejemplo n.º 6
0
        static byte TestBool(JavaCode code, JavaType stackTop)
        {
            if (stackTop.IsReference)
            {
                return(0xC7); // ifnonnull
            }

            if (stackTop.PrimitiveType == TypeCode.Int64 ||
                stackTop.PrimitiveType == TypeCode.UInt64 ||
                stackTop.PrimitiveType == TypeCode.Int32 ||
                stackTop.PrimitiveType == TypeCode.UInt32 ||
                stackTop.PrimitiveType == TypeCode.Int16 ||
                stackTop.PrimitiveType == TypeCode.UInt16 ||
                stackTop.PrimitiveType == TypeCode.SByte ||
                stackTop.PrimitiveType == TypeCode.Byte ||
                stackTop.PrimitiveType == TypeCode.Char ||
                stackTop.PrimitiveType == TypeCode.Boolean)
            {
                if (stackTop.PrimitiveType == TypeCode.Int64 ||
                    stackTop.PrimitiveType == TypeCode.UInt64)
                {
                    code.NewInstruction(0x09 /* lconst_0 (long) */, null, null);
                    code.NewInstruction(0x94 /* lcmp (long) */, null, null);
                }

                return(0x9A); // ifne != zero
            }

            throw new InvalidProgramException();
        }
Ejemplo n.º 7
0
        public static bool LoadStore(bool isLoad, CilType stackTop, JavaType opcodeType,
                                     CilType dataType, JavaCode code)
        {
            if (stackTop.Equals(SpanType) && code.Method.Class.Name != SpanType.ClassName)
            {
                string opcodeDescr;
                if (opcodeType == null)
                {
                    opcodeType  = CilType.SystemValueType;
                    opcodeDescr = "";

                    // at this point we should have been called from LoadObject or
                    // StoreObject in CodeMisc to handle a ldobj/stobj instruction,
                    // so make sure the pointer-span element is a value type
                    if (dataType.IsGenericParameter || (!dataType.IsValueClass))
                    {
                        throw new InvalidProgramException();
                    }
                    code.NewInstruction(0x12 /* ldc */, dataType.AsWritableClass, null);

                    // make sure the stack has room for three parameters:
                    // 'this', value reference (in case of Store), and class
                    code.StackMap.PushStack(JavaType.ObjectType);
                    code.StackMap.PushStack(JavaType.ObjectType);
                    code.StackMap.PushStack(JavaType.ObjectType);
                    code.StackMap.PopStack(CilMain.Where);
                    code.StackMap.PopStack(CilMain.Where);
                    code.StackMap.PopStack(CilMain.Where);
                }
                else
                {
                    if (opcodeType.Equals(JavaType.ShortType) &&
                        stackTop.GenericParameters != null &&
                        stackTop.GenericParameters[0].Equals(JavaType.CharacterType))
                    {
                        opcodeType = JavaType.CharacterType;
                    }

                    opcodeDescr = opcodeType.ToDescriptor();
                }

                var voidType   = JavaType.VoidType;
                var spanMethod = isLoad
                      ? (new JavaMethodRef("Load" + opcodeDescr, opcodeType))
                      : (new JavaMethodRef("Store" + opcodeDescr, voidType, opcodeType));
                if (opcodeDescr == "")
                {
                    spanMethod.Parameters.Add(new JavaFieldRef("", JavaType.ClassType));
                }
                code.NewInstruction(0xB6 /* invokevirtual */, SpanType, spanMethod);
                if (isLoad)
                {
                    code.StackMap.PushStack(CilType.From(opcodeType));
                }

                return(true);
            }
            return(false);
        }
Ejemplo n.º 8
0
        public static bool Address(CilType fromType, CilType intoType, JavaCode code)
        {
            if (intoType.Equals(SpanType) && (!fromType.Equals(SpanType)))
            {
                // allow assignment of null to clear the pointer
                if (fromType.Equals(JavaStackMap.Null))
                {
                    return(true);
                }

                // allow assignment of native int (presumably zero)
                bool     callAssign   = false;
                bool     pushNullType = true;
                JavaType argType      = fromType;
                JavaType retType      = SpanType;

                if ((!fromType.IsReference) && fromType.PrimitiveType == TypeCode.UInt64)
                {
                    callAssign = true;
                }
                else if (intoType.GenericParameters != null)
                {
                    // allow assignment when the types match
                    callAssign = intoType.GenericParameters[0].Equals(fromType) ||
                                 fromType.JavaName == intoType.GenericParameters[0].JavaName;

                    // for arbitrary value types, call a Assign(ValueType)
                    if (fromType.IsValueClass)
                    {
                        argType = retType = CilType.SystemValueType;
                        GenericUtil.LoadMaybeGeneric(fromType, code);
                        pushNullType = false;
                    }
                }

                if (callAssign)
                {
                    if (pushNullType)
                    {
                        code.NewInstruction(0x01 /* aconst_null */, null, null);
                        code.StackMap.PushStack(CilType.SystemTypeType);
                    }

                    code.NewInstruction(0xB8 /* invokestatic */, SpanType,
                                        new JavaMethodRef("Assign" + CilMain.EXCLAMATION,
                                                          retType, argType, CilType.SystemTypeType));

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

                    code.StackMap.PopStack(CilMain.Where);  // null type
                    return(true);
                }


                throw new Exception($"bad assignment of '{fromType.JavaName}' into pointer of '{intoType.GenericParameters[0].JavaName}'");
            }
            return(false);
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
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);
        }
Ejemplo n.º 11
0
        public JavaType GetInnerObject(JavaCode code)
        {
            var innerType = new JavaType(0, 0, OldClassName);

            code.NewInstruction(0xB6 /* invokevirtual */, this,
                                new JavaMethodRef("get", JavaType.ObjectType));
            code.NewInstruction(0xC0 /* checkcast */, innerType, null);
            return(UnboxedType.IsEnum ? SystemEnumType : innerType);
        }
Ejemplo n.º 12
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);
                }
            }
        }
Ejemplo n.º 13
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);
                }
            }
        }
Ejemplo n.º 14
0
        static int ConvertToInteger(JavaCode code, TypeCode oldType, TypeCode newType)
        {
            if (oldType == TypeCode.Double)
            {
                if (newType == TypeCode.Int32 || oldType == TypeCode.UInt32)
                {
                    return(0x8E); // d2i
                }
                code.NewInstruction(0x8E /* d2i */, null, null);
            }

            if (oldType == TypeCode.Single)
            {
                if (newType == TypeCode.Int32 || oldType == TypeCode.UInt32)
                {
                    return(0x8B); // f2i
                }
                code.NewInstruction(0x8B /* f2i */, null, null);
            }

            if (oldType == TypeCode.Int64 || oldType == TypeCode.UInt64)
            {
                if (newType == TypeCode.Int32 || oldType == TypeCode.UInt32)
                {
                    return(0x88); // l2i
                }
                code.NewInstruction(0x88 /* l2i */, null, null);
            }

            if (newType == TypeCode.SByte)
            {
                return(0x91); // i2b
            }
            if (newType == TypeCode.Byte)
            {
                code.StackMap.PushStack(JavaType.IntegerType);
                code.NewInstruction(0x12 /* ldc */, null, (int)0xFF);
                code.StackMap.PushStack(JavaType.IntegerType);
                code.StackMap.PopStack(CilMain.Where);
                code.StackMap.PopStack(CilMain.Where);
                return(0x7E); // iand
            }

            if (newType == TypeCode.Int16)
            {
                return(0x93); // i2s
            }
            if (newType == TypeCode.UInt16)
            {
                return(0x92); // i2c
            }
            return(0x00);     // nop
        }
Ejemplo n.º 15
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);
        }
Ejemplo n.º 16
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);
        }
Ejemplo n.º 17
0
        static void UnsignedDivide(JavaCode code, TypeCode typeCode, bool remainder)
        {
            TypeCode unsignedTypeCode;

            if (typeCode == TypeCode.Int32)
            {
                unsignedTypeCode = TypeCode.UInt32;
            }
            else if (typeCode == TypeCode.Int64)
            {
                unsignedTypeCode = TypeCode.UInt64;
            }
            else
            {
                throw new InvalidProgramException();
            }

            var signedType = CilType.From(new JavaType(typeCode, 0, null));

            code.StackMap.PushStack(signedType);

            code.NewInstruction(0xB8 /* invokestatic */,
                                CilType.From(new JavaType(unsignedTypeCode, 0, null)).AsWritableClass,
                                new JavaMethodRef("Unsigned" + (remainder ? "Remainder" : "Division"),
                                                  signedType, signedType, signedType));
        }
Ejemplo n.º 18
0
        static void OverflowArithmetic(JavaCode code, TypeCode typeCode, Code cilOp)
        {
            bool unsigned = (cilOp == Code.Add_Ovf_Un ||
                             cilOp == Code.Sub_Ovf_Un ||
                             cilOp == Code.Mul_Ovf_Un);
            TypeCode callTypeCode;

            if (typeCode == TypeCode.Int32)
            {
                callTypeCode = unsigned ? TypeCode.UInt32 : typeCode;
            }
            else if (typeCode == TypeCode.Int64)
            {
                callTypeCode = unsigned ? TypeCode.UInt64 : typeCode;
            }
            else
            {
                throw new InvalidProgramException();
            }

            var signedType = CilType.From(new JavaType(typeCode, 0, null));

            code.StackMap.PushStack(signedType);

            string verb = (cilOp == Code.Add_Ovf || cilOp == Code.Add_Ovf_Un) ? "Add"
                        : (cilOp == Code.Sub_Ovf || cilOp == Code.Sub_Ovf_Un) ? "Subtract"
                        : (cilOp == Code.Mul_Ovf || cilOp == Code.Mul_Ovf_Un) ? "Multiply"
                        : throw new InvalidProgramException();

            code.NewInstruction(0xB8 /* invokestatic */,
                                CilType.From(new JavaType(callTypeCode, 0, null)).AsWritableClass,
                                new JavaMethodRef("Overflow" + verb,
                                                  signedType, signedType, signedType));
        }
Ejemplo n.º 19
0
        public static void Conversion(JavaCode code, Code cilOp)
        {
            var oldType = (CilType)code.StackMap.PopStack(CilMain.Where);

            var(newType, overflow, unsigned) = ConvertOpCodeToTypeCode(cilOp);
            int op;

            if (oldType.IsReference)
            {
                ConvertReference(code, oldType, newType);
                return;
            }

            if (newType == TypeCode.Single || newType == TypeCode.Double)
            {
                op = ConvertToFloat(code, oldType.PrimitiveType, newType, unsigned);
            }

            else if (newType == TypeCode.Int64 || newType == TypeCode.UInt64)
            {
                op = ConvertToLong(code, oldType.PrimitiveType, newType, overflow);
            }

            else
            {
                op = ConvertToInteger(code, oldType.PrimitiveType, newType, overflow);
            }

            if (op != -1)
            {
                code.NewInstruction((byte)op, null, null);
            }

            code.StackMap.PushStack(CilType.From(new JavaType(newType, 0, null)));
        }
Ejemplo n.º 20
0
        public static void Switch(JavaCode code, Mono.Cecil.Cil.Instruction cilInst)
        {
            if (cilInst.Operand is Mono.Cecil.Cil.Instruction[] targets)
            {
                if ((targets.Length > Int32.MaxValue - 1) ||
                    cilInst.Next == null ||
                    (!code.StackMap.PopStack(CilMain.Where).IsIntLike))
                {
                    throw new InvalidProgramException();
                }

                ushort offset = (ushort)cilInst.Next.Offset;
                code.StackMap.SaveFrame(offset, true, CilMain.Where);

                int n        = targets.Length;
                var instdata = new int[3 + n];
                instdata[0] = offset;
                instdata[2] = n - 1;

                for (int i = 0; i < n; i++)
                {
                    offset = (ushort)targets[i].Offset;
                    code.StackMap.SaveFrame(offset, true, CilMain.Where);
                    instdata[i + 3] = offset;
                }

                code.NewInstruction(0xAA /* tableswitch */, null, instdata);
            }
        }
Ejemplo n.º 21
0
        public override void SetValueOV(JavaCode code, bool isVolatile = false)
        {
            var innerOrEnum = GetInnerObject(code);

            code.NewInstruction(0xB6 /* invokevirtual */, innerOrEnum,
                                new JavaMethodRef("Set", JavaType.VoidType, UnboxedTypeInMethod));
        }
Ejemplo n.º 22
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);
            }
        }
Ejemplo n.º 23
0
        public virtual void SetValueVO(JavaCode code, bool isVolatile = false)
        {
            var thisOrEnum = ThisOrEnum;

            code.NewInstruction(0xB8 /* invokestatic */, thisOrEnum,
                                new JavaMethodRef(VolatileName("Set", isVolatile),
                                                  JavaType.VoidType, UnboxedTypeInMethod, thisOrEnum));
        }
Ejemplo n.º 24
0
        static void Finish(JavaCode code, CodeLocals locals,
                           Mono.Cecil.Cil.Instruction cilInst, byte op)
        {
            var inst = (Mono.Cecil.Cil.Instruction)cilInst.Operand;

            bool isNop;

            if (op == 0x00 || op == 0x57 || op == 0x58) // nop, pop, pop2
            {
                isNop = true;
            }
            else
            {
                isNop = false;
                int diff = cilInst.Offset - inst.Offset;
                if (diff < -0x2000 || diff > 0x2000)
                {
                    // branch instructions use 16-bits for the signed offset.
                    // for farther branches, we have to negate the condition,
                    // and insert a 32-bit 'goto_w' instruction.

                    if (cilInst.Next != null)
                    {
                        op = NegateCondition(op);
                        var nextOffset = (ushort)cilInst.Next.Offset;
                        code.NewInstruction(op, null, nextOffset);
                        code.StackMap.SaveFrame(nextOffset, true, CilMain.Where);
                    }

                    op = 0xC8;
                }
            }

            code.NewInstruction(op, null, (ushort)inst.Offset);

            if (!isNop)  // no stack frame for 'nop' or 'pop'
            {
                var resetLocals =
                    code.StackMap.SaveFrame((ushort)inst.Offset, true, CilMain.Where);

                if (resetLocals != null)
                {
                    ResetLocalsOutOfScope(code.StackMap, locals, resetLocals, cilInst, inst);
                }
            }
        }
Ejemplo n.º 25
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);
            }
        }
Ejemplo n.º 26
0
        public static bool CompareGtLt(JavaType stackTop, JavaType stackTop2, JavaCode code)
        {
            if (stackTop.Equals(SpanType) && stackTop2.Equals(SpanType))
            {
                code.NewInstruction(0x01 /* aconst_null */, null, null);
                code.StackMap.PushStack(CilType.SystemTypeType);

                code.NewInstruction(0xB8 /* invokestatic */, SpanType,
                                    new JavaMethodRef("CompareTo" + CilMain.EXCLAMATION,
                                                      JavaType.IntegerType, SpanType, SpanType, CilType.SystemTypeType));

                code.StackMap.PopStack(CilMain.Where);  // null type

                return(true);
            }
            return(false);
        }
Ejemplo n.º 27
0
 public virtual void BoxValue(JavaCode code)
 {
     if (UnboxedType.IsEnum)
     {
         code.NewInstruction(0x12 /* ldc */, this, null);
         code.StackMap.PushStack(JavaType.ClassType);
         code.NewInstruction(0xB8 /* invokestatic */, SystemEnumType,
                             new JavaMethodRef("Box", JavaType.ObjectType,
                                               UnboxedTypeInMethod, JavaType.ClassType));
         code.NewInstruction(0xC0 /* checkcast */, this, null);
         code.StackMap.PopStack(CilMain.Where);
     }
     else
     {
         code.NewInstruction(0xB8 /* invokestatic */, this,
                             new JavaMethodRef("Box", this, UnboxedTypeInMethod));
     }
 }
Ejemplo n.º 28
0
 public virtual void GetValue(JavaCode code, bool isVolatile = false)
 {
     code.NewInstruction(0xB6 /* invokevirtual */, ThisOrEnum,
                         new JavaMethodRef(VolatileName("Get", isVolatile),
                                           UnboxedTypeInMethod));
     if (UnboxedTypeInMethod.Category == 2)
     {
         CilMain.MakeRoomForCategory2ValueOnStack(code);
     }
 }
Ejemplo n.º 29
0
        static byte TestEq(JavaCode code, JavaType stackTop, JavaType stackTop2,
                           Mono.Cecil.Cil.Instruction cilInst)
        {
            if (stackTop.IsReference || stackTop2.IsReference)
            {
                byte cmpOp = CodeSpan.CompareEq(stackTop, stackTop2, cilInst, code);
                if (cmpOp == 0)
                {
                    cmpOp = 0xA5; // if_acmpeq (reference)
                }
                return(cmpOp);
            }

            if (stackTop2.IsIntLike && (stackTop.PrimitiveType == TypeCode.Int32 ||
                                        stackTop.PrimitiveType == TypeCode.UInt32 ||
                                        stackTop.PrimitiveType == TypeCode.Int16 ||
                                        stackTop.PrimitiveType == TypeCode.UInt16 ||
                                        stackTop.PrimitiveType == TypeCode.SByte ||
                                        stackTop.PrimitiveType == TypeCode.Byte ||
                                        stackTop.PrimitiveType == TypeCode.Char ||
                                        stackTop.PrimitiveType == TypeCode.Boolean))
            {
                return(0x9F); // if_icmpeq
            }

            byte op;

            if ((stackTop.PrimitiveType == TypeCode.Int64 ||
                 stackTop.PrimitiveType == TypeCode.UInt64) &&
                (stackTop2.PrimitiveType == TypeCode.Int64 ||
                 stackTop2.PrimitiveType == TypeCode.UInt64))
            {
                op = 0x94; // lcmp (long)
            }

            else if (stackTop.PrimitiveType == TypeCode.Single &&
                     stackTop2.PrimitiveType == TypeCode.Single)
            {
                op = 0x95; // fcmpl (float)
            }

            else if (stackTop.PrimitiveType == TypeCode.Double &&
                     stackTop2.PrimitiveType == TypeCode.Double)
            {
                op = 0x97; // dcmpl (double)
            }

            else
            {
                throw new Exception($"incompatible types '{stackTop}' and '{stackTop2}'");
            }

            code.NewInstruction(op, null, null);
            return(0x99); // ifeq == zero
        }
Ejemplo n.º 30
0
        public static bool AddOffset(JavaType offsetType, JavaType spanType, JavaCode code)
        {
            if (spanType.Equals(SpanType))
            {
                code.StackMap.PushStack(spanType);

                if (offsetType.Equals(JavaType.IntegerType))
                {
                    code.NewInstruction(0x85 /* i2l */, null, null);
                    offsetType = JavaType.LongType;
                }
                code.StackMap.PushStack(offsetType);

                bool loadedType = false;
                if (spanType is CilType spanType2)
                {
                    if ((!spanType2.HasGenericParameters) &&
                        spanType2.GenericParameters != null &&
                        spanType2.GenericParameters[0] is CilType spanPointerType &&
                        (!spanPointerType.IsGenericParameter))
                    {
                        GenericUtil.LoadMaybeGeneric(spanPointerType, code);
                        loadedType = true;
                    }
                }
                if (!loadedType)
                {
                    code.NewInstruction(0x01 /* aconst_null */, null, null);
                    code.StackMap.PushStack(CilType.SystemTypeType);
                }

                code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
                                    new JavaMethodRef("Add",
                                                      SpanType, offsetType, CilType.SystemTypeType));

                code.StackMap.PopStack(CilMain.Where);  // span type
                code.StackMap.PopStack(CilMain.Where);  // offset

                return(true);
            }
            return(false);
        }