Пример #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);
            }
        }
Пример #2
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);
        }
Пример #3
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);
 }
Пример #4
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);
 }
Пример #5
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);
        }
Пример #6
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);
        }
Пример #7
0
        public override bool AssignableTo(JavaType other)
        {
            if (base.AssignableTo(other))
            {
                return(true);
            }

            if (SuperTypes != null)
            {
                foreach (var sup in SuperTypes)
                {
                    if ((!sup.Equals(JavaType.ObjectType)) &&
                        (other.Equals(sup) || sup.AssignableTo(other)))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #8
0
        static byte TestGtLt(JavaCode code, JavaType stackTop, JavaType stackTop2,
                             bool greater, bool unsigned_unordered)
        {
            byte op;

            //
            // for floating point, normal comparison returns 0 if either value
            // is NaN, while unordered comparison returns 1.  we have fcmp/dcmp
            // variants which return either 1 or -1.  following the comparison,
            // we have ifgt/iflt to check if the result is either greater than
            // or less than 0.  we consider all this when picking the opcode:
            //
            //                  test    normal compare  unordered compare
            //  greater than    ifgt        xcmpl              xcmpg
            //     less than    iflt        xcmpg              xcmpl
            //

            if (stackTop.PrimitiveType == TypeCode.Single)
            {
                op = (byte)((greater != unsigned_unordered) ? 0x95    // fcmpl
                                                             : 0x96); // fcmpg
            }

            else if (stackTop.PrimitiveType == TypeCode.Double)
            {
                op = (byte)((greater != unsigned_unordered) ? 0x97    // dcmpl
                                                             : 0x98); // dcmpg
            }

            //
            // for unsigned integer comparison, we use library function
            // system.UInt{32,64}.CompareTo, followed by ifgt/iflt
            //

            else if (unsigned_unordered && stackTop.PrimitiveType != TypeCode.Char)
            {
                char   typeChar;
                int    typeBits;
                string typeName = null;

                if (stackTop.PrimitiveType == TypeCode.SByte ||
                    stackTop.PrimitiveType == TypeCode.Byte)
                {
                    typeChar = 'B';
                    typeBits = 0;
                    typeName = "Byte";
                }
                else if (stackTop.PrimitiveType == TypeCode.Int16 ||
                         stackTop.PrimitiveType == TypeCode.UInt16)
                {
                    typeChar = 'S';
                    typeBits = 16;
                }
                else if (stackTop.PrimitiveType == TypeCode.Int32 ||
                         stackTop.PrimitiveType == TypeCode.UInt32)
                {
                    typeChar = 'I';
                    typeBits = 32;
                }
                else if (stackTop.PrimitiveType == TypeCode.Int64 ||
                         stackTop.PrimitiveType == TypeCode.UInt64)
                {
                    typeChar = 'J';
                    typeBits = 64;
                }
                else if (greater && stackTop.Equals(JavaStackMap.Null))
                {
                    // per MS CLI Partition III table 4 note 2, 'cgt.un'
                    // can be used to check for a non-null reference
                    return(0xA6); // if_acmpne
                }
                else
                {
                    if (CodeSpan.CompareGtLt(stackTop, stackTop2, code))
                    {
                        return((byte)(greater ? 0x9D     // ifgt
                                               : 0x9B)); // iflt
                    }

                    throw new InvalidProgramException();
                }

                if (typeBits != 0)
                {
                    typeName = "UInt" + typeBits.ToString();
                }

                code.NewInstruction(0xB8 /* invokestatic */,
                                    new JavaType(0, 0, $"system.{typeName}"),
                                    new JavaMethodRef("CompareTo",
                                                      $"({typeChar}{typeChar})I", CilMain.Where));

                /*
                 * new JavaType(0, 0, $"java.lang.{typeName}"),
                 * new JavaMethodRef("compareUnsigned",
                 *               $"({typeChar}{typeChar})I", CilMain.Where));*/
                op = 0;
            }

            //
            // for signed long comparison, we use lcmp followed by ifgt/iflt
            //

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

            //
            // for signed integer comparison, we have if_icmplt/if_icmpgt
            // which directly compare two integers and branch
            //

            else if (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((byte)(greater ? 0xA3     // if_icmpgt
                                       : 0xA1)); // if_icmplt
            }

            else
            {
                throw new InvalidProgramException();
            }

            //
            // return the selected opcode
            //

            if (op != 0)
            {
                code.NewInstruction(op, null, null);
            }

            return((byte)(greater ? 0x9D     // ifgt
                                   : 0x9B)); // iflt
        }
Пример #9
0
 static bool IsGenericOrEqual(JavaType pThis, CilType pBase)
 => pBase.IsGenericParameter || pThis.Equals(pBase);