/// <summary>
            /// Default ctor
            /// </summary>
            internal AssemblyClasses(AssemblyDefinition assembly, Action<ClassSource> jarLoaded=null)
            {
                this.assembly = assembly;
                foreach (var attr in assembly.GetJavaCodeAttributes())
                {
                    var resourceName = (string)attr.ConstructorArguments[0].Value;
                    var fileName = attr.ConstructorArguments.Count > 1 ? (string)attr.ConstructorArguments[1].Value : null;

                    JavaCode javaCode;
                    if (!javaCodes.TryGetValue(resourceName, out javaCode))
                    {
                        var resource = assembly.MainModule.Resources.FirstOrDefault(x => x.Name == resourceName) as EmbeddedResource;
                        if (resource == null)
                            throw new LoaderException("Cannot find resource " + resourceName);
                        javaCode = new JavaCode(resource, fileName);
                        javaCodes[resourceName] = javaCode;

                        if (jarLoaded != null)
                            jarLoaded(javaCode.ClassSource);

                        foreach (var classFileName in javaCode.Resolve(null).ClassFileNames)
                        {
                            var className = classFileName;
                            if (className.EndsWith(".class", StringComparison.OrdinalIgnoreCase))
                            {
                                className = className.Substring(0, className.Length - ".class".Length);
                            }
                            var jClass = new JavaClass(className, javaCode);
                            javaClasses[className] = jClass;
                        }
                    }
                }
                var scope = AssemblyResolver.IsFrameworkAssembly(assembly) ? AttributeConstants.Dot42Scope : assembly.FullName;
                var ignoreFromJavaTypes = new List<TypeDefinition>();
                foreach (var type in assembly.MainModule.Types)
                {
                    CollectDexImportClasses(type, className2DexImportMap, type2DexImportMap, null, scope, ignoreFromJavaTypes);
                }
                foreach (var type in ignoreFromJavaTypes)
                {
                    var attr = type.GetDexOrJavaImportAttribute();
                    var className = (string)attr.ConstructorArguments[0].Value;
                    DexImport dexImport;
                    if (className2DexImportMap.TryGetValue(className, out dexImport))
                    {
                        dexImport.AddType(type);
                        type2DexImportMap[type] = dexImport;
                    }
                }
            }
Exemple #2
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);
        }
Exemple #3
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));
     }
 }
Exemple #4
0
        public static void Conversion(JavaCode code, Code cilOp,
                                      Mono.Cecil.Cil.Instruction cilInst)
        {
            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 (overflow)
            {
                op = ConvertWithOverflow(code, oldType.PrimitiveType, newType);
            }

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

            else
            {
                var opNext = cilInst.Next?.OpCode.Code ?? 0;
                op = ConvertToInteger(code, oldType.PrimitiveType, newType, opNext);
            }

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

            code.StackMap.PushStack(CilType.From(new JavaType(newType, 0, null)));
        }
Exemple #5
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);
        }
Exemple #6
0
        public static bool AddressArray(CilType elemType, CilType spanType, JavaCode code)
        {
            if (spanType != null && spanType.Equals(SpanType) &&
                elemType.ArrayRank == 0 && (!elemType.Equals(SpanType)))
            {
                GenericUtil.LoadMaybeGeneric(elemType, code);

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

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

                code.StackMap.PopStack(CilMain.Where);  // type argument
                code.StackMap.PushStack(spanType);

                return(true);
            }
            return(false);
        }
Exemple #7
0
        void Process(int numCastableInterfaces)
        {
            code = newMethod.Code = new JavaCode(newMethod);
            var oldLabel = code.SetLabel(0xFFFF);

            locals     = new CodeLocals(method, defMethod, code);
            arrays     = new CodeArrays(code, locals);
            exceptions = new CodeExceptions(defMethodBody, code, locals);

            InsertMethodInitCode(numCastableInterfaces);

            code.SetLabel(oldLabel);

            stackMap = code.StackMap;
            stackMap.SaveFrame(0, false, CilMain.Where);

            ProcessInstructions();

            (code.MaxLocals, code.MaxStack) = locals.GetMaxLocalsAndStack();
            locals.TrackUnconditionalBranch(null);
        }
Exemple #8
0
        public static byte 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);
            }

            else if (CompareGtLt(stackTop, stackTop2, code))
            {
                return(0x99); // ifeq == zero
            }

            return(0);
        }
Exemple #9
0
        public static void Localloc(JavaCode code)
        {
            // 'localloc' step 1

            // the 'localloc' instruction does not specify the type of the memory
            // to allocate.  in most cases it is followed by a store instruction
            // into a variable of a pointer type, or of type System.Span, but in
            // cases where the result of 'localloc' is passed to a method call,
            // there can be any number of intermediate instruction that push
            // other parameters, and it might not be practial to find the type.

            code.NewInstruction(0x01 /* aconst_null */, null, null);
            code.StackMap.PushStack(CilType.SystemTypeType);

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

            code.StackMap.PopStack(CilMain.Where);  // null type
            code.StackMap.PopStack(CilMain.Where);  // localloc size
            code.StackMap.PushStack(SpanType);
        }
Exemple #10
0
 public static void Sizeof(object data, JavaCode code)
 {
     if (data is TypeReference operandTypeReference)
     {
         var myType = CilType.From(operandTypeReference);
         if (myType.IsValueClass)
         {
             // compiler generated IL typically calculates the stackalloc
             // total buffer size, for primitive types, and uses 'sizeof'
             // for values types.  but it also uses 'sizeof' for generic
             // types, which may stand for a primitive type.
             GenericUtil.LoadMaybeGeneric(myType, code);
             code.NewInstruction(0xB8 /* invokestatic */, SpanType,
                                 new JavaMethodRef("Sizeof" + CilMain.EXCLAMATION,
                                                   JavaType.IntegerType, CilType.SystemTypeType));
             code.StackMap.PopStack(CilMain.Where);  // generic type
             code.StackMap.PushStack(JavaType.IntegerType);
             return;
         }
     }
     throw new InvalidProgramException();
 }
Exemple #11
0
        public static void CastToGenericType(TypeReference fromType, int throwBool, JavaCode code)
        {
            var genericMark = CilMain.GenericStack.Mark();

            GenericUtil.LoadMaybeGeneric(CilMain.GenericStack.EnterType(fromType), code);
            CilMain.GenericStack.Release(genericMark);

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

            var parameters = new List <JavaFieldRef>();

            parameters.Add(new JavaFieldRef("", JavaType.ObjectType));
            parameters.Add(new JavaFieldRef("", CilType.SystemTypeType));
            parameters.Add(new JavaFieldRef("", JavaType.BooleanType));

            code.NewInstruction(0xB8 /* invokestatic */, GenericUtil.SystemGenericType,
                                new JavaMethodRef("TestCast",
                                                  JavaType.ObjectType, parameters));
            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);
        }
Exemple #12
0
        public static bool SubOffset(JavaType secondType, JavaCode code)
        {
            // make sure the first operand is a pointer span, not a real Span<T>
            var spanType1 = (CilType)code.StackMap.PopStack(CilMain.Where);

            if ((!spanType1.HasGenericParameters) &&
                spanType1.GenericParameters != null &&
                spanType1.GenericParameters[0] is CilType span1PointerType &&
                (!span1PointerType.IsGenericParameter))
            {
                var spanType2 = (CilType)secondType;

                // check if subtracting two pointer spans
                if ((!spanType2.HasGenericParameters) &&
                    spanType2.GenericParameters != null &&
                    spanType2.GenericParameters[0] is CilType span2PointerType &&
                    (!span2PointerType.IsGenericParameter))
                {
                    code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
                                        new JavaMethodRef("Subtract",
                                                          JavaType.LongType, spanType2));
                    code.StackMap.PushStack(CilType.From(JavaType.LongType));
                    return(true);
                }

                // check if subtracting an offset from a pointer span
                if (spanType2.Equals(JavaType.IntegerType))
                {
                    code.NewInstruction(0xB6 /* invokevirtual */, SpanType,
                                        new JavaMethodRef("Subtract",
                                                          SpanType, spanType2));
                    code.StackMap.PushStack(SpanType);
                    return(true);
                }
            }

            code.StackMap.PushStack(spanType1);
            return(false);
        }
Exemple #13
0
        //
        // InitInterfaceArrayField
        //

        public static void InitInterfaceArrayField(CilType toType, int numCastableInterfaces,
                                                   JavaCode code, int objectIndex)
        {
            // if a type has castable interface (as counted by CastableInterfaceCount),
            // then we need to initialize the helper array field, for use by the
            // implementation of the IGenericObject.TryCast helper method

            if (numCastableInterfaces == 0)
            {
                return;
            }

            // objectIndex specifies the local index for the object reference,
            // e.g. 0 for the 'this' object, or -1 for top of stack.
            if (objectIndex == -1)
            {
                code.NewInstruction(0x59 /* dup */, null, null);
            }
            else
            {
                code.NewInstruction(0x19 /* aload */, null, objectIndex);
            }
            code.StackMap.PushStack(toType);

            code.NewInstruction(0xBB /* new */, AtomicReferenceArrayType, null);
            code.StackMap.PushStack(AtomicReferenceArrayType);
            code.NewInstruction(0x59 /* dup */, null, null);
            code.StackMap.PushStack(AtomicReferenceArrayType);
            code.NewInstruction(0x12 /* ldc */, null, numCastableInterfaces);
            code.StackMap.PushStack(JavaType.IntegerType);
            code.NewInstruction(0xB7 /* invokespecial */, AtomicReferenceArrayType,
                                new JavaMethodRef("<init>", JavaType.VoidType, JavaType.IntegerType));
            code.NewInstruction(0xB5 /* putfield */, toType, InterfaceArrayField);
            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);
        }
Exemple #14
0
        static void BitwiseNot(JavaCode code, TypeCode typeCode)
        {
            var jtype = new JavaType(typeCode, 0, null);

            code.StackMap.PushStack(CilType.From(jtype));
            code.StackMap.PushStack(jtype);

            byte op = 0x82; // ixor

            code.NewInstruction(0x02 /* iconst_m1 */, null, null);
            if (typeCode == TypeCode.Int64)
            {
                code.NewInstruction(0x85 /* i2l */, null, null);
                op++; // lxor
            }
            else if (typeCode != TypeCode.Int32)
            {
                throw new InvalidProgramException();
            }

            code.NewInstruction(op, null, null);
            code.StackMap.PopStack(CilMain.Where);
        }
Exemple #15
0
        static int ConvertToLong(JavaCode code, TypeCode oldType, TypeCode newType, bool overflow)
        {
            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);
                #if true
                long maskValue = (oldType == TypeCode.Byte) ? 0xFF
                               : (oldType == TypeCode.UInt16) ? 0xFFFF
                               : (oldType == TypeCode.UInt32) ? 0xFFFFFFFF
                               : 0;
                code.NewInstruction(0x12 /* ldc */, null, (long)0xFFFFFFFF);
                #else
                code.NewInstruction(0x02 /* iconst_m1 */, null, null);
                code.NewInstruction(0x85 /* i2l */, null, null);
                #endif
                code.StackMap.PushStack(JavaType.LongType);
                code.StackMap.PopStack(CilMain.Where);
                code.StackMap.PopStack(CilMain.Where);
                return(0x7F); // land
            }

            CilMain.MakeRoomForCategory2ValueOnStack(code);
            return(0x85); // i2l
        }
Exemple #16
0
        static void LoadGenericInstance_1_2(CilType loadType, int genericCount,
                                            List <JavaFieldRef> parameters,
                                            JavaCode code)
        {
            // handling for the case of a generic instance with one or two
            // type arguments.  each argument, if it is a concrete argument,
            // call GetType(class, class).  if it is a generic argument,
            // call GetType(class, type).
            // note that the first class argument to GetType was alredy
            // inserted by our caller, LoadMaybeGeneric().

            for (int i = 0; i < genericCount; i++)
            {
                var genericMark = CilMain.GenericStack.Mark();

                var(argType, argIndex) = CilMain.GenericStack.Resolve(
                    loadType.GenericParameters[i].JavaName);

                if (argIndex == 0 && (!argType.HasGenericParameters))
                {
                    // GetType(java.lang.Class, java.lang.Class)
                    code.NewInstruction(0x12 /* ldc */, argType.AsWritableClass, null);
                    code.StackMap.PushStack(CilType.ClassType);
                    // second or third parameter of type java.lang.Class
                    parameters.Add(parameters[0]);
                }
                else
                {
                    // GetType(java.lang.Class, system.Type)
                    LoadGeneric(argType, argIndex, code);
                    // second or third parameter of type system.Type
                    parameters.Add(new JavaFieldRef("", CilType.SystemTypeType));
                }

                CilMain.GenericStack.Release(genericMark);
            }
        }
Exemple #17
0
        public static void Opposite(JavaCode code, Code cilOp, CodeLocals locals,
                                    Mono.Cecil.Cil.Instruction cilInst)
        {
            //
            // an opposite branch works by generating logic/opcode for
            // the opposite test (e.g. clt for bge), and an opposite
            // branch opcode (e.g. for bge, branch if clt returns zero)
            //

            var stackTop = code.StackMap.PopStack(CilMain.Where);

            bool isFloat = (stackTop.PrimitiveType == TypeCode.Single ||
                            stackTop.PrimitiveType == TypeCode.Double);

            if (cilOp == Code.Brfalse || cilOp == Code.Brfalse_S)
            {
                cilOp = Code.Brtrue;
            }
            else if (cilOp == Code.Bne_Un || cilOp == Code.Bne_Un_S)
            {
                cilOp = Code.Beq;
            }
            else if (cilOp == Code.Ble || cilOp == Code.Ble_S)
            {
                // for integer, this is the opposite of BGT
                // for float, this is the opposite of BGT.UN
                cilOp = isFloat ? Code.Bgt_Un : Code.Bgt;
            }
            else if (cilOp == Code.Ble_Un || cilOp == Code.Ble_Un_S)
            {
                // for integer, this is the opposite of BGT.UN
                // for float, this is the opposite of BGT
                cilOp = isFloat ? Code.Bgt : Code.Bgt_Un;
            }
            else if (cilOp == Code.Bge || cilOp == Code.Bge_S)
            {
                // for integer, this is the opposite of BLT
                // for float, this is the opposite of BLT.UN
                cilOp = isFloat ? Code.Blt_Un : Code.Blt;
            }
            else if (cilOp == Code.Bge_Un || cilOp == Code.Bge_Un_S)
            {
                // for integer, this is the opposite of BLT.UN
                // for float, this is the opposite of BLT
                cilOp = isFloat ? Code.Blt : Code.Blt_Un;
            }
            else
            {
                throw new InvalidProgramException();
            }

            //
            // change the branch test to the opposite result
            //

            byte op = Common(code, cilOp, cilInst, stackTop);

            op = NegateCondition(op);

            Finish(code, locals, cilInst, op);
        }
Exemple #18
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
        }
Exemple #19
0
        public static void Compare(JavaCode code, Code cilOp, Mono.Cecil.Cil.Instruction cilInst)
        {
            //
            // each cil comparison instruction checks one relation (equals,
            // grater than, or less than) and pushes integer 0 or 1.
            // in contrast, jvm compares two values and returns -1, 0, or 1.
            // we simulate ceq/cgt/clt as a compare and branch sequence:
            //
            // call to System.UInt{16,32}.CompareTo (for unsigned compare)
            // comparison like lcmp/fcmpl/dcmpl (for long/float/double)
            // branch like if_acmpeq/if_icmplt/ifne (depends on test)
            // iconst_0
            // goto next instruction
            // branch label:
            // iconst_1
            //

            if (cilInst.Next == null)
            {
                throw new InvalidProgramException();
            }

            //
            // first, the comparison test.  this is done in a helper method
            // which returns the opcode for the branch following the test.
            //

            var stackTop  = code.StackMap.PopStack(CilMain.Where);
            var stackTop2 = code.StackMap.PopStack(CilMain.Where);

            byte op = (cilOp == Code.Ceq)
                    ? TestEq(code, stackTop, stackTop2, cilInst)
                    : TestGtLt(code, stackTop, stackTop2,
                               /* if greater than */ (cilOp == Code.Cgt ||
                                                      /* (vs less than) */ cilOp == Code.Cgt_Un),
                               /* if unsigned */ (cilOp == Code.Cgt_Un ||
                                                  /* or unordered */ cilOp == Code.Clt_Un));
            //
            // as branch labels, we generally use the offset of the source
            // cil instruction;  in this case, we need a temporary label
            // which does not correspond to any cil instruction, so we will
            // use offset+1 (knowing that ceq/cgt/clt is two bytes long)
            //

            ushort label1 = (ushort)(cilInst.Offset + 1);

            code.NewInstruction(op, null, label1);
            code.StackMap.SaveFrame(label1, true, CilMain.Where);

            //
            // if the test failed and we fall through, push 0 and branch
            // to the next cil instruction.  otherwise push 1.
            //

            ushort label2 = (ushort)cilInst.Next.Offset;

            code.NewInstruction(0x03 /* iconst_0 */, null, null);
            code.StackMap.PushStack(CilType.From(JavaType.IntegerType));

            code.NewInstruction(0xA7 /* goto */, null, label2);
            code.StackMap.SaveFrame(label2, true, CilMain.Where);

            code.NewInstruction(0x04 /* iconst_1 */, null, null, (ushort)label1);
        }
Exemple #20
0
        public static void Calculation(JavaCode code, Code cilOp,
                                       Mono.Cecil.Cil.Instruction cilInst)
        {
            if (cilOp == Code.And &&
                CodeBuilder.IsAndBeforeShift(cilInst.Previous, code))
            {
                // jvm shift instructions mask the shift count, so
                // eliminate AND-ing with 31 and 63 prior to a shift
                code.NewInstruction(0x00 /* nop */, null, null);
                return;
            }

            var stackTop1 = code.StackMap.PopStack(CilMain.Where);

            if (cilOp == Code.Sub && CodeSpan.SubOffset(stackTop1, code))
            {
                return;
            }
            var type1 = GetNumericTypeCode(stackTop1);

            if (cilOp == Code.Not)
            {
                BitwiseNot(code, type1);
                return;
            }

            byte op;

            if (cilOp == Code.Neg)
            {
                op = 0x74; // ineg
            }
            else
            {
                var stackTop2 = code.StackMap.PopStack(CilMain.Where);
                if ((cilOp == Code.Add || cilOp == Code.Add_Ovf_Un) &&
                    CodeSpan.AddOffset(stackTop1, stackTop2, code))
                {
                    return;
                }

                char kind;
                var  type2 = type1;
                type1 = GetNumericTypeCode(stackTop2);

                switch (cilOp)
                {
                case Code.Add:      op = 0x60; kind = 'A'; break;       // iadd

                case Code.Sub:      op = 0x64; kind = 'A'; break;       // isub

                case Code.Mul:      op = 0x68; kind = 'A'; break;       // imul

                case Code.Div:      op = 0x6C; kind = 'A'; break;       // idiv

                case Code.Rem:      op = 0x70; kind = 'A'; break;       // irem

                case Code.And:      op = 0x7E; kind = 'L'; break;       // iand

                case Code.Or:       op = 0x80; kind = 'L'; break;       // ior

                case Code.Xor:      op = 0x82; kind = 'L'; break;       // ixor

                case Code.Shl:      op = 0x78; kind = 'S'; break;       // ishl

                case Code.Shr:      op = 0x7A; kind = 'S'; break;       // ishr

                case Code.Shr_Un:   op = 0x7C; kind = 'S'; break;       // iushr

                case Code.Div_Un:
                case Code.Rem_Un:
                    op = 0x00; kind = 'U'; break;

                case Code.Add_Ovf:
                case Code.Sub_Ovf:
                case Code.Mul_Ovf:
                case Code.Add_Ovf_Un:
                case Code.Sub_Ovf_Un:
                case Code.Mul_Ovf_Un:
                    op = 0x00; kind = 'A'; break;

                default:            throw new InvalidProgramException();
                }

                bool ok = true;
                if (kind == 'S')
                {
                    // second operand must be integer shift count
                    if (type2 != TypeCode.Int32)
                    {
                        ok = false;
                    }
                }
                else
                {
                    // logical and arithmetic operands must be same type
                    if (type1 != type2)
                    {
                        if (kind == 'A' && type1 == TypeCode.Int64 && type2 == TypeCode.Int32)
                        {
                            // special case:  convert the second operand to Int64
                            code.NewInstruction(0x85 /* i2l */, null, null);
                            code.StackMap.PushStack(JavaType.LongType);
                            code.StackMap.PushStack(JavaType.LongType);
                            code.StackMap.PopStack(CilMain.Where);
                            code.StackMap.PopStack(CilMain.Where);
                        }
                        else if (kind == 'A' && type1 == TypeCode.Int32 && type2 == TypeCode.Int64)
                        {
                            // special case:  convert the second operand to Int32
                            code.NewInstruction(0x88 /* l2i */, null, null);
                        }
                        else
                        {
                            ok = false;
                        }
                    }

                    if (kind == 'L')
                    {
                        // logical operation requires integer operands
                        if (type1 != TypeCode.Int32 && type1 != TypeCode.Int64)
                        {
                            ok = false;
                        }
                    }
                }

                if (!ok)
                {
                    throw new Exception($"unexpected opcode or operands ({type1} and {type2})");
                }

                if (kind == 'A' && op == 0)
                {
                    OverflowArithmetic(code, type1, cilOp);
                    return;
                }

                if (kind == 'U')
                {
                    UnsignedDivide(code, type1, (cilOp == Code.Rem_Un));
                    return;
                }
            }

            if (type1 == TypeCode.Int64)
            {
                op++;       // ixxx -> lxxx
            }
            else if (type1 == TypeCode.Single)
            {
                op += 2;    // ixxx -> fxxx
            }
            else if (type1 == TypeCode.Double)
            {
                op += 3;    // ixxx -> dxxx
            }
            code.NewInstruction(op, null, null);
            code.StackMap.PushStack(CilType.From(new JavaType(type1, 0, null)));
        }
Exemple #21
0
 public static void ValueClone(JavaCode code)
 {
     code.NewInstruction(0xB8 /* invokestatic */, SystemGenericType, GenericClone);
 }
Exemple #22
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)
                {
                    int genericCount = loadType.GenericParameters.Count;
                    if (genericCount <= 2)
                    {
                        LoadGenericInstance_1_2(loadType, genericCount,
                                                parameters, code);
                    }
                    else
                    {
                        LoadGenericInstance_3_N(loadType, genericCount,
                                                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);
                }
            }
        }
Exemple #23
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 ||
                             ((!resolvedType.IsReference) &&
                              resolvedType.PrimitiveType != 0))
                    {
                        // cast the generic type to an actual boxed type, when it is
                        // returned byref (called from PushMethodReturnType), or when
                        // the actual type is a primitive (from LoadFieldAddress)
                        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);
        }
Exemple #24
0
 public override void BoxValue(JavaCode code) => throw new NotImplementedException();
Exemple #25
0
        private void OptimizeGeneratedCode()
        {
            var Instructions = code.Instructions;
            var StackMap     = code.StackMap;
            int n            = Instructions.Count;

            //
            // nop optimization:
            //
            // remove any nop instructions that are not a branch target,
            // and only if there are no exception tables.  note that
            // removing nops that are a branch target, or nops in a method
            // with exception tables, would require updating the stack map,
            // branch instructions and exception tables.
            //

            var nops = new List <int>();

            bool discardNops =
                (code.Exceptions == null || code.Exceptions.Count == 0);

            // constants optimization:
            //
            // find occurrences of iconst_0 or iconst_1 followed by i2l
            // (which must not be a branch target), and convert to lconst_xx
            //

            for (int i = 0; i < n; i++)
            {
                byte op = Instructions[i].Opcode;

                if (op == 0x00 /* nop */)
                {
                    // collect this nop only if it is not a branch target
                    if (!StackMap.HasBranchFrame(Instructions[i].Label))
                    {
                        nops.Add(i);
                    }
                }

                else if (JavaCode.IsBranchOpcode(op)) // jump inst
                {
                    if (Instructions[i].Data is int)
                    {
                        // if jump instruction has an explicit byte offset,
                        // we can't do nop elimination; see FillJumpTargets
                        // in JavaBinary.JavaCodeWriter
                        discardNops = false;
                    }
                }

                else if (op == 0x85 /* i2l */ && i > 0)
                {
                    var prevInst = Instructions[i - 1];
                    if (prevInst.Opcode == 0x12 &&  /* ldc */
                        prevInst.Data is int intValue &&
                        (intValue == 0 || intValue == 1) &&
                        (!StackMap.HasBranchFrame(
                             Instructions[i].Label)))
                    {
                        // convert ldc of 0 or 1 into lconst_0 or lconst_1
                        prevInst.Opcode = (byte)(intValue + 0x09);

                        // convert current instruction to nop,
                        // and mark to discard it if discarding nops
                        Instructions[i].Opcode = 0x00; // nop
                        nops.Add(i);
                    }
                }
            }

            if (discardNops)
            {
                for (int i = nops.Count; i-- > 0;)
                {
                    Instructions.RemoveAt(nops[i]);
                }
            }
        }
Exemple #26
0
 public virtual void SetValueVO(JavaCode code, bool isVolatile = false) =>
 code.NewInstruction(0xB8 /* invokestatic */, ThisOrEnum,
                     new JavaMethodRef(VolatileName("Set", isVolatile),
                                       JavaType.VoidType, UnboxedTypeInMethod, ThisOrEnum));
Exemple #27
0
        static int ConvertToFloat(JavaCode code, TypeCode oldType, TypeCode newType, bool unsigned)
        {
            if (newType == TypeCode.Single)
            {
                //
                // convert to float
                //

                if (oldType == TypeCode.Single)
                {
                    return(0x00); // nop
                }
                if (oldType == TypeCode.Double)
                {
                    return(0x90); // d2f
                }
                if (oldType == TypeCode.Int64)
                {
                    return(0x89); // l2f
                }
                if (oldType != TypeCode.UInt64)
                {
                    return(0x86); // i2f
                }
                CallUnsignedLongToDouble(code);
                code.NewInstruction(0x8D /* d2f */, null, null);
                return(-1); // no output
            }

            else if (!unsigned)
            {
                //
                // convert to double
                //

                if (oldType == TypeCode.Double)
                {
                    return(0x00); // nop
                }
                if (oldType == TypeCode.Single)
                {
                    CilMain.MakeRoomForCategory2ValueOnStack(code);
                    return(0x8D); // f2d
                }

                if (oldType == TypeCode.Int64)
                {
                    return(0x8A); // l2d
                }
                if (oldType != TypeCode.UInt64)
                {
                    return(0x87); // i2d
                }
                CallUnsignedLongToDouble(code);
                return(-1); // no output
            }

            else
            {
                //
                // convert integer, interpreted as unsigned, to a double
                //

                if (oldType == TypeCode.Single || oldType == TypeCode.Double)
                {
                    throw new InvalidProgramException();
                }

                bool fromInt32 = (oldType != TypeCode.Int64 && oldType != TypeCode.UInt64);
                if (fromInt32)
                {
                    CilMain.MakeRoomForCategory2ValueOnStack(code);

                    code.NewInstruction(0x85 /* i2l */, null, null);
                    code.StackMap.PushStack(JavaType.LongType);

                    if (oldType == TypeCode.UInt32)
                    {
                        code.NewInstruction(0x12 /* ldc */, null, (long)0xFFFFFFFF);
                        code.StackMap.PushStack(JavaType.LongType);
                        code.NewInstruction(0x7F /* land */, null, null);
                        code.StackMap.PopStack(CilMain.Where);
                    }
                }

                CallUnsignedLongToDouble(code);

                if (fromInt32)
                {
                    code.StackMap.PopStack(CilMain.Where);
                }

                return(-1); // no output
            }

            void CallUnsignedLongToDouble(JavaCode code)
            {
                code.NewInstruction(0xB8 /* invokestatic */,
                                    CilType.From(JavaType.DoubleType).AsWritableClass,
                                    new JavaMethodRef("UnsignedLongToDouble",
                                                      JavaType.DoubleType, JavaType.LongType));
            }
        }
Exemple #28
0
 public virtual void SetValueOV(JavaCode code, bool isVolatile = false)
 {
     code.NewInstruction(0xB6 /* invokevirtual */, ThisOrEnum,
                         new JavaMethodRef(VolatileName("Set", isVolatile),
                                           JavaType.VoidType, UnboxedTypeInMethod));
 }
Exemple #29
0
        public static void Indirection(JavaCode code, Code cilOp)
        {
            var(name, opcodeType) = IndirectOpCodeToNameAndType(cilOp);
            bool isRef = opcodeType.Equals(JavaType.ObjectType);

            bool isLoad;

            if (cilOp >= Code.Ldind_I1 && cilOp <= Code.Ldind_Ref)
            {
                isLoad = true;
            }
            else
            {
                isLoad = false;
                var valueType = code.StackMap.PopStack(CilMain.Where);
                if (valueType.IsReference != isRef)
                {
                    throw new InvalidProgramException();
                }
            }

            var stackTop = (CilType)code.StackMap.PopStack(CilMain.Where);

            if (stackTop.IsGenericParameter)
            {
                if (isLoad)
                {
                    var resultType = GenericUtil.CastMaybeGeneric(stackTop, false, code);
                    if (resultType == stackTop && (!stackTop.Equals(JavaType.ObjectType)))
                    {
                        code.NewInstruction(0xC0 /* checkcast */, stackTop.AsWritableClass, null);
                        resultType = stackTop;
                    }
                    code.StackMap.PushStack(resultType);
                }
                else
                {
                    code.NewInstruction(0x5F /* swap */, null, null);
                    GenericUtil.ValueCopy(stackTop, code);
                }
                return;
            }

            //
            // non-generic object reference
            //

            var boxedType = stackTop as BoxedType;

            if (boxedType == null || boxedType.IsBoxedReference != isRef)
            {
                if (CodeSpan.LoadStore(isLoad, stackTop, opcodeType, null, code))
                {
                    return;
                }

                if (object.ReferenceEquals(stackTop, CodeArrays.GenericArrayType))
                {
                    // a byref parameter T[] gets translated to java.lang.Object,
                    // so we have to explicitly cast it to system.Reference
                    boxedType = new BoxedType(stackTop, false);
                    code.NewInstruction(0x5F /* swap */, null, null);
                    code.NewInstruction(0xC0 /* checkcast */,
                                        boxedType.AsWritableClass, null);
                    code.NewInstruction(0x5F /* swap */, null, null);
                }
                else
                {
                    throw new ArgumentException($"incompatible type '{stackTop}'");
                }
            }

            var unboxedType     = boxedType.UnboxedType;
            var unboxedTypeCode = unboxedType.IsReference ? 0 : unboxedType.PrimitiveType;

            JavaMethodRef method;

            if (CompareIndirectTypes(unboxedTypeCode, opcodeType.PrimitiveType))
            {
                // indirect access to a primitive or reference type, with a
                // reference type that represents the boxed form of the same type.

                if (isLoad)
                {
                    boxedType.GetValue(code);
                    if (unboxedType.IsReference)
                    {
                        // if we know the type of indirected value, cast to it
                        if (!unboxedType.Equals(JavaType.ObjectType))
                        {
                            code.NewInstruction(0xC0 /* checkcast */,
                                                unboxedType.AsWritableClass, null);
                        }
                    }
                    else
                    {
                        unboxedType = CilType.From(opcodeType);
                    }
                    code.StackMap.PushStack(unboxedType);
                }
                else
                {
                    // if we are storing a real array into a boxed reference of
                    // e.g., system.Array, then we have to create an array proxy
                    CodeArrays.MaybeGetProxy(CodeArrays.GenericArrayType, unboxedType, code);

                    boxedType.SetValueOV(code);
                }
                return;
            }

            // indirect access to a primitive value from a reference type that
            // represents some other a primitive value;  for example ldind.r4
            // from a system.Int32.  we call the "CodeNumber.Indirection methods"
            // helpers, defined in all baselib primitives, to assist.

            if (opcodeType.IsIntLike)
            {
                opcodeType = JavaType.IntegerType;
            }
            if (isLoad)
            {
                method = new JavaMethodRef("Get_" + name, opcodeType);
                code.StackMap.PushStack(CilType.From(opcodeType));
            }
            else
            {
                method = new JavaMethodRef("Set_" + name, JavaType.VoidType, opcodeType);
            }
            code.NewInstruction(0xB6 /* invokevirtual */, boxedType, method);
        }
Exemple #30
0
 public CodeArrays(JavaCode _code, CodeLocals _locals)
 {
     locals   = _locals;
     code     = _code;
     stackMap = code.StackMap;
 }
Exemple #31
0
        public static void InitializeArray(object initialValue, JavaCode code)
        {
            //
            // the input array on the stack should be a primitive array
            //

            var array = code.StackMap.PopStack(CilMain.Where);

            int size = 0;

            switch (array.PrimitiveType)
            {
            case TypeCode.Boolean:
            case TypeCode.SByte:
            case TypeCode.Byte:   size = 1; break;

            case TypeCode.Char:
            case TypeCode.Int16:
            case TypeCode.UInt16: size = 2; break;

            case TypeCode.Single:
            case TypeCode.Int32:
            case TypeCode.UInt32: size = 4; break;

            case TypeCode.Double:
            case TypeCode.Int64:
            case TypeCode.UInt64: size = 8; break;

            default:                                                          size = 0; break;
            }
            if (size == 0 || array.ArrayRank == 0)
            {
                throw new Exception("invalid array for InitializeArray");
            }

            //
            // the initializer byte buffer should be divisible by element size
            //

            var bytes = initialValue as byte[];
            int count = 0;

            if (bytes != null && bytes.Length != 0 && (bytes.Length % size) == 0)
            {
                count = bytes.Length / size;
            }
            if (count == 0)
            {
                throw new Exception("invalid data for InitializeArray");
            }

            //
            // prepare the operand stack for as many operands as we will need
            //

            code.StackMap.PushStack(array);
            code.StackMap.PushStack(JavaType.IntegerType);
            code.StackMap.PushStack(size == 8 ? JavaType.LongType : JavaType.IntegerType);

            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);
            code.StackMap.PopStack(CilMain.Where);

            //
            // generate a sequence of instructions to initialize the array,
            // a reference to which was already pushed at the top of the stack
            //

            byte storeArrayOpcode =
                ((CilType)array).AdjustRank(-array.ArrayRank).StoreArrayOpcode;

            for (int index = 0; index < count; index++)
            {
                if (index > 0)
                {
                    code.NewInstruction(0x59 /* dup */, null, null);
                }
                code.NewInstruction(0x12 /* ldc */, null, (int)index);
                code.NewInstruction(0x12 /* ldc */, null,
                                    Value(bytes, index * size, array.PrimitiveType));
                code.NewInstruction(storeArrayOpcode, null, null);
            }

            object Value(byte[] bytes, int offset, TypeCode primitive)
            {
                switch (primitive)
                {
                case TypeCode.Boolean:
                    bool boolValue = BitConverter.ToBoolean(bytes, offset);
                    return((int)(boolValue ? 1 : 0));

                case TypeCode.SByte:
                    return((int)(((sbyte[])(object)bytes)[offset]));

                case TypeCode.Byte:
                    return((int)bytes[offset]);

                case TypeCode.Char:
                    return((int)BitConverter.ToChar(bytes, offset));

                case TypeCode.Int16:
                    return((int)BitConverter.ToInt16(bytes, offset));

                case TypeCode.UInt16:
                    return((int)BitConverter.ToUInt16(bytes, offset));

                case TypeCode.Int32:
                    return(BitConverter.ToInt32(bytes, offset));

                case TypeCode.UInt32:
                    return((int)BitConverter.ToUInt32(bytes, offset));

                case TypeCode.Int64:
                    return(BitConverter.ToInt64(bytes, offset));

                case TypeCode.UInt64:
                    return((long)BitConverter.ToUInt64(bytes, offset));

                case TypeCode.Single:
                    return(BitConverter.ToSingle(bytes, offset));

                case TypeCode.Double:
                    return(BitConverter.ToDouble(bytes, offset));

                default:
                    return(null);
                }
            }
        }
 /// <summary>
 /// Default ctor
 /// </summary>
 public JavaClass(string className, JavaCode javaCode)
 {
     this.className = className;
     this.javaCode = javaCode;
 }